Merge branch 'master' into master
This commit is contained in:
commit
f0e4f4dc9d
7
NEWS.md
7
NEWS.md
@ -11,6 +11,11 @@
|
|||||||
---
|
---
|
||||||
## (current master)
|
## (current master)
|
||||||
|
|
||||||
|
## 0.13.1
|
||||||
|
|
||||||
|
- fix a bug when passing a vector of functions with no bounds (e.g. `plot([sin, cos])`)
|
||||||
|
- export `pct` and `px` from Plots.PlotMeasures
|
||||||
|
|
||||||
## 0.13.0
|
## 0.13.0
|
||||||
|
|
||||||
- support `plotattributes` rather than `d` in recipes
|
- support `plotattributes` rather than `d` in recipes
|
||||||
@ -100,7 +105,7 @@
|
|||||||
#### 0.11.0
|
#### 0.11.0
|
||||||
|
|
||||||
- julia 0.6 compatibility
|
- julia 0.6 compatibility
|
||||||
- matplotlib 0.2.0 compatibility
|
- matplotlib 2.0 compatibility
|
||||||
- add inspectdr backend
|
- add inspectdr backend
|
||||||
- improved histogram functionality:
|
- improved histogram functionality:
|
||||||
- added a `:stephist` and `:scatterhist` series type as well as ``:barhist` (the default)
|
- added a `:stephist` and `:scatterhist` series type as well as ``:barhist` (the default)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
# Plots
|
# Plots
|
||||||
|
|
||||||
[](https://travis-ci.org/JuliaPlots/Plots.jl)
|
[](https://travis-ci.org/JuliaPlots/Plots.jl)
|
||||||
[](https://ci.appveyor.com/project/tbreloff/plots-jl)
|
[](https://ci.appveyor.com/project/mkborregaard/plots-jl)
|
||||||
[](https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
[](https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||||
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.3) -->
|
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.3) -->
|
||||||
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.4) -->
|
<!-- [](http://pkg.julialang.org/?pkg=Plots&ver=0.4) -->
|
||||||
@ -20,4 +20,4 @@ Plots is a plotting API and toolset. My goals with the package are:
|
|||||||
- **Lightweight**. Very few dependencies.
|
- **Lightweight**. Very few dependencies.
|
||||||
- **Smart**. Attempts to figure out what you **want** it to do... not just what you **tell** it.
|
- **Smart**. Attempts to figure out what you **want** it to do... not just what you **tell** it.
|
||||||
|
|
||||||
View the [full documentation](http://juliaplots.github.io).
|
View the [full documentation](http://docs.juliaplots.org/latest).
|
||||||
|
|||||||
57
src/Plots.jl
57
src/Plots.jl
@ -15,6 +15,8 @@ using Base.Meta
|
|||||||
import Showoff
|
import Showoff
|
||||||
import StatsBase
|
import StatsBase
|
||||||
|
|
||||||
|
using Requires
|
||||||
|
|
||||||
export
|
export
|
||||||
grid,
|
grid,
|
||||||
bbox,
|
bbox,
|
||||||
@ -110,13 +112,13 @@ export
|
|||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
||||||
import NaNMath # define functions that ignores NaNs. To overcome the destructive effects of https://github.com/JuliaLang/julia/pull/12563
|
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::AbstractArray{F}) where {F<:AbstractFloat} = NaNMath.minimum(x)
|
||||||
ignorenan_minimum(x) = Base.minimum(x)
|
ignorenan_minimum(x) = Base.minimum(x)
|
||||||
ignorenan_maximum{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.maximum(x)
|
ignorenan_maximum(x::AbstractArray{F}) where {F<:AbstractFloat} = NaNMath.maximum(x)
|
||||||
ignorenan_maximum(x) = Base.maximum(x)
|
ignorenan_maximum(x) = Base.maximum(x)
|
||||||
ignorenan_mean{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.mean(x)
|
ignorenan_mean(x::AbstractArray{F}) where {F<:AbstractFloat} = NaNMath.mean(x)
|
||||||
ignorenan_mean(x) = Base.mean(x)
|
ignorenan_mean(x) = Base.mean(x)
|
||||||
ignorenan_extrema{F<:AbstractFloat}(x::AbstractArray{F}) = NaNMath.extrema(x)
|
ignorenan_extrema(x::AbstractArray{F}) where {F<:AbstractFloat} = NaNMath.extrema(x)
|
||||||
ignorenan_extrema(x) = Base.extrema(x)
|
ignorenan_extrema(x) = Base.extrema(x)
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
@ -138,12 +140,15 @@ module PlotMeasures
|
|||||||
import Measures
|
import Measures
|
||||||
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h
|
import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h
|
||||||
const BBox = Measures.Absolute2DBox
|
const BBox = Measures.Absolute2DBox
|
||||||
export BBox, BoundingBox, mm, cm, inch, pt, px, pct, w, h
|
|
||||||
|
# allow pixels and percentages
|
||||||
|
const px = AbsoluteLength(0.254)
|
||||||
|
const pct = Length{:pct, Float64}(1.0)
|
||||||
|
export BBox, BoundingBox, mm, cm, inch, px, pct, pt, w, h
|
||||||
end
|
end
|
||||||
|
|
||||||
using .PlotMeasures
|
using .PlotMeasures
|
||||||
import .PlotMeasures: Length, AbsoluteLength, Measure, width, height
|
import .PlotMeasures: Length, AbsoluteLength, Measure, width, height
|
||||||
export BBox, BoundingBox
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
||||||
include("types.jl")
|
include("types.jl")
|
||||||
@ -212,13 +217,13 @@ xlabel!(s::AbstractString; kw...) = plot!(; xlabel = s, kw...)
|
|||||||
ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...)
|
ylabel!(s::AbstractString; kw...) = plot!(; ylabel = s, kw...)
|
||||||
|
|
||||||
"Set xlims for an existing plot"
|
"Set xlims for an existing plot"
|
||||||
xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; xlims = lims, kw...)
|
xlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; xlims = lims, kw...)
|
||||||
|
|
||||||
"Set ylims for an existing plot"
|
"Set ylims for an existing plot"
|
||||||
ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; ylims = lims, kw...)
|
ylims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; ylims = lims, kw...)
|
||||||
|
|
||||||
"Set zlims for an existing plot"
|
"Set zlims for an existing plot"
|
||||||
zlims!{T<:Real,S<:Real}(lims::Tuple{T,S}; kw...) = plot!(; zlims = lims, kw...)
|
zlims!(lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(; zlims = lims, kw...)
|
||||||
|
|
||||||
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...)
|
xlims!(xmin::Real, xmax::Real; kw...) = plot!(; xlims = (xmin,xmax), kw...)
|
||||||
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...)
|
ylims!(ymin::Real, ymax::Real; kw...) = plot!(; ylims = (ymin,ymax), kw...)
|
||||||
@ -226,19 +231,19 @@ zlims!(zmin::Real, zmax::Real; kw...) = plot!(; zlims = (zmi
|
|||||||
|
|
||||||
|
|
||||||
"Set xticks for an existing plot"
|
"Set xticks for an existing plot"
|
||||||
xticks!{T<:Real}(v::AVec{T}; kw...) = plot!(; xticks = v, kw...)
|
xticks!(v::AVec{T}; kw...) where {T<:Real} = plot!(; xticks = v, kw...)
|
||||||
|
|
||||||
"Set yticks for an existing plot"
|
"Set yticks for an existing plot"
|
||||||
yticks!{T<:Real}(v::AVec{T}; kw...) = plot!(; yticks = v, kw...)
|
yticks!(v::AVec{T}; kw...) where {T<:Real} = plot!(; yticks = v, kw...)
|
||||||
|
|
||||||
xticks!{T<:Real,S<:AbstractString}(
|
xticks!(
|
||||||
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; xticks = (ticks,labels), kw...)
|
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; xticks = (ticks,labels), kw...)
|
||||||
yticks!{T<:Real,S<:AbstractString}(
|
yticks!(
|
||||||
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(; yticks = (ticks,labels), kw...)
|
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(; yticks = (ticks,labels), kw...)
|
||||||
|
|
||||||
"Add annotations to an existing plot"
|
"Add annotations to an existing plot"
|
||||||
annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)
|
annotate!(anns...; kw...) = plot!(; annotation = anns, kw...)
|
||||||
annotate!{T<:Tuple}(anns::AVec{T}; kw...) = plot!(; annotation = anns, kw...)
|
annotate!(anns::AVec{T}; kw...) where {T<:Tuple} = plot!(; annotation = anns, kw...)
|
||||||
|
|
||||||
"Flip the current plots' x axis"
|
"Flip the current plots' x axis"
|
||||||
xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...)
|
xflip!(flip::Bool = true; kw...) = plot!(; xflip = flip, kw...)
|
||||||
@ -258,22 +263,22 @@ let PlotOrSubplot = Union{Plot, Subplot}
|
|||||||
title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
|
title!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; title = s, kw...)
|
||||||
xlabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; xlabel = s, kw...)
|
xlabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; xlabel = s, kw...)
|
||||||
ylabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; ylabel = s, kw...)
|
ylabel!(plt::PlotOrSubplot, s::AbstractString; kw...) = plot!(plt; ylabel = s, kw...)
|
||||||
xlims!{T<:Real,S<:Real}(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) = plot!(plt; xlims = lims, kw...)
|
xlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; xlims = lims, kw...)
|
||||||
ylims!{T<:Real,S<:Real}(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) = plot!(plt; ylims = lims, kw...)
|
ylims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; ylims = lims, kw...)
|
||||||
zlims!{T<:Real,S<:Real}(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) = plot!(plt; zlims = lims, kw...)
|
zlims!(plt::PlotOrSubplot, lims::Tuple{T,S}; kw...) where {T<:Real,S<:Real} = plot!(plt; zlims = lims, kw...)
|
||||||
xlims!(plt::PlotOrSubplot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin,xmax), kw...)
|
xlims!(plt::PlotOrSubplot, xmin::Real, xmax::Real; kw...) = plot!(plt; xlims = (xmin,xmax), kw...)
|
||||||
ylims!(plt::PlotOrSubplot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin,ymax), kw...)
|
ylims!(plt::PlotOrSubplot, ymin::Real, ymax::Real; kw...) = plot!(plt; ylims = (ymin,ymax), kw...)
|
||||||
zlims!(plt::PlotOrSubplot, zmin::Real, zmax::Real; kw...) = plot!(plt; zlims = (zmin,zmax), kw...)
|
zlims!(plt::PlotOrSubplot, zmin::Real, zmax::Real; kw...) = plot!(plt; zlims = (zmin,zmax), kw...)
|
||||||
xticks!{T<:Real}(plt::PlotOrSubplot, ticks::AVec{T}; kw...) = plot!(plt; xticks = ticks, kw...)
|
xticks!(plt::PlotOrSubplot, ticks::AVec{T}; kw...) where {T<:Real} = plot!(plt; xticks = ticks, kw...)
|
||||||
yticks!{T<:Real}(plt::PlotOrSubplot, ticks::AVec{T}; kw...) = plot!(plt; yticks = ticks, kw...)
|
yticks!(plt::PlotOrSubplot, ticks::AVec{T}; kw...) where {T<:Real} = plot!(plt; yticks = ticks, kw...)
|
||||||
xticks!{T<:Real,S<:AbstractString}(plt::PlotOrSubplot,
|
xticks!(plt::PlotOrSubplot,
|
||||||
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; xticks = (ticks,labels), kw...)
|
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; xticks = (ticks,labels), kw...)
|
||||||
yticks!{T<:Real,S<:AbstractString}(plt::PlotOrSubplot,
|
yticks!(plt::PlotOrSubplot,
|
||||||
ticks::AVec{T}, labels::AVec{S}; kw...) = plot!(plt; yticks = (ticks,labels), kw...)
|
ticks::AVec{T}, labels::AVec{S}; kw...) where {T<:Real,S<:AbstractString} = plot!(plt; yticks = (ticks,labels), kw...)
|
||||||
xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...)
|
xgrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xgrid = args, kw...)
|
||||||
ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...)
|
ygrid!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; ygrid = args, kw...)
|
||||||
annotate!(plt::PlotOrSubplot, anns...; kw...) = plot!(plt; annotation = anns, 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...)
|
annotate!(plt::PlotOrSubplot, anns::AVec{T}; kw...) where {T<:Tuple} = plot!(plt; annotation = anns, kw...)
|
||||||
xflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...)
|
xflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; xflip = flip, kw...)
|
||||||
yflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; yflip = flip, kw...)
|
yflip!(plt::PlotOrSubplot, flip::Bool = true; kw...) = plot!(plt; yflip = flip, kw...)
|
||||||
xaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xaxis = args, kw...)
|
xaxis!(plt::PlotOrSubplot, args...; kw...) = plot!(plt; xaxis = args, kw...)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
"Represents an animation object"
|
"Represents an animation object"
|
||||||
immutable Animation
|
struct Animation
|
||||||
dir::String
|
dir::String
|
||||||
frames::Vector{String}
|
frames::Vector{String}
|
||||||
end
|
end
|
||||||
@ -14,7 +14,7 @@ end
|
|||||||
|
|
||||||
Add a plot (the current plot if not specified) to an existing animation
|
Add a plot (the current plot if not specified) to an existing animation
|
||||||
"""
|
"""
|
||||||
function frame{P<:AbstractPlot}(anim::Animation, plt::P=current())
|
function frame(anim::Animation, plt::P=current()) where P<:AbstractPlot
|
||||||
i = length(anim.frames) + 1
|
i = length(anim.frames) + 1
|
||||||
filename = @sprintf("%06d.png", i)
|
filename = @sprintf("%06d.png", i)
|
||||||
png(plt, joinpath(anim.dir, filename))
|
png(plt, joinpath(anim.dir, filename))
|
||||||
@ -25,7 +25,7 @@ giffn() = (isijulia() ? "tmp.gif" : tempname()*".gif")
|
|||||||
movfn() = (isijulia() ? "tmp.mov" : tempname()*".mov")
|
movfn() = (isijulia() ? "tmp.mov" : tempname()*".mov")
|
||||||
mp4fn() = (isijulia() ? "tmp.mp4" : tempname()*".mp4")
|
mp4fn() = (isijulia() ? "tmp.mp4" : tempname()*".mp4")
|
||||||
|
|
||||||
type FrameIterator
|
mutable struct FrameIterator
|
||||||
itr
|
itr
|
||||||
every::Int
|
every::Int
|
||||||
kw
|
kw
|
||||||
@ -54,44 +54,36 @@ end
|
|||||||
# -----------------------------------------------
|
# -----------------------------------------------
|
||||||
|
|
||||||
"Wraps the location of an animated gif so that it can be displayed"
|
"Wraps the location of an animated gif so that it can be displayed"
|
||||||
immutable AnimatedGif
|
struct AnimatedGif
|
||||||
filename::String
|
filename::String
|
||||||
end
|
end
|
||||||
|
|
||||||
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
|
file_extension(fn) = Base.Filesystem.splitext(fn)[2][2:end]
|
||||||
|
|
||||||
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...)
|
gif(anim::Animation, fn = giffn(); kw...) = buildanimation(anim.dir, fn; kw...)
|
||||||
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn; kw...)
|
mov(anim::Animation, fn = movfn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
|
||||||
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, fn; kw...)
|
mp4(anim::Animation, fn = mp4fn(); kw...) = buildanimation(anim.dir, fn, false; kw...)
|
||||||
|
|
||||||
const _imagemagick_initialized = Ref(false)
|
|
||||||
|
|
||||||
function buildanimation(animdir::AbstractString, fn::AbstractString;
|
function buildanimation(animdir::AbstractString, fn::AbstractString,
|
||||||
fps::Integer = 20, loop::Integer = 0)
|
is_animated_gif::Bool=true;
|
||||||
|
fps::Integer = 20, loop::Integer = 0,
|
||||||
|
variable_palette::Bool=false)
|
||||||
fn = abspath(fn)
|
fn = abspath(fn)
|
||||||
try
|
|
||||||
if !_imagemagick_initialized[]
|
if is_animated_gif
|
||||||
file = joinpath(Pkg.dir("ImageMagick"), "deps","deps.jl")
|
if variable_palette
|
||||||
if isfile(file) && !haskey(ENV, "MAGICK_CONFIGURE_PATH")
|
# generate a colorpalette for each frame for highest quality, but larger filesize
|
||||||
include(file)
|
palette="palettegen=stats_mode=single[pal],[0:v][pal]paletteuse=new=1"
|
||||||
end
|
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -lavfi "$palette" -y $fn`)
|
||||||
_imagemagick_initialized[] = true
|
else
|
||||||
|
# generate a colorpalette first so ffmpeg does not have to guess it
|
||||||
|
run(`ffmpeg -v 0 -i $(animdir)/%06d.png -vf "palettegen=stats_mode=diff" -y "$(animdir)/palette.bmp"`)
|
||||||
|
# then apply the palette to get better results
|
||||||
|
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -i "$(animdir)/palette.bmp" -lavfi "paletteuse=dither=sierra2_4a" -y $fn`)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
# prefix = get(ENV, "MAGICK_CONFIGURE_PATH", "")
|
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -pix_fmt yuv420p -y $fn`)
|
||||||
# high quality
|
|
||||||
speed = round(Int, 100 / fps)
|
|
||||||
run(`convert -delay $speed -loop $loop $(joinpath(animdir, "*.png")) -alpha off $fn`)
|
|
||||||
|
|
||||||
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.
|
|
||||||
Will try ffmpeg, but it's lower quality...)""")
|
|
||||||
|
|
||||||
# low quality
|
|
||||||
run(`ffmpeg -v 0 -framerate $fps -loop $loop -i $(animdir)/%06d.png -y $fn`)
|
|
||||||
# run(`ffmpeg -v warning -i "fps=$fps,scale=320:-1:flags=lanczos"`)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
info("Saved animation to ", fn)
|
info("Saved animation to ", fn)
|
||||||
|
|||||||
@ -66,11 +66,17 @@ const _arg_desc = KW(
|
|||||||
:dpi => "Number. Dots Per Inch of output figures",
|
:dpi => "Number. Dots Per Inch of output figures",
|
||||||
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
|
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
|
||||||
:extra_kwargs => "KW (Dict{Symbol,Any}). Pass a map of extra keyword args which may be specific to a backend.",
|
:extra_kwargs => "KW (Dict{Symbol,Any}). Pass a map of extra keyword args which may be specific to a backend.",
|
||||||
|
:fontfamily => "String or Symbol. Default font family for title, legend entries, tick labels and guides",
|
||||||
|
|
||||||
# subplot args
|
# subplot args
|
||||||
:title => "String. Subplot title.",
|
:title => "String. Subplot title.",
|
||||||
:title_location => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`",
|
:title_location => "Symbol. Position of subplot title. Values: `:left`, `:center`, `:right`",
|
||||||
:titlefont => "Font. Font of subplot title.",
|
:titlefontfamily => "String or Symbol. Font family of subplot title.",
|
||||||
|
:titlefontsize => "Integer. Font pointsize of subplot title.",
|
||||||
|
:titlefonthalign => "Symbol. Font horizontal alignment of subplot title: :hcenter, :left, :right or :center",
|
||||||
|
:titlefontvalign => "Symbol. Font vertical alignment of subplot title: :vcenter, :top, :bottom or :center",
|
||||||
|
:titlefontrotation => "Real. Font rotation of subplot title",
|
||||||
|
:titlefontcolor => "Color Type. Font color of subplot title",
|
||||||
:background_color_subplot => "Color Type or `:match` (matches `:background_color`). Base background color of the subplot.",
|
:background_color_subplot => "Color Type or `:match` (matches `:background_color`). Base background color of the subplot.",
|
||||||
:background_color_legend => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.",
|
:background_color_legend => "Color Type or `:match` (matches `:background_color_subplot`). Background color of the legend.",
|
||||||
:background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).",
|
:background_color_inside => "Color Type or `:match` (matches `:background_color_subplot`). Background color inside the plot area (under the grid).",
|
||||||
@ -79,7 +85,12 @@ const _arg_desc = KW(
|
|||||||
:foreground_color_title => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of subplot title.",
|
: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.",
|
: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)",
|
: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)",
|
||||||
:legendtitle => "String or nothing (default). Sets the legend title.",
|
:legendfontfamily => "String or Symbol. Font family of legend entries.",
|
||||||
|
:legendfontsize => "Integer. Font pointsize of legend entries.",
|
||||||
|
:legendfonthalign => "Symbol. Font horizontal alignment of legend entries: :hcenter, :left, :right or :center",
|
||||||
|
:legendfontvalign => "Symbol. Font vertical alignment of legend entries: :vcenter, :top, :bottom or :center",
|
||||||
|
:legendfontrotation => "Real. Font rotation of legend entries",
|
||||||
|
:legendfontcolor => "Color Type. Font color of legend entries",
|
||||||
: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)",
|
: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.",
|
:clims => "`:auto` or NTuple{2,Number}. Fixes the limits of the colorbar.",
|
||||||
:legendfont => "Font. Font of legend items.",
|
:legendfont => "Font. Font of legend items.",
|
||||||
@ -94,6 +105,7 @@ const _arg_desc = KW(
|
|||||||
:subplot_index => "Integer. Internal (not set by user). Specifies the index of this subplot in the Plot's `plt.subplot` list.",
|
: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.",
|
:colorbar_title => "String. Title of colorbar.",
|
||||||
:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)",
|
:framestyle => "Symbol. Style of the axes frame. Choose from $(_allFramestyles)",
|
||||||
|
:camera => "NTuple{2, Real}. Sets the view angle (azimuthal, elevation) for 3D plots",
|
||||||
|
|
||||||
# axis args
|
# axis args
|
||||||
:guide => "String. Axis guide (label).",
|
:guide => "String. Axis guide (label).",
|
||||||
@ -103,17 +115,28 @@ const _arg_desc = KW(
|
|||||||
:rotation => "Number. Degrees rotation of tick labels.",
|
:rotation => "Number. Degrees rotation of tick labels.",
|
||||||
:flip => "Bool. Should we flip (reverse) the axis?",
|
:flip => "Bool. Should we flip (reverse) the axis?",
|
||||||
:formatter => "Function, :scientific, or :auto. A method which converts a number to a string for tick labeling.",
|
:formatter => "Function, :scientific, or :auto. A method which converts a number to a string for tick labeling.",
|
||||||
:tickfont => "Font. Font of axis tick labels.",
|
:tickfontfamily => "String or Symbol. Font family of tick labels.",
|
||||||
:guidefont => "Font. Font of axis guide (label).",
|
:tickfontsize => "Integer. Font pointsize of tick labels.",
|
||||||
|
:tickfonthalign => "Symbol. Font horizontal alignment of tick labels: :hcenter, :left, :right or :center",
|
||||||
|
:tickfontvalign => "Symbol. Font vertical alignment of tick labels: :vcenter, :top, :bottom or :center",
|
||||||
|
:tickfontrotation => "Real. Font rotation of tick labels",
|
||||||
|
:tickfontcolor => "Color Type. Font color of tick labels",
|
||||||
|
:guidefontfamily => "String or Symbol. Font family of axes guides.",
|
||||||
|
:guidefontsize => "Integer. Font pointsize of axes guides.",
|
||||||
|
:guidefonthalign => "Symbol. Font horizontal alignment of axes guides: :hcenter, :left, :right or :center",
|
||||||
|
:guidefontvalign => "Symbol. Font vertical alignment of axes guides: :vcenter, :top, :bottom or :center",
|
||||||
|
:guidefontrotation => "Real. Font rotation of axes guides",
|
||||||
|
:guidefontcolor => "Color Type. Font color of axes guides",
|
||||||
:foreground_color_axis => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis ticks.",
|
:foreground_color_axis => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of axis ticks.",
|
||||||
:foreground_color_border => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of plot area border (spines).",
|
:foreground_color_border => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of plot area border (spines).",
|
||||||
:foreground_color_text => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of tick labels.",
|
: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).",
|
: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).",
|
: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`",
|
:grid => "Bool, Symbol, String or `nothing`. Show the grid lines? `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:none`, `:off`",
|
||||||
:foreground_color_grid => "Color Type or `:match` (matches `:foreground_color_subplot`). Color of grid lines.",
|
: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.",
|
:gridalpha => "Number in [0,1]. The alpha/opacity override for the grid lines.",
|
||||||
:gridstyle => "Symbol. Style of the grid lines. Choose from $(_allStyles)",
|
:gridstyle => "Symbol. Style of the grid lines. Choose from $(_allStyles)",
|
||||||
:gridlinewidth => "Number. Width of the grid lines (in pixels)",
|
:gridlinewidth => "Number. Width of the grid lines (in pixels)",
|
||||||
:tick_direction => "Symbol. Direction of the ticks. `:in` or `:out`"
|
:tick_direction => "Symbol. Direction of the ticks. `:in` or `:out`",
|
||||||
|
:showaxis => "Bool, Symbol or String. Show the axis. `true`, `false`, `:show`, `:hide`, `:yes`, `:no`, `:x`, `:y`, `:z`, `:xy`, ..., `:all`, `:off`"
|
||||||
)
|
)
|
||||||
|
|||||||
169
src/args.jl
169
src/args.jl
@ -170,8 +170,8 @@ const _scaleAliases = Dict{Symbol,Symbol}(
|
|||||||
const _allGridSyms = [:x, :y, :z,
|
const _allGridSyms = [:x, :y, :z,
|
||||||
:xy, :xz, :yx, :yz, :zx, :zy,
|
:xy, :xz, :yx, :yz, :zx, :zy,
|
||||||
:xyz, :xzy, :yxz, :yzx, :zxy, :zyx,
|
:xyz, :xzy, :yxz, :yzx, :zxy, :zyx,
|
||||||
:all, :both, :on,
|
:all, :both, :on, :yes, :show,
|
||||||
:none, :off,]
|
:none, :off, :no, :hide]
|
||||||
const _allGridArgs = [_allGridSyms; string.(_allGridSyms); nothing]
|
const _allGridArgs = [_allGridSyms; string.(_allGridSyms); nothing]
|
||||||
hasgrid(arg::Void, letter) = false
|
hasgrid(arg::Void, letter) = false
|
||||||
hasgrid(arg::Bool, letter) = arg
|
hasgrid(arg::Bool, letter) = arg
|
||||||
@ -185,6 +185,24 @@ function hasgrid(arg::Symbol, letter)
|
|||||||
end
|
end
|
||||||
hasgrid(arg::AbstractString, letter) = hasgrid(Symbol(arg), letter)
|
hasgrid(arg::AbstractString, letter) = hasgrid(Symbol(arg), letter)
|
||||||
|
|
||||||
|
const _allShowaxisSyms = [:x, :y, :z,
|
||||||
|
:xy, :xz, :yx, :yz, :zx, :zy,
|
||||||
|
:xyz, :xzy, :yxz, :yzx, :zxy, :zyx,
|
||||||
|
:all, :both, :on, :yes, :show,
|
||||||
|
:off, :no, :hide]
|
||||||
|
const _allShowaxisArgs = [_allGridSyms; string.(_allGridSyms)]
|
||||||
|
showaxis(arg::Void, letter) = false
|
||||||
|
showaxis(arg::Bool, letter) = arg
|
||||||
|
function showaxis(arg::Symbol, letter)
|
||||||
|
if arg in _allGridSyms
|
||||||
|
arg in (:all, :both, :on, :yes) || contains(string(arg), string(letter))
|
||||||
|
else
|
||||||
|
warn("Unknown showaxis argument $arg; $(Symbol(letter, :showaxis)) was set to `true` instead.")
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
showaxis(arg::AbstractString, letter) = hasgrid(Symbol(arg), letter)
|
||||||
|
|
||||||
const _allFramestyles = [:box, :semi, :axes, :origin, :zerolines, :grid, :none]
|
const _allFramestyles = [:box, :semi, :axes, :origin, :zerolines, :grid, :none]
|
||||||
const _framestyleAliases = Dict{Symbol, Symbol}(
|
const _framestyleAliases = Dict{Symbol, Symbol}(
|
||||||
:frame => :box,
|
:frame => :box,
|
||||||
@ -255,6 +273,7 @@ const _plot_defaults = KW(
|
|||||||
:background_color => colorant"white", # default for all backgrounds,
|
:background_color => colorant"white", # default for all backgrounds,
|
||||||
:background_color_outside => :match, # background outside grid,
|
:background_color_outside => :match, # background outside grid,
|
||||||
:foreground_color => :auto, # default for all foregrounds, and title color,
|
:foreground_color => :auto, # default for all foregrounds, and title color,
|
||||||
|
:fontfamily => "sans-serif",
|
||||||
:size => (600,400),
|
:size => (600,400),
|
||||||
:pos => (0,0),
|
:pos => (0,0),
|
||||||
:window_title => "Plots.jl",
|
:window_title => "Plots.jl",
|
||||||
@ -274,7 +293,13 @@ const _plot_defaults = KW(
|
|||||||
const _subplot_defaults = KW(
|
const _subplot_defaults = KW(
|
||||||
:title => "",
|
:title => "",
|
||||||
:title_location => :center, # also :left or :right
|
:title_location => :center, # also :left or :right
|
||||||
:titlefont => font(14),
|
:fontfamily_subplot => :match,
|
||||||
|
:titlefontfamily => :match,
|
||||||
|
:titlefontsize => 14,
|
||||||
|
:titlefonthalign => :hcenter,
|
||||||
|
:titlefontvalign => :vcenter,
|
||||||
|
:titlefontrotation => 0.0,
|
||||||
|
:titlefontcolor => :match,
|
||||||
:background_color_subplot => :match, # default for other bg colors... match takes plot default
|
:background_color_subplot => :match, # default for other bg colors... match takes plot default
|
||||||
:background_color_legend => :match, # background of legend
|
:background_color_legend => :match, # background of legend
|
||||||
:background_color_inside => :match, # background inside grid
|
:background_color_inside => :match, # background inside grid
|
||||||
@ -286,7 +311,12 @@ const _subplot_defaults = KW(
|
|||||||
:legendtitle => nothing,
|
:legendtitle => nothing,
|
||||||
:colorbar => :legend,
|
:colorbar => :legend,
|
||||||
:clims => :auto,
|
:clims => :auto,
|
||||||
:legendfont => font(8),
|
:legendfontfamily => :match,
|
||||||
|
:legendfontsize => 8,
|
||||||
|
:legendfonthalign => :hcenter,
|
||||||
|
:legendfontvalign => :vcenter,
|
||||||
|
:legendfontrotation => 0.0,
|
||||||
|
:legendfontcolor => :match,
|
||||||
:annotations => [], # annotation tuples... list of (x,y,annotation)
|
:annotations => [], # annotation tuples... list of (x,y,annotation)
|
||||||
:projection => :none, # can also be :polar or :3d
|
:projection => :none, # can also be :polar or :3d
|
||||||
:aspect_ratio => :none, # choose from :none or :equal
|
:aspect_ratio => :none, # choose from :none or :equal
|
||||||
@ -298,6 +328,7 @@ const _subplot_defaults = KW(
|
|||||||
:subplot_index => -1,
|
:subplot_index => -1,
|
||||||
:colorbar_title => "",
|
:colorbar_title => "",
|
||||||
:framestyle => :axes,
|
:framestyle => :axes,
|
||||||
|
:camera => (30,30),
|
||||||
)
|
)
|
||||||
|
|
||||||
const _axis_defaults = KW(
|
const _axis_defaults = KW(
|
||||||
@ -308,8 +339,18 @@ const _axis_defaults = KW(
|
|||||||
:rotation => 0,
|
:rotation => 0,
|
||||||
:flip => false,
|
:flip => false,
|
||||||
:link => [],
|
:link => [],
|
||||||
:tickfont => font(8),
|
:tickfontfamily => :match,
|
||||||
:guidefont => font(11),
|
:tickfontsize => 8,
|
||||||
|
:tickfonthalign => :hcenter,
|
||||||
|
:tickfontvalign => :vcenter,
|
||||||
|
:tickfontrotation => 0.0,
|
||||||
|
:tickfontcolor => :match,
|
||||||
|
:guidefontfamily => :match,
|
||||||
|
:guidefontsize => 11,
|
||||||
|
:guidefonthalign => :hcenter,
|
||||||
|
:guidefontvalign => :vcenter,
|
||||||
|
:guidefontrotation => 0.0,
|
||||||
|
:guidefontcolor => :match,
|
||||||
:foreground_color_axis => :match, # axis border/tick colors,
|
:foreground_color_axis => :match, # axis border/tick colors,
|
||||||
:foreground_color_border => :match, # plot area border/spines,
|
:foreground_color_border => :match, # plot area border/spines,
|
||||||
:foreground_color_text => :match, # tick text color,
|
:foreground_color_text => :match, # tick text color,
|
||||||
@ -322,7 +363,8 @@ const _axis_defaults = KW(
|
|||||||
:gridalpha => 0.1,
|
:gridalpha => 0.1,
|
||||||
:gridstyle => :solid,
|
:gridstyle => :solid,
|
||||||
:gridlinewidth => 0.5,
|
:gridlinewidth => 0.5,
|
||||||
:tick_direction => :in,
|
:tick_direction => :in,
|
||||||
|
:showaxis => true,
|
||||||
)
|
)
|
||||||
|
|
||||||
const _suppress_warnings = Set{Symbol}([
|
const _suppress_warnings = Set{Symbol}([
|
||||||
@ -374,11 +416,13 @@ const _all_defaults = KW[
|
|||||||
_axis_defaults_byletter
|
_axis_defaults_byletter
|
||||||
]
|
]
|
||||||
|
|
||||||
|
const _initial_defaults = deepcopy(_all_defaults)
|
||||||
|
|
||||||
# to be able to reset font sizes to initial values
|
# to be able to reset font sizes to initial values
|
||||||
const _initial_fontsizes = Dict(:titlefont => _subplot_defaults[:titlefont].pointsize,
|
const _initial_fontsizes = Dict(:titlefont => _subplot_defaults[:titlefontsize],
|
||||||
:legendfont => _subplot_defaults[:legendfont].pointsize,
|
:legendfont => _subplot_defaults[:legendfontsize],
|
||||||
:tickfont => _axis_defaults[:tickfont].pointsize,
|
:tickfont => _axis_defaults[:tickfontsize],
|
||||||
:guidefont => _axis_defaults[:guidefont].pointsize)
|
:guidefont => _axis_defaults[:guidefontsize])
|
||||||
|
|
||||||
const _all_args = sort(collect(union(map(keys, _all_defaults)...)))
|
const _all_args = sort(collect(union(map(keys, _all_defaults)...)))
|
||||||
|
|
||||||
@ -513,6 +557,7 @@ add_aliases(:gridlinewidth, :gridwidth, :grid_linewidth, :grid_width, :gridlw, :
|
|||||||
add_aliases(:gridstyle, :grid_style, :gridlinestyle, :grid_linestyle, :grid_ls, :gridls)
|
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_aliases(:framestyle, :frame_style, :frame, :axesstyle, :axes_style, :boxstyle, :box_style, :box, :borderstyle, :border_style, :border)
|
||||||
add_aliases(:tick_direction, :tickdirection, :tick_dir, :tickdir, :tick_orientation, :tickorientation, :tick_or, :tickor)
|
add_aliases(:tick_direction, :tickdirection, :tick_dir, :tickdir, :tick_orientation, :tickorientation, :tick_or, :tickor)
|
||||||
|
add_aliases(:camera, :cam, :viewangle, :view_angle)
|
||||||
|
|
||||||
# add all pluralized forms to the _keyAliases dict
|
# add all pluralized forms to the _keyAliases dict
|
||||||
for arg in keys(_series_defaults)
|
for arg in keys(_series_defaults)
|
||||||
@ -569,6 +614,7 @@ function default(d::KW, k::Symbol)
|
|||||||
get(d, k, default(k))
|
get(d, k, default(k))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
reset_defaults() = foreach(merge!, _all_defaults, _initial_defaults)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -671,6 +717,9 @@ function processFillArg(d::KW, arg)
|
|||||||
arg.color == nothing || (d[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
|
arg.color == nothing || (d[:fillcolor] = arg.color == :auto ? :auto : plot_color(arg.color))
|
||||||
arg.alpha == nothing || (d[:fillalpha] = arg.alpha)
|
arg.alpha == nothing || (d[:fillalpha] = arg.alpha)
|
||||||
|
|
||||||
|
elseif typeof(arg) <: Bool
|
||||||
|
d[:fillrange] = arg ? 0 : nothing
|
||||||
|
|
||||||
# fillrange function
|
# fillrange function
|
||||||
elseif allFunctions(arg)
|
elseif allFunctions(arg)
|
||||||
d[:fillrange] = arg
|
d[:fillrange] = arg
|
||||||
@ -710,12 +759,44 @@ function processGridArg!(d::KW, arg, letter)
|
|||||||
d[Symbol(letter, :gridlinewidth)] = arg
|
d[Symbol(letter, :gridlinewidth)] = arg
|
||||||
|
|
||||||
# color
|
# color
|
||||||
elseif !handleColors!(d, arg, Symbol(letter, :foreground_color_grid))
|
elseif !handleColors!(d, arg, Symbol(letter, :foreground_color_grid))
|
||||||
warn("Skipped grid arg $arg.")
|
warn("Skipped grid arg $arg.")
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function processFontArg!(d::KW, fontname::Symbol, arg)
|
||||||
|
T = typeof(arg)
|
||||||
|
if T <: Font
|
||||||
|
d[Symbol(fontname, :family)] = arg.family
|
||||||
|
d[Symbol(fontname, :size)] = arg.pointsize
|
||||||
|
d[Symbol(fontname, :halign)] = arg.halign
|
||||||
|
d[Symbol(fontname, :valign)] = arg.valign
|
||||||
|
d[Symbol(fontname, :rotation)] = arg.rotation
|
||||||
|
d[Symbol(fontname, :color)] = arg.color
|
||||||
|
elseif arg == :center
|
||||||
|
d[Symbol(fontname, :halign)] = :hcenter
|
||||||
|
d[Symbol(fontname, :valign)] = :vcenter
|
||||||
|
elseif arg in (:hcenter, :left, :right)
|
||||||
|
d[Symbol(fontname, :halign)] = arg
|
||||||
|
elseif arg in (:vcenter, :top, :bottom)
|
||||||
|
d[Symbol(fontname, :valign)] = arg
|
||||||
|
elseif T <: Colorant
|
||||||
|
d[Symbol(fontname, :color)] = arg
|
||||||
|
elseif T <: Symbol || T <: AbstractString
|
||||||
|
try
|
||||||
|
d[Symbol(fontname, :color)] = parse(Colorant, string(arg))
|
||||||
|
catch
|
||||||
|
d[Symbol(fontname, :family)] = string(arg)
|
||||||
|
end
|
||||||
|
elseif typeof(arg) <: Integer
|
||||||
|
d[Symbol(fontname, :size)] = arg
|
||||||
|
elseif typeof(arg) <: Real
|
||||||
|
d[Symbol(fontname, :rotation)] = convert(Float64, arg)
|
||||||
|
else
|
||||||
|
warn("Skipped font arg: $arg ($(typeof(arg)))")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
_replace_markershape(shape::Symbol) = get(_markerAliases, shape, shape)
|
_replace_markershape(shape::Symbol) = get(_markerAliases, shape, shape)
|
||||||
_replace_markershape(shapes::AVec) = map(_replace_markershape, shapes)
|
_replace_markershape(shapes::AVec) = map(_replace_markershape, shapes)
|
||||||
@ -735,13 +816,13 @@ function preprocessArgs!(d::KW)
|
|||||||
replaceAliases!(d, _keyAliases)
|
replaceAliases!(d, _keyAliases)
|
||||||
|
|
||||||
# clear all axis stuff
|
# clear all axis stuff
|
||||||
if haskey(d, :axis) && d[:axis] in (:none, nothing, false)
|
# if haskey(d, :axis) && d[:axis] in (:none, nothing, false)
|
||||||
d[:ticks] = nothing
|
# d[:ticks] = nothing
|
||||||
d[:foreground_color_border] = RGBA(0,0,0,0)
|
# d[:foreground_color_border] = RGBA(0,0,0,0)
|
||||||
d[:foreground_color_axis] = RGBA(0,0,0,0)
|
# d[:foreground_color_axis] = RGBA(0,0,0,0)
|
||||||
d[:grid] = false
|
# d[:grid] = false
|
||||||
delete!(d, :axis)
|
# delete!(d, :axis)
|
||||||
end
|
# end
|
||||||
# for letter in (:x, :y, :z)
|
# for letter in (:x, :y, :z)
|
||||||
# asym = Symbol(letter, :axis)
|
# asym = Symbol(letter, :axis)
|
||||||
# if haskey(d, asym) || d[asym] in (:none, nothing, false)
|
# if haskey(d, asym) || d[asym] in (:none, nothing, false)
|
||||||
@ -750,6 +831,13 @@ function preprocessArgs!(d::KW)
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
|
|
||||||
|
# handle axis args common to all axis
|
||||||
|
args = pop!(d, :axis, ())
|
||||||
|
for arg in wraptuple(args)
|
||||||
|
for letter in (:x, :y, :z)
|
||||||
|
process_axis_arg!(d, arg, letter)
|
||||||
|
end
|
||||||
|
end
|
||||||
# handle axis args
|
# handle axis args
|
||||||
for letter in (:x, :y, :z)
|
for letter in (:x, :y, :z)
|
||||||
asym = Symbol(letter, :axis)
|
asym = Symbol(letter, :axis)
|
||||||
@ -777,6 +865,32 @@ function preprocessArgs!(d::KW)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# fonts
|
||||||
|
for fontname in (:titlefont, :legendfont)
|
||||||
|
args = pop!(d, fontname, ())
|
||||||
|
for arg in wraptuple(args)
|
||||||
|
processFontArg!(d, fontname, arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# handle font args common to all axes
|
||||||
|
for fontname in (:tickfont, :guidefont)
|
||||||
|
args = pop!(d, fontname, ())
|
||||||
|
for arg in wraptuple(args)
|
||||||
|
for letter in (:x, :y, :z)
|
||||||
|
processFontArg!(d, Symbol(letter, fontname), arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
# handle individual axes font args
|
||||||
|
for letter in (:x, :y, :z)
|
||||||
|
for fontname in (:tickfont, :guidefont)
|
||||||
|
args = pop!(d, Symbol(letter, fontname), ())
|
||||||
|
for arg in wraptuple(args)
|
||||||
|
processFontArg!(d, Symbol(letter, fontname), arg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# handle line args
|
# handle line args
|
||||||
for arg in wraptuple(pop!(d, :line, ()))
|
for arg in wraptuple(pop!(d, :line, ()))
|
||||||
processLineArg(d, arg)
|
processLineArg(d, arg)
|
||||||
@ -858,7 +972,7 @@ end
|
|||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
"A special type that will break up incoming data into groups, and allow for easier creation of grouped plots"
|
"A special type that will break up incoming data into groups, and allow for easier creation of grouped plots"
|
||||||
type GroupBy
|
mutable struct GroupBy
|
||||||
groupLabels::Vector # length == numGroups
|
groupLabels::Vector # length == numGroups
|
||||||
groupIds::Vector{Vector{Int}} # list of indices for each group
|
groupIds::Vector{Vector{Int}} # list of indices for each group
|
||||||
end
|
end
|
||||||
@ -885,7 +999,7 @@ function extractGroupArgs(vs::Tuple, args...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# expecting a mapping of "group label" to "group indices"
|
# expecting a mapping of "group label" to "group indices"
|
||||||
function extractGroupArgs{T, V<:AVec{Int}}(idxmap::Dict{T,V}, args...)
|
function extractGroupArgs(idxmap::Dict{T,V}, args...) where {T, V<:AVec{Int}}
|
||||||
groupLabels = sortedkeys(idxmap)
|
groupLabels = sortedkeys(idxmap)
|
||||||
groupIds = Vector{Int}[collect(idxmap[k]) for k in groupLabels]
|
groupIds = Vector{Int}[collect(idxmap[k]) for k in groupLabels]
|
||||||
GroupBy(groupLabels, groupIds)
|
GroupBy(groupLabels, groupIds)
|
||||||
@ -968,7 +1082,7 @@ function convertLegendValue(val::Symbol)
|
|||||||
:best
|
:best
|
||||||
elseif val in (:no, :none)
|
elseif val in (:no, :none)
|
||||||
:none
|
:none
|
||||||
elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright)
|
elseif val in (:right, :left, :top, :bottom, :inside, :best, :legend, :topright, :topleft, :bottomleft, :bottomright, :outertopright)
|
||||||
val
|
val
|
||||||
else
|
else
|
||||||
error("Invalid symbol for legend: $val")
|
error("Invalid symbol for legend: $val")
|
||||||
@ -976,7 +1090,7 @@ function convertLegendValue(val::Symbol)
|
|||||||
end
|
end
|
||||||
convertLegendValue(val::Bool) = val ? :best : :none
|
convertLegendValue(val::Bool) = val ? :best : :none
|
||||||
convertLegendValue(val::Void) = :none
|
convertLegendValue(val::Void) = :none
|
||||||
convertLegendValue{S<:Real, T<:Real}(v::Tuple{S,T}) = v
|
convertLegendValue(v::Tuple{S,T}) where {S<:Real, T<:Real} = v
|
||||||
convertLegendValue(v::AbstractArray) = map(convertLegendValue, v)
|
convertLegendValue(v::AbstractArray) = map(convertLegendValue, v)
|
||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@ -1050,6 +1164,12 @@ const _match_map = KW(
|
|||||||
:top_margin => :margin,
|
:top_margin => :margin,
|
||||||
:right_margin => :margin,
|
:right_margin => :margin,
|
||||||
:bottom_margin => :margin,
|
:bottom_margin => :margin,
|
||||||
|
:titlefontfamily => :fontfamily_subplot,
|
||||||
|
:legendfontfamily => :fontfamily_subplot,
|
||||||
|
:titlefontcolor => :foreground_color_subplot,
|
||||||
|
:legendfontcolor => :foreground_color_subplot,
|
||||||
|
:tickfontcolor => :foreground_color_text,
|
||||||
|
:guidefontcolor => :foreground_color_guide,
|
||||||
)
|
)
|
||||||
|
|
||||||
# these can match values from the parent container (axis --> subplot --> plot)
|
# these can match values from the parent container (axis --> subplot --> plot)
|
||||||
@ -1061,6 +1181,9 @@ const _match_map2 = KW(
|
|||||||
:foreground_color_grid => :foreground_color_subplot,
|
:foreground_color_grid => :foreground_color_subplot,
|
||||||
:foreground_color_guide => :foreground_color_subplot,
|
:foreground_color_guide => :foreground_color_subplot,
|
||||||
:foreground_color_text => :foreground_color_subplot,
|
:foreground_color_text => :foreground_color_subplot,
|
||||||
|
:fontfamily_subplot => :fontfamily,
|
||||||
|
:tickfontfamily => :fontfamily_subplot,
|
||||||
|
:guidefontfamily => :fontfamily_subplot,
|
||||||
)
|
)
|
||||||
|
|
||||||
# properly retrieve from plt.attr, passing `:match` to the correct key
|
# properly retrieve from plt.attr, passing `:match` to the correct key
|
||||||
|
|||||||
114
src/axes.jl
114
src/axes.jl
@ -70,13 +70,16 @@ function process_axis_arg!(d::KW, arg, letter = "")
|
|||||||
elseif arg == nothing
|
elseif arg == nothing
|
||||||
d[Symbol(letter,:ticks)] = []
|
d[Symbol(letter,:ticks)] = []
|
||||||
|
|
||||||
|
elseif T <: Bool || arg in _allShowaxisArgs
|
||||||
|
d[Symbol(letter,:showaxis)] = showaxis(arg, letter)
|
||||||
|
|
||||||
elseif typeof(arg) <: Number
|
elseif typeof(arg) <: Number
|
||||||
d[Symbol(letter,:rotation)] = arg
|
d[Symbol(letter,:rotation)] = arg
|
||||||
|
|
||||||
elseif typeof(arg) <: Function
|
elseif typeof(arg) <: Function
|
||||||
d[Symbol(letter,:formatter)] = arg
|
d[Symbol(letter,:formatter)] = arg
|
||||||
|
|
||||||
else
|
elseif !handleColors!(d, arg, Symbol(letter, :foreground_color_axis))
|
||||||
warn("Skipped $(letter)axis arg $arg")
|
warn("Skipped $(letter)axis arg $arg")
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -236,8 +239,13 @@ function get_ticks(axis::Axis)
|
|||||||
# discrete ticks...
|
# discrete ticks...
|
||||||
axis[:continuous_values], dvals
|
axis[:continuous_values], dvals
|
||||||
elseif ticks == :auto
|
elseif ticks == :auto
|
||||||
# compute optimal ticks and labels
|
if ispolar(axis.sps[1]) && axis[:letter] == :x
|
||||||
optimal_ticks_and_labels(axis)
|
#force theta axis to be full circle
|
||||||
|
(collect(0:pi/4:7pi/4), string.(0:45:315))
|
||||||
|
else
|
||||||
|
# compute optimal ticks and labels
|
||||||
|
optimal_ticks_and_labels(axis)
|
||||||
|
end
|
||||||
elseif typeof(ticks) <: Union{AVec, Int}
|
elseif typeof(ticks) <: Union{AVec, Int}
|
||||||
# override ticks, but get the labels
|
# override ticks, but get the labels
|
||||||
optimal_ticks_and_labels(axis, ticks)
|
optimal_ticks_and_labels(axis, ticks)
|
||||||
@ -290,13 +298,13 @@ expand_extrema!(axis::Axis, ::Void) = axis[:extrema]
|
|||||||
expand_extrema!(axis::Axis, ::Bool) = axis[:extrema]
|
expand_extrema!(axis::Axis, ::Bool) = axis[:extrema]
|
||||||
|
|
||||||
|
|
||||||
function expand_extrema!{MIN<:Number,MAX<:Number}(axis::Axis, v::Tuple{MIN,MAX})
|
function expand_extrema!(axis::Axis, v::Tuple{MIN,MAX}) where {MIN<:Number,MAX<:Number}
|
||||||
ex = axis[:extrema]
|
ex = axis[:extrema]
|
||||||
ex.emin = NaNMath.min(v[1], ex.emin)
|
ex.emin = NaNMath.min(v[1], ex.emin)
|
||||||
ex.emax = NaNMath.max(v[2], ex.emax)
|
ex.emax = NaNMath.max(v[2], ex.emax)
|
||||||
ex
|
ex
|
||||||
end
|
end
|
||||||
function expand_extrema!{N<:Number}(axis::Axis, v::AVec{N})
|
function expand_extrema!(axis::Axis, v::AVec{N}) where N<:Number
|
||||||
ex = axis[:extrema]
|
ex = axis[:extrema]
|
||||||
for vi in v
|
for vi in v
|
||||||
expand_extrema!(ex, vi)
|
expand_extrema!(ex, vi)
|
||||||
@ -347,7 +355,7 @@ function expand_extrema!(sp::Subplot, d::KW)
|
|||||||
if fr == nothing && d[:seriestype] == :bar
|
if fr == nothing && d[:seriestype] == :bar
|
||||||
fr = 0.0
|
fr = 0.0
|
||||||
end
|
end
|
||||||
if fr != nothing
|
if fr != nothing && !all3D(d)
|
||||||
axis = sp.attr[vert ? :yaxis : :xaxis]
|
axis = sp.attr[vert ? :yaxis : :xaxis]
|
||||||
if typeof(fr) <: Tuple
|
if typeof(fr) <: Tuple
|
||||||
for fri in fr
|
for fri in fr
|
||||||
@ -372,6 +380,15 @@ function expand_extrema!(sp::Subplot, d::KW)
|
|||||||
expand_extrema!(axis, ignorenan_minimum(data) - 0.5minimum(bw))
|
expand_extrema!(axis, ignorenan_minimum(data) - 0.5minimum(bw))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# expand for heatmaps
|
||||||
|
if d[:seriestype] == :heatmap
|
||||||
|
for letter in (:x, :y)
|
||||||
|
data = d[letter]
|
||||||
|
axis = sp[Symbol(letter, "axis")]
|
||||||
|
scale = get(d, Symbol(letter, "scale"), :identity)
|
||||||
|
expand_extrema!(axis, heatmap_edges(data, scale))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function expand_extrema!(sp::Subplot, xmin, xmax, ymin, ymax)
|
function expand_extrema!(sp::Subplot, xmin, xmax, ymin, ymax)
|
||||||
@ -424,7 +441,16 @@ function axis_limits(axis::Axis, should_widen::Bool = default_should_widen(axis)
|
|||||||
if !isfinite(amin) && !isfinite(amax)
|
if !isfinite(amin) && !isfinite(amax)
|
||||||
amin, amax = 0.0, 1.0
|
amin, amax = 0.0, 1.0
|
||||||
end
|
end
|
||||||
if should_widen
|
if ispolar(axis.sps[1])
|
||||||
|
if axis[:letter] == :x
|
||||||
|
amin, amax = 0, 2pi
|
||||||
|
elseif lims == :auto
|
||||||
|
#widen max radius so ticks dont overlap with theta axis
|
||||||
|
amin, amax + 0.1 * abs(amax - amin)
|
||||||
|
else
|
||||||
|
amin, amax
|
||||||
|
end
|
||||||
|
elseif should_widen
|
||||||
widen(amin, amax)
|
widen(amin, amax)
|
||||||
else
|
else
|
||||||
amin, amax
|
amin, amax
|
||||||
@ -515,18 +541,24 @@ function axis_drawing_info(sp::Subplot)
|
|||||||
xborder_segs = Segments(2)
|
xborder_segs = Segments(2)
|
||||||
yborder_segs = Segments(2)
|
yborder_segs = Segments(2)
|
||||||
|
|
||||||
if !(sp[:framestyle] == :none)
|
if sp[:framestyle] != :none
|
||||||
# xaxis
|
# xaxis
|
||||||
sp[:framestyle] in (:grid, :origin, :zerolines) || push!(xaxis_segs, (xmin,ymin), (xmax,ymin)) # bottom spine / xaxis
|
if xaxis[:showaxis]
|
||||||
if sp[:framestyle] in (:origin, :zerolines)
|
if sp[:framestyle] != :grid
|
||||||
push!(xaxis_segs, (xmin, 0.0), (xmax, 0.0))
|
y1, y2 = if sp[:framestyle] in (:origin, :zerolines)
|
||||||
# don't show the 0 tick label for the origin framestyle
|
0.0, 0.0
|
||||||
if sp[:framestyle] == :origin && length(xticks) > 1
|
else
|
||||||
showticks = xticks[1] .!= 0
|
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, ymin) : (ymin, ymax)
|
||||||
xticks = (xticks[1][showticks], xticks[2][showticks])
|
end
|
||||||
|
push!(xaxis_segs, (xmin, y1), (xmax, y1))
|
||||||
|
# don't show the 0 tick label for the origin framestyle
|
||||||
|
if sp[:framestyle] == :origin && length(xticks) > 1
|
||||||
|
showticks = xticks[1] .!= 0
|
||||||
|
xticks = (xticks[1][showticks], xticks[2][showticks])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin, y2), (xmax, y2)) # top spine
|
||||||
end
|
end
|
||||||
sp[:framestyle] in (:semi, :box) && push!(xborder_segs, (xmin,ymax), (xmax,ymax)) # top spine
|
|
||||||
if !(xaxis[:ticks] in (nothing, false))
|
if !(xaxis[:ticks] in (nothing, false))
|
||||||
f = scalefunc(yaxis[:scale])
|
f = scalefunc(yaxis[:scale])
|
||||||
invf = invscalefunc(yaxis[:scale])
|
invf = invscalefunc(yaxis[:scale])
|
||||||
@ -536,28 +568,36 @@ function axis_drawing_info(sp::Subplot)
|
|||||||
t3 = invf(f(0) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
|
t3 = invf(f(0) + 0.015 * (f(ymax) - f(ymin)) * ticks_in)
|
||||||
|
|
||||||
for xtick in xticks[1]
|
for xtick in xticks[1]
|
||||||
tick_start, tick_stop = if sp[:framestyle] == :origin
|
if xaxis[:showaxis]
|
||||||
(0, t3)
|
tick_start, tick_stop = if sp[:framestyle] == :origin
|
||||||
else
|
(0, t3)
|
||||||
xaxis[:mirror] ? (ymax, t2) : (ymin, t1)
|
else
|
||||||
|
xor(xaxis[:mirror], yaxis[:flip]) ? (ymax, t2) : (ymin, t1)
|
||||||
|
end
|
||||||
|
push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
|
||||||
end
|
end
|
||||||
push!(xtick_segs, (xtick, tick_start), (xtick, tick_stop)) # bottom tick
|
|
||||||
# sp[:draw_axes_border] && push!(xaxis_segs, (xtick, ymax), (xtick, t2)) # top 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
|
xaxis[:grid] && push!(xgrid_segs, (xtick, ymin), (xtick, ymax)) # vertical grid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# yaxis
|
# yaxis
|
||||||
sp[:framestyle] in (:grid, :origin, :zerolines) || push!(yaxis_segs, (xmin,ymin), (xmin,ymax)) # left spine / yaxis
|
if yaxis[:showaxis]
|
||||||
if sp[:framestyle] in (:origin, :zerolines)
|
if sp[:framestyle] != :grid
|
||||||
push!(yaxis_segs, (0.0, ymin), (0.0, ymax))
|
x1, x2 = if sp[:framestyle] in (:origin, :zerolines)
|
||||||
# don't show the 0 tick label for the origin framestyle
|
0.0, 0.0
|
||||||
if sp[:framestyle] == :origin && length(yticks) > 1
|
else
|
||||||
showticks = yticks[1] .!= 0
|
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, xmin) : (xmin, xmax)
|
||||||
yticks = (yticks[1][showticks], yticks[2][showticks])
|
end
|
||||||
|
push!(yaxis_segs, (x1, ymin), (x1, ymax))
|
||||||
|
# don't show the 0 tick label for the origin framestyle
|
||||||
|
if sp[:framestyle] == :origin && length(yticks) > 1
|
||||||
|
showticks = yticks[1] .!= 0
|
||||||
|
yticks = (yticks[1][showticks], yticks[2][showticks])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (x2, ymin), (x2, ymax)) # right spine
|
||||||
end
|
end
|
||||||
sp[:framestyle] in (:semi, :box) && push!(yborder_segs, (xmax,ymin), (xmax,ymax)) # right spine
|
|
||||||
if !(yaxis[:ticks] in (nothing, false))
|
if !(yaxis[:ticks] in (nothing, false))
|
||||||
f = scalefunc(xaxis[:scale])
|
f = scalefunc(xaxis[:scale])
|
||||||
invf = invscalefunc(xaxis[:scale])
|
invf = invscalefunc(xaxis[:scale])
|
||||||
@ -567,14 +607,16 @@ function axis_drawing_info(sp::Subplot)
|
|||||||
t3 = invf(f(0) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
|
t3 = invf(f(0) + 0.015 * (f(xmax) - f(xmin)) * ticks_in)
|
||||||
|
|
||||||
for ytick in yticks[1]
|
for ytick in yticks[1]
|
||||||
tick_start, tick_stop = if sp[:framestyle] == :origin
|
if yaxis[:showaxis]
|
||||||
(0, t3)
|
tick_start, tick_stop = if sp[:framestyle] == :origin
|
||||||
else
|
(0, t3)
|
||||||
yaxis[:mirror] ? (xmax, t2) : (xmin, t1)
|
else
|
||||||
|
xor(yaxis[:mirror], xaxis[:flip]) ? (xmax, t2) : (xmin, t1)
|
||||||
|
end
|
||||||
|
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
|
||||||
end
|
end
|
||||||
push!(ytick_segs, (tick_start, ytick), (tick_stop, ytick)) # left tick
|
|
||||||
# sp[:draw_axes_border] && push!(yaxis_segs, (xmax, ytick), (t2, ytick)) # right 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
|
yaxis[:grid] && push!(ygrid_segs, (xmin, ytick), (xmax, ytick)) # horizontal grid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
immutable NoBackend <: AbstractBackend end
|
struct NoBackend <: AbstractBackend end
|
||||||
|
|
||||||
const _backendType = Dict{Symbol, DataType}(:none => NoBackend)
|
const _backendType = Dict{Symbol, DataType}(:none => NoBackend)
|
||||||
const _backendSymbol = Dict{DataType, Symbol}(NoBackend => :none)
|
const _backendSymbol = Dict{DataType, Symbol}(NoBackend => :none)
|
||||||
@ -18,7 +18,7 @@ macro init_backend(s)
|
|||||||
sym = Symbol(str)
|
sym = Symbol(str)
|
||||||
T = Symbol(string(s) * "Backend")
|
T = Symbol(string(s) * "Backend")
|
||||||
esc(quote
|
esc(quote
|
||||||
immutable $T <: AbstractBackend end
|
struct $T <: AbstractBackend end
|
||||||
export $sym
|
export $sym
|
||||||
$sym(; kw...) = (default(; kw...); backend(Symbol($str)))
|
$sym(; kw...) = (default(; kw...); backend(Symbol($str)))
|
||||||
backend_name(::$T) = Symbol($str)
|
backend_name(::$T) = Symbol($str)
|
||||||
@ -51,8 +51,8 @@ _series_updated(plt::Plot, series::Series) = nothing
|
|||||||
|
|
||||||
_before_layout_calcs(plt::Plot) = nothing
|
_before_layout_calcs(plt::Plot) = nothing
|
||||||
|
|
||||||
title_padding(sp::Subplot) = sp[:title] == "" ? 0mm : sp[:titlefont].pointsize * pt
|
title_padding(sp::Subplot) = sp[:title] == "" ? 0mm : sp[:titlefontsize] * pt
|
||||||
guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefont].pointsize * pt
|
guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefontsize] * pt
|
||||||
|
|
||||||
"Returns the (width,height) of a text label."
|
"Returns the (width,height) of a text label."
|
||||||
function text_size(lablen::Int, sz::Number, rot::Number = 0)
|
function text_size(lablen::Int, sz::Number, rot::Number = 0)
|
||||||
@ -93,7 +93,7 @@ function tick_padding(axis::Axis)
|
|||||||
# hgt
|
# hgt
|
||||||
|
|
||||||
# get the height of the rotated label
|
# get the height of the rotated label
|
||||||
text_size(longest_label, axis[:tickfont].pointsize, rot)[2]
|
text_size(longest_label, axis[:tickfontsize], rot)[2]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ _update_plot_object(plt::Plot) = nothing
|
|||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
type CurrentBackend
|
mutable struct CurrentBackend
|
||||||
sym::Symbol
|
sym::Symbol
|
||||||
pkg::AbstractBackend
|
pkg::AbstractBackend
|
||||||
end
|
end
|
||||||
|
|||||||
@ -9,6 +9,10 @@ TODO
|
|||||||
* fix units in all visuals (e.g dotted lines, marker scale, surfaces)
|
* fix units in all visuals (e.g dotted lines, marker scale, surfaces)
|
||||||
=#
|
=#
|
||||||
|
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "glvisualize.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
const _glvisualize_attr = merge_with_base_supported([
|
const _glvisualize_attr = merge_with_base_supported([
|
||||||
:annotations,
|
:annotations,
|
||||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||||
@ -20,10 +24,13 @@ const _glvisualize_attr = merge_with_base_supported([
|
|||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
|
||||||
:fillrange, :fillcolor, :fillalpha,
|
:fillrange, :fillcolor, :fillalpha,
|
||||||
:bins, :bar_width, :bar_edges, :bar_position,
|
:bins, :bar_width, :bar_edges, :bar_position,
|
||||||
:title, :title_location, :titlefont,
|
:title, :title_location,
|
||||||
:window_title,
|
:window_title,
|
||||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
:tickfont, :guidefont, :legendfont,
|
:titlefontsize, :titlefontcolor,
|
||||||
|
:legendfontsize, :legendfontcolor,
|
||||||
|
:tickfontsize,
|
||||||
|
:guidefontsize, :guidefontcolor,
|
||||||
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
||||||
:legend, :colorbar,
|
:legend, :colorbar,
|
||||||
:marker_z,
|
:marker_z,
|
||||||
@ -69,9 +76,9 @@ function _initialize_backend(::GLVisualizeBackend; kw...)
|
|||||||
import GLVisualize: visualize
|
import GLVisualize: visualize
|
||||||
import Plots.GL
|
import Plots.GL
|
||||||
import UnicodeFun
|
import UnicodeFun
|
||||||
Plots.slice_arg{C<:Colorant}(img::Matrix{C}, idx::Int) = img
|
Plots.slice_arg(img::Matrix{C}, idx::Int) where {C<:Colorant} = img
|
||||||
is_marker_supported(::GLVisualizeBackend, shape::GLVisualize.AllPrimitives) = true
|
is_marker_supported(::GLVisualizeBackend, shape::GLVisualize.AllPrimitives) = true
|
||||||
is_marker_supported{C<:Colorant}(::GLVisualizeBackend, shape::Union{Vector{Matrix{C}}, Matrix{C}}) = true
|
is_marker_supported(::GLVisualizeBackend, shape::Union{Vector{Matrix{C}}, Matrix{C}}) where {C<:Colorant} = true
|
||||||
is_marker_supported(::GLVisualizeBackend, shape::Shape) = true
|
is_marker_supported(::GLVisualizeBackend, shape::Shape) = true
|
||||||
const GL = Plots
|
const GL = Plots
|
||||||
end
|
end
|
||||||
@ -214,13 +221,13 @@ function extract_limits(sp, d, kw_args)
|
|||||||
nothing
|
nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
to_vec{T <: StaticArrays.StaticVector}(::Type{T}, vec::T) = vec
|
to_vec(::Type{T}, vec::T) where {T <: StaticArrays.StaticVector} = vec
|
||||||
to_vec{T <: StaticArrays.StaticVector}(::Type{T}, s::Number) = T(s)
|
to_vec(::Type{T}, s::Number) where {T <: StaticArrays.StaticVector} = T(s)
|
||||||
|
|
||||||
to_vec{T <: StaticArrays.StaticVector{2}}(::Type{T}, vec::StaticArrays.StaticVector{3}) = T(vec[1], vec[2])
|
to_vec(::Type{T}, vec::StaticArrays.StaticVector{3}) where {T <: StaticArrays.StaticVector{2}} = 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(::Type{T}, vec::StaticArrays.StaticVector{2}) where {T <: StaticArrays.StaticVector{3}} = T(vec[1], vec[2], 0)
|
||||||
|
|
||||||
to_vec{T <: StaticArrays.StaticVector}(::Type{T}, vecs::AbstractVector) = map(x-> to_vec(T, x), vecs)
|
to_vec(::Type{T}, vecs::AbstractVector) where {T <: StaticArrays.StaticVector} = map(x-> to_vec(T, x), vecs)
|
||||||
|
|
||||||
function extract_marker(d, kw_args)
|
function extract_marker(d, kw_args)
|
||||||
dim = Plots.is3d(d) ? 3 : 2
|
dim = Plots.is3d(d) ? 3 : 2
|
||||||
@ -275,7 +282,7 @@ end
|
|||||||
function extract_surface(d)
|
function extract_surface(d)
|
||||||
map(_extract_surface, (d[:x], d[:y], d[:z]))
|
map(_extract_surface, (d[:x], d[:y], d[:z]))
|
||||||
end
|
end
|
||||||
function topoints{P}(::Type{P}, array)
|
function topoints(::Type{P}, array) where P
|
||||||
[P(x) for x in zip(array...)]
|
[P(x) for x in zip(array...)]
|
||||||
end
|
end
|
||||||
function extract_points(d)
|
function extract_points(d)
|
||||||
@ -283,7 +290,7 @@ function extract_points(d)
|
|||||||
array = (d[:x], d[:y], d[:z])[1:dim]
|
array = (d[:x], d[:y], d[:z])[1:dim]
|
||||||
topoints(Point{dim, Float32}, array)
|
topoints(Point{dim, Float32}, array)
|
||||||
end
|
end
|
||||||
function make_gradient{C <: Colorant}(grad::Vector{C})
|
function make_gradient(grad::Vector{C}) where C <: Colorant
|
||||||
grad
|
grad
|
||||||
end
|
end
|
||||||
function make_gradient(grad::ColorGradient)
|
function make_gradient(grad::ColorGradient)
|
||||||
@ -338,7 +345,7 @@ function extract_color(d, sym)
|
|||||||
end
|
end
|
||||||
|
|
||||||
gl_color(c::PlotUtils.ColorGradient) = c.colors
|
gl_color(c::PlotUtils.ColorGradient) = c.colors
|
||||||
gl_color{T<:Colorant}(c::Vector{T}) = c
|
gl_color(c::Vector{T}) where {T<:Colorant} = c
|
||||||
gl_color(c::RGBA{Float32}) = c
|
gl_color(c::RGBA{Float32}) = c
|
||||||
gl_color(c::Colorant) = RGBA{Float32}(c)
|
gl_color(c::Colorant) = RGBA{Float32}(c)
|
||||||
|
|
||||||
@ -608,7 +615,7 @@ function draw_ticks(
|
|||||||
axis, ticks, isx, isorigin, lims, m, text = "",
|
axis, ticks, isx, isorigin, lims, m, text = "",
|
||||||
positions = Point2f0[], offsets=Vec2f0[]
|
positions = Point2f0[], offsets=Vec2f0[]
|
||||||
)
|
)
|
||||||
sz = pointsize(axis[:tickfont])
|
sz = pointsize(tickfont(axis))
|
||||||
atlas = GLVisualize.get_texture_atlas()
|
atlas = GLVisualize.get_texture_atlas()
|
||||||
font = GLVisualize.defaultfont()
|
font = GLVisualize.defaultfont()
|
||||||
|
|
||||||
@ -732,21 +739,31 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
|
|||||||
xlim = Plots.axis_limits(xaxis)
|
xlim = Plots.axis_limits(xaxis)
|
||||||
ylim = Plots.axis_limits(yaxis)
|
ylim = Plots.axis_limits(yaxis)
|
||||||
|
|
||||||
if !(xaxis[:ticks] in (nothing, false, :none)) && !(sp[:framestyle] == :none)
|
if !(xaxis[:ticks] in (nothing, false, :none)) && !(sp[:framestyle] == :none) && xaxis[:showaxis]
|
||||||
ticklabels = map(model) do m
|
ticklabels = map(model) do m
|
||||||
mirror = xaxis[:mirror]
|
mirror = xaxis[:mirror]
|
||||||
t, positions, offsets = draw_ticks(xaxis, xticks, true, sp[:framestyle] == :origin, ylim, m)
|
t, positions, offsets = draw_ticks(xaxis, xticks, true, sp[:framestyle] == :origin, ylim, m)
|
||||||
mirror = xaxis[:mirror]
|
|
||||||
t, positions, offsets = draw_ticks(
|
|
||||||
yaxis, yticks, false, sp[:framestyle] == :origin, xlim, m,
|
|
||||||
t, positions, offsets
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
kw_args = Dict{Symbol, Any}(
|
kw_args = Dict{Symbol, Any}(
|
||||||
:position => map(x-> x[2], ticklabels),
|
:position => map(x-> x[2], ticklabels),
|
||||||
:offset => map(last, ticklabels),
|
:offset => map(last, ticklabels),
|
||||||
:color => fcolor,
|
:color => fcolor,
|
||||||
:relative_scale => pointsize(xaxis[:tickfont]),
|
:relative_scale => pointsize(tickfont(xaxis)),
|
||||||
|
:scale_primitive => false
|
||||||
|
)
|
||||||
|
push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args))
|
||||||
|
end
|
||||||
|
|
||||||
|
if !(yaxis[:ticks] in (nothing, false, :none)) && !(sp[:framestyle] == :none) && yaxis[:showaxis]
|
||||||
|
ticklabels = map(model) do m
|
||||||
|
mirror = yaxis[:mirror]
|
||||||
|
t, positions, offsets = draw_ticks(yaxis, yticks, false, sp[:framestyle] == :origin, xlim, m)
|
||||||
|
end
|
||||||
|
kw_args = Dict{Symbol, Any}(
|
||||||
|
:position => map(x-> x[2], ticklabels),
|
||||||
|
:offset => map(last, ticklabels),
|
||||||
|
:color => fcolor,
|
||||||
|
:relative_scale => pointsize(tickfont(xaxis)),
|
||||||
:scale_primitive => false
|
:scale_primitive => false
|
||||||
)
|
)
|
||||||
push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args))
|
push!(axis_vis, visualize(map(first, ticklabels), Style(:default), kw_args))
|
||||||
@ -763,8 +780,8 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
|
|||||||
|
|
||||||
area_w = GeometryTypes.widths(area)
|
area_w = GeometryTypes.widths(area)
|
||||||
if sp[:title] != ""
|
if sp[:title] != ""
|
||||||
tf = sp[:titlefont]; color = gl_color(sp[:foreground_color_title])
|
tf = titlefont(sp)
|
||||||
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, tf.rotation, color)
|
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, tf.rotation, tf.color)
|
||||||
xy = Point2f0(area.w/2, area_w[2] + pointsize(tf)/2)
|
xy = Point2f0(area.w/2, area_w[2] + pointsize(tf)/2)
|
||||||
kw = Dict(:model => text_model(font, xy), :scale_primitive => true)
|
kw = Dict(:model => text_model(font, xy), :scale_primitive => true)
|
||||||
extract_font(font, kw)
|
extract_font(font, kw)
|
||||||
@ -772,9 +789,9 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
|
|||||||
push!(axis_vis, glvisualize_text(xy, t, kw))
|
push!(axis_vis, glvisualize_text(xy, t, kw))
|
||||||
end
|
end
|
||||||
if xaxis[:guide] != ""
|
if xaxis[:guide] != ""
|
||||||
tf = xaxis[:guidefont]; color = gl_color(xaxis[:foreground_color_guide])
|
tf = guidefont(xaxis)
|
||||||
xy = Point2f0(area.w/2, - pointsize(tf)/2)
|
xy = Point2f0(area.w/2, - pointsize(tf)/2)
|
||||||
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :bottom, tf.rotation, color)
|
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :bottom, tf.rotation, tf.color)
|
||||||
kw = Dict(:model => text_model(font, xy), :scale_primitive => true)
|
kw = Dict(:model => text_model(font, xy), :scale_primitive => true)
|
||||||
t = PlotText(xaxis[:guide], font)
|
t = PlotText(xaxis[:guide], font)
|
||||||
extract_font(font, kw)
|
extract_font(font, kw)
|
||||||
@ -782,8 +799,8 @@ function gl_draw_axes_2d(sp::Plots.Subplot{Plots.GLVisualizeBackend}, model, are
|
|||||||
end
|
end
|
||||||
|
|
||||||
if yaxis[:guide] != ""
|
if yaxis[:guide] != ""
|
||||||
tf = yaxis[:guidefont]; color = gl_color(yaxis[:foreground_color_guide])
|
tf = guidefont(yaxis)
|
||||||
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, 90f0, color)
|
font = Plots.Font(tf.family, tf.pointsize, :hcenter, :top, 90f0, tf.color)
|
||||||
xy = Point2f0(-pointsize(tf)/2, area.h/2)
|
xy = Point2f0(-pointsize(tf)/2, area.h/2)
|
||||||
kw = Dict(:model => text_model(font, xy), :scale_primitive=>true)
|
kw = Dict(:model => text_model(font, xy), :scale_primitive=>true)
|
||||||
t = PlotText(yaxis[:guide], font)
|
t = PlotText(yaxis[:guide], font)
|
||||||
@ -1202,7 +1219,7 @@ function gl_image(img, kw_args)
|
|||||||
visualize(img, Style(:default), kw_args)
|
visualize(img, Style(:default), kw_args)
|
||||||
end
|
end
|
||||||
|
|
||||||
function handle_segment{P}(lines, line_segments, points::Vector{P}, segment)
|
function handle_segment(lines, line_segments, points::Vector{P}, segment) where P
|
||||||
(isempty(segment) || length(segment) < 2) && return
|
(isempty(segment) || length(segment) < 2) && return
|
||||||
if length(segment) == 2
|
if length(segment) == 2
|
||||||
append!(line_segments, view(points, segment))
|
append!(line_segments, view(points, segment))
|
||||||
@ -1469,9 +1486,8 @@ function make_label(sp, series, i)
|
|||||||
else
|
else
|
||||||
series[:label]
|
series[:label]
|
||||||
end
|
end
|
||||||
color = sp[:foreground_color_legend]
|
ft = legendfont(sp)
|
||||||
ft = sp[:legendfont]
|
font = Plots.Font(ft.family, ft.pointsize, :left, :bottom, 0.0, ft.color)
|
||||||
font = Plots.Font(ft.family, ft.pointsize, :left, :bottom, 0.0, color)
|
|
||||||
xy = Point2f0(w+gap, 0.0)
|
xy = Point2f0(w+gap, 0.0)
|
||||||
kw = Dict(:model => text_model(font, xy), :scale_primitive=>false)
|
kw = Dict(:model => text_model(font, xy), :scale_primitive=>false)
|
||||||
extract_font(font, kw)
|
extract_font(font, kw)
|
||||||
|
|||||||
@ -3,6 +3,9 @@
|
|||||||
|
|
||||||
# significant contributions by @jheinen
|
# significant contributions by @jheinen
|
||||||
|
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "gr.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
const _gr_attr = merge_with_base_supported([
|
const _gr_attr = merge_with_base_supported([
|
||||||
:annotations,
|
:annotations,
|
||||||
@ -19,7 +22,14 @@ const _gr_attr = merge_with_base_supported([
|
|||||||
:layout,
|
:layout,
|
||||||
:title, :window_title,
|
:title, :window_title,
|
||||||
:guide, :lims, :ticks, :scale, :flip,
|
:guide, :lims, :ticks, :scale, :flip,
|
||||||
:tickfont, :guidefont, :legendfont,
|
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
|
||||||
|
:titlefontrotation, :titlefontcolor,
|
||||||
|
:legendfontfamily, :legendfontsize, :legendfonthalign, :legendfontvalign,
|
||||||
|
:legendfontrotation, :legendfontcolor,
|
||||||
|
:tickfontfamily, :tickfontsize, :tickfonthalign, :tickfontvalign,
|
||||||
|
:tickfontrotation, :tickfontcolor,
|
||||||
|
:guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign,
|
||||||
|
:guidefontrotation, :guidefontcolor,
|
||||||
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
||||||
:legend, :legendtitle, :colorbar,
|
:legend, :legendtitle, :colorbar,
|
||||||
:fill_z, :line_z, :marker_z, :levels,
|
:fill_z, :line_z, :marker_z, :levels,
|
||||||
@ -34,6 +44,7 @@ const _gr_attr = merge_with_base_supported([
|
|||||||
:arrow,
|
:arrow,
|
||||||
:framestyle,
|
:framestyle,
|
||||||
:tick_direction,
|
:tick_direction,
|
||||||
|
:camera,
|
||||||
])
|
])
|
||||||
const _gr_seriestype = [
|
const _gr_seriestype = [
|
||||||
:path, :scatter,
|
:path, :scatter,
|
||||||
@ -201,35 +212,62 @@ function gr_text(x, y, s)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function gr_polaraxes(rmin, rmax)
|
function gr_polaraxes(rmin::Real, rmax::Real, sp::Subplot)
|
||||||
GR.savestate()
|
GR.savestate()
|
||||||
GR.setlinetype(GR.LINETYPE_SOLID)
|
xaxis = sp[:xaxis]
|
||||||
GR.setlinecolorind(88)
|
yaxis = sp[:yaxis]
|
||||||
tick = 0.5 * GR.tick(rmin, rmax)
|
|
||||||
n = round(Int, (rmax - rmin) / tick + 0.5)
|
α = 0:45:315
|
||||||
for i in 0:n
|
a = α .+ 90
|
||||||
r = float(i) / n
|
sinf = sind.(a)
|
||||||
if i % 2 == 0
|
cosf = cosd.(a)
|
||||||
GR.setlinecolorind(88)
|
rtick_values, rtick_labels = get_ticks(yaxis)
|
||||||
if i > 0
|
|
||||||
GR.drawarc(-r, r, -r, r, 0, 359)
|
#draw angular grid
|
||||||
end
|
if xaxis[:grid]
|
||||||
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
|
gr_set_line(xaxis[:gridlinewidth], xaxis[:gridstyle], xaxis[:foreground_color_grid])
|
||||||
x, y = GR.wctondc(0.05, r)
|
GR.settransparency(xaxis[:gridalpha])
|
||||||
GR.text(x, y, string(signif(rmin + i * tick, 12)))
|
for i in 1:length(α)
|
||||||
else
|
GR.polyline([sinf[i], 0], [cosf[i], 0])
|
||||||
GR.setlinecolorind(90)
|
|
||||||
GR.drawarc(-r, r, -r, r, 0, 359)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for α in 0:45:315
|
|
||||||
a = α + 90
|
#draw radial grid
|
||||||
sinf = sin(a * pi / 180)
|
if yaxis[:grid]
|
||||||
cosf = cos(a * pi / 180)
|
gr_set_line(yaxis[:gridlinewidth], yaxis[:gridstyle], yaxis[:foreground_color_grid])
|
||||||
GR.polyline([sinf, 0], [cosf, 0])
|
GR.settransparency(yaxis[:gridalpha])
|
||||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
|
for i in 1:length(rtick_values)
|
||||||
x, y = GR.wctondc(1.1 * sinf, 1.1 * cosf)
|
r = (rtick_values[i] - rmin) / (rmax - rmin)
|
||||||
GR.textext(x, y, string(α, "^o"))
|
if r <= 1.0 && r >= 0.0
|
||||||
|
GR.drawarc(-r, r, -r, r, 0, 359)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
GR.drawarc(-1, 1, -1, 1, 0, 359)
|
||||||
|
end
|
||||||
|
|
||||||
|
#prepare to draw ticks
|
||||||
|
GR.settransparency(1)
|
||||||
|
GR.setlinecolorind(90)
|
||||||
|
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
|
||||||
|
|
||||||
|
#draw angular ticks
|
||||||
|
if xaxis[:showaxis]
|
||||||
|
GR.drawarc(-1, 1, -1, 1, 0, 359)
|
||||||
|
for i in 1:length(α)
|
||||||
|
x, y = GR.wctondc(1.1 * sinf[i], 1.1 * cosf[i])
|
||||||
|
GR.textext(x, y, string((360-α[i])%360, "^o"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#draw radial ticks
|
||||||
|
if yaxis[:showaxis]
|
||||||
|
for i in 1:length(rtick_values)
|
||||||
|
r = (rtick_values[i] - rmin) / (rmax - rmin)
|
||||||
|
if r <= 1.0 && r >= 0.0
|
||||||
|
x, y = GR.wctondc(0.05, r)
|
||||||
|
gr_text(x, y, _cycle(rtick_labels, i))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
GR.restorestate()
|
GR.restorestate()
|
||||||
end
|
end
|
||||||
@ -342,10 +380,6 @@ function gr_draw_markers(series::Series, x, y, clims)
|
|||||||
mz = normalize_zvals(series[:marker_z], clims)
|
mz = normalize_zvals(series[:marker_z], clims)
|
||||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||||
gr_draw_markers(series, x, y, series[:markersize], mz)
|
gr_draw_markers(series, x, y, series[:markersize], mz)
|
||||||
if hascolorbar(series[:subplot])
|
|
||||||
GR.setscale(0)
|
|
||||||
gr_colorbar(series[:subplot], clims)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# ---------------------------------------------------------
|
# ---------------------------------------------------------
|
||||||
@ -412,6 +446,9 @@ function gr_viewport_from_bbox(sp::Subplot{GRBackend}, bb::BoundingBox, w, h, vi
|
|||||||
viewport[3] = 0.5 * (vp[3] + vp[4] - extent)
|
viewport[3] = 0.5 * (vp[3] + vp[4] - extent)
|
||||||
viewport[4] = 0.5 * (vp[3] + vp[4] + extent)
|
viewport[4] = 0.5 * (vp[3] + vp[4] + extent)
|
||||||
end
|
end
|
||||||
|
if hascolorbar(sp)
|
||||||
|
viewport[2] -= 0.1
|
||||||
|
end
|
||||||
viewport
|
viewport
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -447,17 +484,12 @@ function gr_set_viewport_polar()
|
|||||||
end
|
end
|
||||||
|
|
||||||
# add the colorbar
|
# add the colorbar
|
||||||
function gr_colorbar(sp::Subplot)
|
|
||||||
gr_set_viewport_cmap(sp)
|
|
||||||
GR.colorbar()
|
|
||||||
gr_set_viewport_plotarea()
|
|
||||||
end
|
|
||||||
|
|
||||||
function gr_colorbar(sp::Subplot, clims)
|
function gr_colorbar(sp::Subplot, clims)
|
||||||
xmin, xmax = gr_xy_axislims(sp)[1:2]
|
xmin, xmax = gr_xy_axislims(sp)[1:2]
|
||||||
gr_set_viewport_cmap(sp)
|
gr_set_viewport_cmap(sp)
|
||||||
l = zeros(Int32, 1, 256)
|
l = zeros(Int32, 1, 256)
|
||||||
l[1,:] = Int[round(Int, _i) for _i in linspace(1000, 1255, 256)]
|
l[1,:] = Int[round(Int, _i) for _i in linspace(1000, 1255, 256)]
|
||||||
|
GR.setscale(0)
|
||||||
GR.setwindow(xmin, xmax, clims[1], clims[2])
|
GR.setwindow(xmin, xmax, clims[1], clims[2])
|
||||||
GR.cellarray(xmin, xmax, clims[2], clims[1], 1, length(l), l)
|
GR.cellarray(xmin, xmax, clims[2], clims[1], 1, length(l), l)
|
||||||
ztick = 0.5 * GR.tick(clims[1], clims[2])
|
ztick = 0.5 * GR.tick(clims[1], clims[2])
|
||||||
@ -490,7 +522,7 @@ function gr_legend_pos(s::Symbol,w,h)
|
|||||||
(xpos,ypos)
|
(xpos,ypos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function gr_legend_pos{S<:Real, T<:Real}(v::Tuple{S,T},w,h)
|
function gr_legend_pos(v::Tuple{S,T},w,h) where {S<:Real, T<:Real}
|
||||||
xpos = v[1] * (viewport_plotarea[2] - viewport_plotarea[1]) + viewport_plotarea[1]
|
xpos = v[1] * (viewport_plotarea[2] - viewport_plotarea[1]) + viewport_plotarea[1]
|
||||||
ypos = v[2] * (viewport_plotarea[4] - viewport_plotarea[3]) + viewport_plotarea[3]
|
ypos = v[2] * (viewport_plotarea[4] - viewport_plotarea[3]) + viewport_plotarea[3]
|
||||||
(xpos,ypos)
|
(xpos,ypos)
|
||||||
@ -558,10 +590,9 @@ end
|
|||||||
function gr_set_xticks_font(sp)
|
function gr_set_xticks_font(sp)
|
||||||
flip = sp[:yaxis][:flip]
|
flip = sp[:yaxis][:flip]
|
||||||
mirror = sp[:xaxis][:mirror]
|
mirror = sp[:xaxis][:mirror]
|
||||||
gr_set_font(sp[:xaxis][:tickfont],
|
gr_set_font(tickfont(sp[:xaxis]),
|
||||||
halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2],
|
halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2],
|
||||||
valign = (mirror ? :bottom : :top),
|
valign = (mirror ? :bottom : :top),
|
||||||
color = sp[:xaxis][:foreground_color_axis],
|
|
||||||
rotation = sp[:xaxis][:rotation])
|
rotation = sp[:xaxis][:rotation])
|
||||||
return flip, mirror
|
return flip, mirror
|
||||||
end
|
end
|
||||||
@ -570,10 +601,9 @@ end
|
|||||||
function gr_set_yticks_font(sp)
|
function gr_set_yticks_font(sp)
|
||||||
flip = sp[:xaxis][:flip]
|
flip = sp[:xaxis][:flip]
|
||||||
mirror = sp[:yaxis][:mirror]
|
mirror = sp[:yaxis][:mirror]
|
||||||
gr_set_font(sp[:yaxis][:tickfont],
|
gr_set_font(tickfont(sp[:yaxis]),
|
||||||
halign = (mirror ? :left : :right),
|
halign = (mirror ? :left : :right),
|
||||||
valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2],
|
valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2],
|
||||||
color = sp[:yaxis][:foreground_color_axis],
|
|
||||||
rotation = sp[:yaxis][:rotation])
|
rotation = sp[:yaxis][:rotation])
|
||||||
return flip, mirror
|
return flip, mirror
|
||||||
end
|
end
|
||||||
@ -692,11 +722,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if cmap
|
|
||||||
# note: add extra midpadding on the right for the colorbar
|
|
||||||
viewport_plotarea[2] -= 0.1
|
|
||||||
end
|
|
||||||
|
|
||||||
# set our plot area view
|
# set our plot area view
|
||||||
gr_set_viewport_plotarea()
|
gr_set_viewport_plotarea()
|
||||||
|
|
||||||
@ -739,8 +764,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# draw the axes
|
# draw the axes
|
||||||
gr_set_font(xaxis[:tickfont])
|
gr_set_font(tickfont(xaxis))
|
||||||
gr_set_textcolor(xaxis[:foreground_color_text])
|
|
||||||
GR.setlinewidth(1)
|
GR.setlinewidth(1)
|
||||||
|
|
||||||
if is3d(sp)
|
if is3d(sp)
|
||||||
@ -750,7 +774,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
isfinite(clims[1]) && (zmin = clims[1])
|
isfinite(clims[1]) && (zmin = clims[1])
|
||||||
isfinite(clims[2]) && (zmax = clims[2])
|
isfinite(clims[2]) && (zmax = clims[2])
|
||||||
end
|
end
|
||||||
GR.setspace(zmin, zmax, 35, 60)
|
GR.setspace(zmin, zmax, round.(Int, sp[:camera])...)
|
||||||
xtick = GR.tick(xmin, xmax) / 2
|
xtick = GR.tick(xmin, xmax) / 2
|
||||||
ytick = GR.tick(ymin, ymax) / 2
|
ytick = GR.tick(ymin, ymax) / 2
|
||||||
ztick = GR.tick(zmin, zmax) / 2
|
ztick = GR.tick(zmin, zmax) / 2
|
||||||
@ -765,9 +789,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
|
|
||||||
elseif ispolar(sp)
|
elseif ispolar(sp)
|
||||||
r = gr_set_viewport_polar()
|
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])
|
rmin, rmax = axis_limits(sp[:yaxis])
|
||||||
gr_polaraxes(rmin, rmax)
|
gr_polaraxes(rmin, rmax, sp)
|
||||||
|
|
||||||
elseif draw_axes
|
elseif draw_axes
|
||||||
if xmax > xmin && ymax > ymin
|
if xmax > xmin && ymax > ymin
|
||||||
@ -793,35 +817,43 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
GR.settransparency(1.0)
|
GR.settransparency(1.0)
|
||||||
|
|
||||||
# axis lines
|
# axis lines
|
||||||
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
|
if xaxis[:showaxis]
|
||||||
GR.setclip(0)
|
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
|
||||||
gr_polyline(coords(xspine_segs)...)
|
GR.setclip(0)
|
||||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
gr_polyline(coords(xspine_segs)...)
|
||||||
GR.setclip(0)
|
end
|
||||||
gr_polyline(coords(yspine_segs)...)
|
if yaxis[:showaxis]
|
||||||
|
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
||||||
|
GR.setclip(0)
|
||||||
|
gr_polyline(coords(yspine_segs)...)
|
||||||
|
end
|
||||||
GR.setclip(1)
|
GR.setclip(1)
|
||||||
|
|
||||||
# axis ticks
|
# axis ticks
|
||||||
if sp[:framestyle] in (:zerolines, :grid)
|
if xaxis[:showaxis]
|
||||||
gr_set_line(1, :solid, xaxis[:foreground_color_grid])
|
if sp[:framestyle] in (:zerolines, :grid)
|
||||||
GR.settransparency(xaxis[:gridalpha])
|
gr_set_line(1, :solid, xaxis[:foreground_color_grid])
|
||||||
else
|
GR.settransparency(xaxis[:gridalpha])
|
||||||
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
|
else
|
||||||
|
gr_set_line(1, :solid, xaxis[:foreground_color_axis])
|
||||||
|
end
|
||||||
|
GR.setclip(0)
|
||||||
|
gr_polyline(coords(xtick_segs)...)
|
||||||
end
|
end
|
||||||
GR.setclip(0)
|
if yaxis[:showaxis]
|
||||||
gr_polyline(coords(xtick_segs)...)
|
if sp[:framestyle] in (:zerolines, :grid)
|
||||||
if sp[:framestyle] in (:zerolines, :grid)
|
gr_set_line(1, :solid, yaxis[:foreground_color_grid])
|
||||||
gr_set_line(1, :solid, yaxis[:foreground_color_grid])
|
GR.settransparency(yaxis[:gridalpha])
|
||||||
GR.settransparency(yaxis[:gridalpha])
|
else
|
||||||
else
|
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
||||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
end
|
||||||
|
GR.setclip(0)
|
||||||
|
gr_polyline(coords(ytick_segs)...)
|
||||||
end
|
end
|
||||||
GR.setclip(0)
|
|
||||||
gr_polyline(coords(ytick_segs)...)
|
|
||||||
GR.setclip(1)
|
GR.setclip(1)
|
||||||
|
|
||||||
# tick marks
|
# tick marks
|
||||||
if !(xticks in (:none, nothing, false))
|
if !(xticks in (:none, nothing, false)) && xaxis[:showaxis]
|
||||||
# x labels
|
# x labels
|
||||||
flip, mirror = gr_set_xticks_font(sp)
|
flip, mirror = gr_set_xticks_font(sp)
|
||||||
for (cv, dv) in zip(xticks...)
|
for (cv, dv) in zip(xticks...)
|
||||||
@ -832,7 +864,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if !(yticks in (:none, nothing, false))
|
if !(yticks in (:none, nothing, false)) && yaxis[:showaxis]
|
||||||
# y labels
|
# y labels
|
||||||
flip, mirror = gr_set_yticks_font(sp)
|
flip, mirror = gr_set_yticks_font(sp)
|
||||||
for (cv, dv) in zip(yticks...)
|
for (cv, dv) in zip(yticks...)
|
||||||
@ -859,29 +891,37 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
# add the guides
|
# add the guides
|
||||||
GR.savestate()
|
GR.savestate()
|
||||||
if sp[:title] != ""
|
if sp[:title] != ""
|
||||||
gr_set_font(sp[:titlefont])
|
gr_set_font(titlefont(sp))
|
||||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
loc = sp[:title_location]
|
||||||
gr_set_textcolor(sp[:foreground_color_title])
|
if loc == :left
|
||||||
gr_text(gr_view_xcenter(), viewport_subplot[4], sp[:title])
|
xpos = viewport_plotarea[1]
|
||||||
|
halign = GR.TEXT_HALIGN_LEFT
|
||||||
|
elseif loc == :right
|
||||||
|
xpos = viewport_plotarea[2]
|
||||||
|
halign = GR.TEXT_HALIGN_RIGHT
|
||||||
|
else
|
||||||
|
xpos = gr_view_xcenter()
|
||||||
|
halign = GR.TEXT_HALIGN_CENTER
|
||||||
|
end
|
||||||
|
GR.settextalign(halign, GR.TEXT_VALIGN_TOP)
|
||||||
|
gr_text(xpos, viewport_subplot[4], sp[:title])
|
||||||
end
|
end
|
||||||
|
|
||||||
if xaxis[:guide] != ""
|
if xaxis[:guide] != ""
|
||||||
gr_set_font(xaxis[:guidefont])
|
gr_set_font(guidefont(xaxis))
|
||||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||||
gr_set_textcolor(xaxis[:foreground_color_guide])
|
|
||||||
gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide])
|
gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide])
|
||||||
end
|
end
|
||||||
|
|
||||||
if yaxis[:guide] != ""
|
if yaxis[:guide] != ""
|
||||||
gr_set_font(yaxis[:guidefont])
|
gr_set_font(guidefont(yaxis))
|
||||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||||
GR.setcharup(-1, 0)
|
GR.setcharup(-1, 0)
|
||||||
gr_set_textcolor(yaxis[:foreground_color_guide])
|
|
||||||
gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide])
|
gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide])
|
||||||
end
|
end
|
||||||
GR.restorestate()
|
GR.restorestate()
|
||||||
|
|
||||||
gr_set_font(xaxis[:tickfont])
|
gr_set_font(tickfont(xaxis))
|
||||||
|
|
||||||
# this needs to be here to point the colormap to the right indices
|
# this needs to be here to point the colormap to the right indices
|
||||||
GR.setcolormap(1000 + GR.COLORMAP_COOLWARM)
|
GR.setcolormap(1000 + GR.COLORMAP_COOLWARM)
|
||||||
@ -935,33 +975,32 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
|
|
||||||
if st in (:path, :scatter)
|
if st in (:path, :scatter)
|
||||||
if length(x) > 1
|
if length(x) > 1
|
||||||
|
lz = series[:line_z]
|
||||||
|
segments_iterator = if lz != nothing && length(lz) > 1
|
||||||
|
[i:(i + 1) for i in 1:(length(x) - 1)]
|
||||||
|
else
|
||||||
|
iter_segments(x, y)
|
||||||
|
end
|
||||||
# do area fill
|
# do area fill
|
||||||
if frng != nothing
|
if frng != nothing
|
||||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||||
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
|
fr_from, fr_to = (is_2tuple(frng) ? frng : (y, frng))
|
||||||
for i in 1:length(x) - 1
|
for (i, rng) in enumerate(segments_iterator)
|
||||||
gr_set_fillcolor(get_fillcolor(sp, series, i))
|
gr_set_fillcolor(get_fillcolor(sp, series, i))
|
||||||
xseg = _cycle(x, [i, i+1, i+1, i])
|
fx = _cycle(x, vcat(rng, reverse(rng)))
|
||||||
yseg = [_cycle(fr_from, [i, i+1]); _cycle(fr_to, [i+1, i])]
|
fy = vcat(_cycle(fr_from,rng), _cycle(fr_to,reverse(rng)))
|
||||||
series[:fillalpha] != nothing && GR.settransparency(series[:fillalpha])
|
series[:fillalpha] != nothing && GR.settransparency(series[:fillalpha])
|
||||||
GR.fillarea(xseg, yseg)
|
GR.fillarea(fx, fy)
|
||||||
end
|
end
|
||||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
|
||||||
GR.settransparency(1)
|
|
||||||
cmap && gr_colorbar(sp, clims)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# draw the line(s)
|
# draw the line(s)
|
||||||
if st == :path
|
if st == :path
|
||||||
for i in 1:length(x) - 1
|
for (i, rng) in enumerate(segments_iterator)
|
||||||
xseg = x[i:(i + 1)]
|
|
||||||
yseg = y[i:(i + 1)]
|
|
||||||
gr_set_line(series[:linewidth], series[:linestyle], get_linecolor(sp, series, i)) #, series[:linealpha])
|
gr_set_line(series[:linewidth], series[:linestyle], get_linecolor(sp, series, i)) #, series[:linealpha])
|
||||||
arrowside = (i == length(y) - 1) && isa(series[:arrow], Arrow) ? series[:arrow].side : :none
|
arrowside = isa(series[:arrow], Arrow) ? series[:arrow].side : :none
|
||||||
gr_polyline(xseg, yseg; arrowside = arrowside)
|
gr_polyline(x[rng], y[rng]; arrowside = arrowside)
|
||||||
end
|
end
|
||||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
|
||||||
cmap && gr_colorbar(sp, clims)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -984,11 +1023,14 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
if series[:fillrange] != nothing
|
if series[:fillrange] != nothing
|
||||||
GR.surface(x, y, z, GR.OPTION_CELL_ARRAY)
|
GR.surface(x, y, z, GR.OPTION_CELL_ARRAY)
|
||||||
else
|
else
|
||||||
|
GR.setlinetype(gr_linetype[series[:linestyle]])
|
||||||
|
GR.setlinewidth(max(0, series[:linewidth] / (sum(gr_plot_size) * 0.001)))
|
||||||
GR.contour(x, y, h, z, 1000)
|
GR.contour(x, y, h, z, 1000)
|
||||||
end
|
end
|
||||||
|
|
||||||
# create the colorbar of contour levels
|
# create the colorbar of contour levels
|
||||||
if cmap
|
if cmap
|
||||||
|
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
||||||
gr_set_viewport_cmap(sp)
|
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.setwindow(xmin, xmax, zmin, zmax)
|
||||||
@ -1009,7 +1051,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
GR.setfillcolorind(0)
|
GR.setfillcolorind(0)
|
||||||
GR.surface(x, y, z, GR.OPTION_FILLED_MESH)
|
GR.surface(x, y, z, GR.OPTION_FILLED_MESH)
|
||||||
end
|
end
|
||||||
cmap && gr_colorbar(sp)
|
|
||||||
|
|
||||||
elseif st == :heatmap
|
elseif st == :heatmap
|
||||||
xmin, xmax, ymin, ymax = xy_lims
|
xmin, xmax, ymin, ymax = xy_lims
|
||||||
@ -1023,20 +1064,22 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
round(Int, red(c) * 255) ), colors)
|
round(Int, red(c) * 255) ), colors)
|
||||||
w, h = length(x), length(y)
|
w, h = length(x), length(y)
|
||||||
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
|
GR.drawimage(xmin, xmax, ymax, ymin, w, h, rgba)
|
||||||
cmap && gr_colorbar(sp, clims)
|
|
||||||
|
|
||||||
elseif st in (:path3d, :scatter3d)
|
elseif st in (:path3d, :scatter3d)
|
||||||
# draw path
|
# draw path
|
||||||
if st == :path3d
|
if st == :path3d
|
||||||
for i in 1:length(x) - 1
|
if length(x) > 1
|
||||||
xseg = x[i:(i + 1)]
|
lz = series[:line_z]
|
||||||
yseg = y[i:(i + 1)]
|
segments_iterator = if lz != nothing && length(lz) > 1
|
||||||
zseg = z[i:(i + 1)]
|
[i:(i + 1) for i in 1:(length(x) - 1)]
|
||||||
gr_set_line(series[:linewidth], series[:linestyle], get_linecolor(sp, series, i)) #, series[:linealpha])
|
else
|
||||||
GR.polyline3d(xseg, yseg, zseg)
|
iter_segments(x, y, z)
|
||||||
|
end
|
||||||
|
for (i, rng) in enumerate(segments_iterator)
|
||||||
|
gr_set_line(series[:linewidth], series[:linestyle], get_linecolor(sp, series, i)) #, series[:linealpha])
|
||||||
|
GR.polyline3d(x[rng], y[rng], z[rng])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
|
||||||
cmap && gr_colorbar(sp, clims)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# draw markers
|
# draw markers
|
||||||
@ -1111,8 +1154,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
GR.polyline(xseg, yseg)
|
GR.polyline(xseg, yseg)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
|
||||||
cmap && gr_colorbar(sp, clims)
|
|
||||||
|
|
||||||
|
|
||||||
elseif st == :image
|
elseif st == :image
|
||||||
@ -1137,6 +1178,13 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
gr_text(GR.wctondc(xi, yi)..., str)
|
gr_text(GR.wctondc(xi, yi)..., str)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# draw the colorbar
|
||||||
|
if cmap && st != :contour # special colorbar with steps is drawn for contours
|
||||||
|
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
|
||||||
|
GR.settransparency(1)
|
||||||
|
gr_colorbar(sp, clims)
|
||||||
|
end
|
||||||
|
|
||||||
GR.restorestate()
|
GR.restorestate()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1146,7 +1194,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
GR.savestate()
|
GR.savestate()
|
||||||
GR.selntran(0)
|
GR.selntran(0)
|
||||||
GR.setscale(0)
|
GR.setscale(0)
|
||||||
gr_set_font(sp[:legendfont])
|
gr_set_font(legendfont(sp))
|
||||||
w = 0
|
w = 0
|
||||||
i = 0
|
i = 0
|
||||||
n = 0
|
n = 0
|
||||||
@ -1164,23 +1212,22 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
else
|
else
|
||||||
lab = series[:label]
|
lab = series[:label]
|
||||||
end
|
end
|
||||||
tbx, tby = gr_inqtext(0, 0, lab)
|
tbx, tby = gr_inqtext(0, 0, string(lab))
|
||||||
w = max(w, tbx[3] - tbx[1])
|
w = max(w, tbx[3] - tbx[1])
|
||||||
end
|
end
|
||||||
if w > 0
|
if w > 0
|
||||||
dy = _gr_point_mult[1] * sp[:legendfont].pointsize * 1.75
|
dy = _gr_point_mult[1] * sp[:legendfontsize] * 1.75
|
||||||
h = dy*n
|
h = dy*n
|
||||||
(xpos,ypos) = gr_legend_pos(sp[:legend],w,h)
|
(xpos,ypos) = gr_legend_pos(sp[:legend],w,h)
|
||||||
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
GR.setfillintstyle(GR.INTSTYLE_SOLID)
|
||||||
gr_set_fillcolor(sp[:background_color_legend])
|
gr_set_fillcolor(sp[:background_color_legend])
|
||||||
GR.fillrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
|
GR.fillrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
|
||||||
GR.setlinetype(1)
|
gr_set_line(1, :solid, sp[:foreground_color_legend])
|
||||||
GR.setlinewidth(1)
|
|
||||||
GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
|
GR.drawrect(xpos - 0.08, xpos + w + 0.02, ypos + dy, ypos - dy * n)
|
||||||
i = 0
|
i = 0
|
||||||
if sp[:legendtitle] != nothing
|
if sp[:legendtitle] != nothing
|
||||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
|
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_HALF)
|
||||||
gr_set_textcolor(sp[:foreground_color_legend])
|
gr_set_textcolor(sp[:legendfontcolor])
|
||||||
GR.settransparency(1)
|
GR.settransparency(1)
|
||||||
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
|
gr_text(xpos - 0.03 + 0.5*w, ypos, string(sp[:legendtitle]))
|
||||||
ypos -= dy
|
ypos -= dy
|
||||||
@ -1222,8 +1269,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
|||||||
lab = series[:label]
|
lab = series[:label]
|
||||||
end
|
end
|
||||||
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
|
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
|
||||||
gr_set_textcolor(sp[:foreground_color_legend])
|
gr_set_textcolor(sp[:legendfontcolor])
|
||||||
gr_text(xpos, ypos, lab)
|
gr_text(xpos, ypos, string(lab))
|
||||||
ypos -= dy
|
ypos -= dy
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1281,12 +1328,18 @@ for (mime, fmt) in _gr_mimeformats
|
|||||||
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GRBackend})
|
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GRBackend})
|
||||||
GR.emergencyclosegks()
|
GR.emergencyclosegks()
|
||||||
filepath = tempname() * "." * $fmt
|
filepath = tempname() * "." * $fmt
|
||||||
|
env = get(ENV, "GKSwstype", "0")
|
||||||
ENV["GKSwstype"] = $fmt
|
ENV["GKSwstype"] = $fmt
|
||||||
ENV["GKS_FILEPATH"] = filepath
|
ENV["GKS_FILEPATH"] = filepath
|
||||||
gr_display(plt)
|
gr_display(plt)
|
||||||
GR.emergencyclosegks()
|
GR.emergencyclosegks()
|
||||||
write(io, readstring(filepath))
|
write(io, readstring(filepath))
|
||||||
rm(filepath)
|
rm(filepath)
|
||||||
|
if env != "0"
|
||||||
|
ENV["GKSwstype"] = env
|
||||||
|
else
|
||||||
|
pop!(ENV,"GKSwstype")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -28,14 +28,17 @@ Read from .hdf5 file using:
|
|||||||
- Should be reliable for archival purposes.
|
- Should be reliable for archival purposes.
|
||||||
==#
|
==#
|
||||||
|
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "hdf5.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
import FixedPointNumbers: N0f8 #In core Julia
|
import FixedPointNumbers: N0f8 #In core Julia
|
||||||
|
|
||||||
#Dispatch types:
|
#Dispatch types:
|
||||||
immutable HDF5PlotNative; end #Indentifies a data element that can natively be handled by HDF5
|
struct HDF5PlotNative; end #Indentifies a data element that can natively be handled by HDF5
|
||||||
immutable HDF5CTuple; end #Identifies a "complex" tuple structure
|
struct HDF5CTuple; end #Identifies a "complex" tuple structure
|
||||||
|
|
||||||
type HDF5Plot_PlotRef
|
mutable struct HDF5Plot_PlotRef
|
||||||
ref::Union{Plot, Void}
|
ref::Union{Plot, Void}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -276,11 +279,11 @@ function _hdf5plot_overwritetype(grp, T::Type) #Write directly to group
|
|||||||
HDF5.a_delete(grp, _hdf5plot_datatypeid)
|
HDF5.a_delete(grp, _hdf5plot_datatypeid)
|
||||||
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
|
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
|
||||||
end
|
end
|
||||||
function _hdf5plot_writetype{T<:Any}(grp, ::Type{Array{T}})
|
function _hdf5plot_writetype(grp, ::Type{Array{T}}) where T<:Any
|
||||||
tstr = HDF5PLOT_MAP_TELEM2STR[Array] #ANY
|
tstr = HDF5PLOT_MAP_TELEM2STR[Array] #ANY
|
||||||
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
|
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
|
||||||
end
|
end
|
||||||
function _hdf5plot_writetype{T<:BoundingBox}(grp, ::Type{T})
|
function _hdf5plot_writetype(grp, ::Type{T}) where T<:BoundingBox
|
||||||
tstr = HDF5PLOT_MAP_TELEM2STR[BoundingBox]
|
tstr = HDF5PLOT_MAP_TELEM2STR[BoundingBox]
|
||||||
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
|
HDF5.a_write(grp, _hdf5plot_datatypeid, tstr)
|
||||||
end
|
end
|
||||||
@ -305,7 +308,7 @@ function _hdf5plot_gwrite(grp, k::String, v) #Default
|
|||||||
grp[k] = v
|
grp[k] = v
|
||||||
_hdf5plot_writetype(grp, k, HDF5PlotNative)
|
_hdf5plot_writetype(grp, k, HDF5PlotNative)
|
||||||
end
|
end
|
||||||
function _hdf5plot_gwrite{T<:Number}(grp, k::String, v::Array{T}) #Default for arrays
|
function _hdf5plot_gwrite(grp, k::String, v::Array{T}) where T<:Number #Default for arrays
|
||||||
grp[k] = v
|
grp[k] = v
|
||||||
_hdf5plot_writetype(grp, k, HDF5PlotNative)
|
_hdf5plot_writetype(grp, k, HDF5PlotNative)
|
||||||
end
|
end
|
||||||
@ -355,7 +358,7 @@ function _hdf5plot_gwrite(grp, k::String, v::Colorant)
|
|||||||
_hdf5plot_gwrite(grp, k, ARGB{N0f8}(v))
|
_hdf5plot_gwrite(grp, k, ARGB{N0f8}(v))
|
||||||
end
|
end
|
||||||
#Custom vector (when not using simple numeric type):
|
#Custom vector (when not using simple numeric type):
|
||||||
function _hdf5plot_gwritearray{T}(grp, k::String, v::Array{T})
|
function _hdf5plot_gwritearray(grp, k::String, v::Array{T}) where T
|
||||||
if "annotations" == k;
|
if "annotations" == k;
|
||||||
return #Hack. Does not yet support annotations.
|
return #Hack. Does not yet support annotations.
|
||||||
end
|
end
|
||||||
@ -380,7 +383,7 @@ function _hdf5plot_gwrite(grp, k::String, v::Extrema)
|
|||||||
grp[k] = [v.emin, v.emax]
|
grp[k] = [v.emin, v.emax]
|
||||||
_hdf5plot_writetype(grp, k, Extrema)
|
_hdf5plot_writetype(grp, k, Extrema)
|
||||||
end
|
end
|
||||||
function _hdf5plot_gwrite{T}(grp, k::String, v::Length{T})
|
function _hdf5plot_gwrite(grp, k::String, v::Length{T}) where T
|
||||||
grp[k] = v.value
|
grp[k] = v.value
|
||||||
_hdf5plot_writetype(grp, k, [HDF5PLOT_MAP_TELEM2STR[Length], string(T)])
|
_hdf5plot_writetype(grp, k, [HDF5PLOT_MAP_TELEM2STR[Length], string(T)])
|
||||||
end
|
end
|
||||||
|
|||||||
@ -13,6 +13,10 @@ Add in functionality to Plots.jl:
|
|||||||
:aspect_ratio,
|
:aspect_ratio,
|
||||||
=#
|
=#
|
||||||
|
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "inspectdr.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
#TODO: remove features
|
#TODO: remove features
|
||||||
const _inspectdr_attr = merge_with_base_supported([
|
const _inspectdr_attr = merge_with_base_supported([
|
||||||
@ -28,10 +32,13 @@ const _inspectdr_attr = merge_with_base_supported([
|
|||||||
:markerstrokestyle, #Causes warning not to have it... what is this?
|
:markerstrokestyle, #Causes warning not to have it... what is this?
|
||||||
:fillcolor, :fillalpha, #:fillrange,
|
:fillcolor, :fillalpha, #:fillrange,
|
||||||
# :bins, :bar_width, :bar_edges, :bar_position,
|
# :bins, :bar_width, :bar_edges, :bar_position,
|
||||||
:title, :title_location, :titlefont,
|
:title, :title_location,
|
||||||
:window_title,
|
:window_title,
|
||||||
:guide, :lims, :scale, #:ticks, :flip, :rotation,
|
:guide, :lims, :scale, #:ticks, :flip, :rotation,
|
||||||
:tickfont, :guidefont, :legendfont,
|
:titlefontfamily, :titlefontsize, :titlefontcolor,
|
||||||
|
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
||||||
|
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
||||||
|
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
||||||
:grid, :legend, #:colorbar,
|
:grid, :legend, #:colorbar,
|
||||||
# :marker_z,
|
# :marker_z,
|
||||||
# :line_z,
|
# :line_z,
|
||||||
@ -131,7 +138,7 @@ end
|
|||||||
|
|
||||||
function _inspectdr_getscale(s::Symbol, yaxis::Bool)
|
function _inspectdr_getscale(s::Symbol, yaxis::Bool)
|
||||||
#TODO: Support :asinh, :sqrt
|
#TODO: Support :asinh, :sqrt
|
||||||
kwargs = yaxis? (:tgtmajor=>8, :tgtminor=>2): () #More grid lines on y-axis
|
kwargs = yaxis ? (:tgtmajor=>8, :tgtminor=>2) : () #More grid lines on y-axis
|
||||||
if :log2 == s
|
if :log2 == s
|
||||||
return InspectDR.AxisScale(:log2; kwargs...)
|
return InspectDR.AxisScale(:log2; kwargs...)
|
||||||
elseif :log10 == s
|
elseif :log10 == s
|
||||||
@ -163,7 +170,7 @@ function _initialize_backend(::InspectDRBackend; kw...)
|
|||||||
2*InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y
|
2*InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y
|
||||||
)
|
)
|
||||||
|
|
||||||
type InspecDRPlotRef
|
mutable struct InspecDRPlotRef
|
||||||
mplot::Union{Void, InspectDR.Multiplot}
|
mplot::Union{Void, InspectDR.Multiplot}
|
||||||
gui::Union{Void, InspectDR.GtkPlot}
|
gui::Union{Void, InspectDR.GtkPlot}
|
||||||
end
|
end
|
||||||
@ -172,7 +179,7 @@ function _initialize_backend(::InspectDRBackend; kw...)
|
|||||||
_inspectdr_getmplot(r::InspecDRPlotRef) = r.mplot
|
_inspectdr_getmplot(r::InspecDRPlotRef) = r.mplot
|
||||||
|
|
||||||
_inspectdr_getgui(::Any) = nothing
|
_inspectdr_getgui(::Any) = nothing
|
||||||
_inspectdr_getgui(gplot::InspectDR.GtkPlot) = (gplot.destroyed? nothing: gplot)
|
_inspectdr_getgui(gplot::InspectDR.GtkPlot) = (gplot.destroyed ? nothing : gplot)
|
||||||
_inspectdr_getgui(r::InspecDRPlotRef) = _inspectdr_getgui(r.gui)
|
_inspectdr_getgui(r::InspecDRPlotRef) = _inspectdr_getgui(r.gui)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -235,13 +242,13 @@ function _series_added(plt::Plot{InspectDRBackend}, series::Series)
|
|||||||
#Don't do anything without a "subplot" object: Will process later.
|
#Don't do anything without a "subplot" object: Will process later.
|
||||||
if nothing == plot; return; end
|
if nothing == plot; return; end
|
||||||
|
|
||||||
_vectorize(v) = isa(v, Vector)? v: collect(v) #InspectDR only supports vectors
|
_vectorize(v) = isa(v, Vector) ? v : collect(v) #InspectDR only supports vectors
|
||||||
x = _vectorize(series[:x]); y = _vectorize(series[:y])
|
x = _vectorize(series[:x]); y = _vectorize(series[:y])
|
||||||
|
|
||||||
#No support for polar grid... but can still perform polar transformation:
|
#No support for polar grid... but can still perform polar transformation:
|
||||||
if ispolar(sp)
|
if ispolar(sp)
|
||||||
Θ = x; r = y
|
Θ = x; r = y
|
||||||
x = r.*cos(Θ); y = r.*sin(Θ)
|
x = r.*cos.(Θ); y = r.*sin.(Θ)
|
||||||
end
|
end
|
||||||
|
|
||||||
# doesn't handle mismatched x/y - wrap data (pyplot behaviour):
|
# doesn't handle mismatched x/y - wrap data (pyplot behaviour):
|
||||||
@ -278,7 +285,7 @@ For st in :shape:
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
i = (nmax >= 2? div(nmax, 2): nmax) #Must pick one set of colors for legend
|
i = (nmax >= 2 ? div(nmax, 2) : nmax) #Must pick one set of colors for legend
|
||||||
if i > 1 #Add dummy waveform for legend entry:
|
if i > 1 #Add dummy waveform for legend entry:
|
||||||
linewidth = series[:linewidth]
|
linewidth = series[:linewidth]
|
||||||
linecolor = _inspectdr_mapcolor(_cycle(series[:linecolor], i))
|
linecolor = _inspectdr_mapcolor(_cycle(series[:linecolor], i))
|
||||||
@ -296,7 +303,7 @@ For st in :shape:
|
|||||||
#NOTE: In Plots.jl, :scatter plots have 0-linewidths (I think).
|
#NOTE: In Plots.jl, :scatter plots have 0-linewidths (I think).
|
||||||
linewidth = series[:linewidth]
|
linewidth = series[:linewidth]
|
||||||
#More efficient & allows some support for markerstrokewidth:
|
#More efficient & allows some support for markerstrokewidth:
|
||||||
_style = (0==linewidth? :none: series[:linestyle])
|
_style = (0==linewidth ? :none : series[:linestyle])
|
||||||
wfrm = InspectDR.add(plot, x, y, id=series[:label])
|
wfrm = InspectDR.add(plot, x, y, id=series[:label])
|
||||||
wfrm.line = InspectDR.line(
|
wfrm.line = InspectDR.line(
|
||||||
style = _style,
|
style = _style,
|
||||||
@ -369,24 +376,24 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
|
|||||||
l[:frame_canvas].fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot])
|
l[:frame_canvas].fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot])
|
||||||
l[:frame_data].fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
|
l[:frame_data].fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
|
||||||
l[:frame_data].line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
|
l[:frame_data].line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
|
||||||
l[:font_title] = InspectDR.Font(sp[:titlefont].family,
|
l[:font_title] = InspectDR.Font(sp[:titlefontfamily],
|
||||||
_inspectdr_mapptsize(sp[:titlefont].pointsize),
|
_inspectdr_mapptsize(sp[:titlefontsize]),
|
||||||
color = _inspectdr_mapcolor(sp[:foreground_color_title])
|
color = _inspectdr_mapcolor(sp[:titlefontcolor])
|
||||||
)
|
)
|
||||||
#Cannot independently control fonts of axes with InspectDR:
|
#Cannot independently control fonts of axes with InspectDR:
|
||||||
l[:font_axislabel] = InspectDR.Font(xaxis[:guidefont].family,
|
l[:font_axislabel] = InspectDR.Font(xaxis[:guidefontfamily],
|
||||||
_inspectdr_mapptsize(xaxis[:guidefont].pointsize),
|
_inspectdr_mapptsize(xaxis[:guidefontsize]),
|
||||||
color = _inspectdr_mapcolor(xaxis[:foreground_color_guide])
|
color = _inspectdr_mapcolor(xaxis[:guidefontcolor])
|
||||||
)
|
)
|
||||||
l[:font_ticklabel] = InspectDR.Font(xaxis[:tickfont].family,
|
l[:font_ticklabel] = InspectDR.Font(xaxis[:tickfontfamily],
|
||||||
_inspectdr_mapptsize(xaxis[:tickfont].pointsize),
|
_inspectdr_mapptsize(xaxis[:tickfontsize]),
|
||||||
color = _inspectdr_mapcolor(xaxis[:foreground_color_text])
|
color = _inspectdr_mapcolor(xaxis[:tickfontcolor])
|
||||||
)
|
)
|
||||||
l[:enable_legend] = (sp[:legend] != :none)
|
l[:enable_legend] = (sp[:legend] != :none)
|
||||||
#l[:halloc_legend] = 150 #TODO: compute???
|
#l[:halloc_legend] = 150 #TODO: compute???
|
||||||
l[:font_legend] = InspectDR.Font(sp[:legendfont].family,
|
l[:font_legend] = InspectDR.Font(sp[:legendfontfamily],
|
||||||
_inspectdr_mapptsize(sp[:legendfont].pointsize),
|
_inspectdr_mapptsize(sp[:legendfontsize]),
|
||||||
color = _inspectdr_mapcolor(sp[:foreground_color_legend])
|
color = _inspectdr_mapcolor(sp[:legendfontcolor])
|
||||||
)
|
)
|
||||||
l[:frame_legend].fillcolor = _inspectdr_mapcolor(sp[:background_color_legend])
|
l[:frame_legend].fillcolor = _inspectdr_mapcolor(sp[:background_color_legend])
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
# significant contributions by: @pkofod
|
# significant contributions by: @pkofod
|
||||||
|
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "pgfplots.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
const _pgfplots_attr = merge_with_base_supported([
|
const _pgfplots_attr = merge_with_base_supported([
|
||||||
:annotations,
|
:annotations,
|
||||||
# :background_color_legend,
|
# :background_color_legend,
|
||||||
@ -32,10 +36,12 @@ const _pgfplots_attr = merge_with_base_supported([
|
|||||||
:aspect_ratio,
|
:aspect_ratio,
|
||||||
# :match_dimensions,
|
# :match_dimensions,
|
||||||
:tick_direction,
|
:tick_direction,
|
||||||
|
:framestyle,
|
||||||
|
:camera,
|
||||||
])
|
])
|
||||||
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape]
|
const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape]
|
||||||
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||||
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon] #vcat(_allMarkers, Shape)
|
const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon, :hline] #vcat(_allMarkers, Shape)
|
||||||
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
|
const _pgfplots_scale = [:identity, :ln, :log2, :log10]
|
||||||
|
|
||||||
|
|
||||||
@ -80,6 +86,7 @@ const _pgfplots_markers = KW(
|
|||||||
:star6 => "asterisk",
|
:star6 => "asterisk",
|
||||||
:diamond => "diamond*",
|
:diamond => "diamond*",
|
||||||
:pentagon => "pentagon*",
|
:pentagon => "pentagon*",
|
||||||
|
:hline => "-"
|
||||||
)
|
)
|
||||||
|
|
||||||
const _pgfplots_legend_pos = KW(
|
const _pgfplots_legend_pos = KW(
|
||||||
@ -87,6 +94,7 @@ const _pgfplots_legend_pos = KW(
|
|||||||
:bottomright => "south east",
|
:bottomright => "south east",
|
||||||
:topright => "north east",
|
:topright => "north east",
|
||||||
:topleft => "north west",
|
:topleft => "north west",
|
||||||
|
:outertopright => "outer north east",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -107,6 +115,18 @@ const _pgf_annotation_halign = KW(
|
|||||||
:right => "left"
|
:right => "left"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const _pgf_framestyles = [:box, :axes, :origin, :zerolines, :grid, :none]
|
||||||
|
const _pgf_framestyle_defaults = Dict(:semi => :box)
|
||||||
|
function pgf_framestyle(style::Symbol)
|
||||||
|
if style in _pgf_framestyles
|
||||||
|
return style
|
||||||
|
else
|
||||||
|
default_style = get(_pgf_framestyle_defaults, style, :axes)
|
||||||
|
warn("Framestyle :$style is not (yet) supported by the PGFPlots backend. :$default_style was cosen instead.")
|
||||||
|
default_style
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# --------------------------------------------------------------------------------------
|
# --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
# takes in color,alpha, and returns color and alpha appropriate for pgf style
|
# takes in color,alpha, and returns color and alpha appropriate for pgf style
|
||||||
@ -188,6 +208,9 @@ function pgf_series(sp::Subplot, series::Series)
|
|||||||
# add to legend?
|
# add to legend?
|
||||||
if sp[:legend] != :none && should_add_to_legend(series)
|
if sp[:legend] != :none && should_add_to_legend(series)
|
||||||
kw[:legendentry] = d[:label]
|
kw[:legendentry] = d[:label]
|
||||||
|
if st == :shape || d[:fillrange] != nothing
|
||||||
|
push!(style, "area legend")
|
||||||
|
end
|
||||||
else
|
else
|
||||||
push!(style, "forget plot")
|
push!(style, "forget plot")
|
||||||
end
|
end
|
||||||
@ -201,6 +224,9 @@ function pgf_series(sp::Subplot, series::Series)
|
|||||||
# If a marker_z is used pass it as third coordinate to a 2D plot.
|
# If a marker_z is used pass it as third coordinate to a 2D plot.
|
||||||
# See "Scatter Plots" in PGFPlots documentation
|
# See "Scatter Plots" in PGFPlots documentation
|
||||||
d[:x], d[:y], d[:marker_z]
|
d[:x], d[:y], d[:marker_z]
|
||||||
|
elseif ispolar(sp)
|
||||||
|
theta, r = filter_radial_data(d[:x], d[:y], axis_limits(sp[:yaxis]))
|
||||||
|
rad2deg.(theta), r
|
||||||
else
|
else
|
||||||
d[:x], d[:y]
|
d[:x], d[:y]
|
||||||
end
|
end
|
||||||
@ -246,6 +272,9 @@ function pgf_axis(sp::Subplot, letter)
|
|||||||
style = []
|
style = []
|
||||||
kw = KW()
|
kw = KW()
|
||||||
|
|
||||||
|
# set to supported framestyle
|
||||||
|
framestyle = pgf_framestyle(sp[:framestyle])
|
||||||
|
|
||||||
# axis guide
|
# axis guide
|
||||||
kw[Symbol(letter,:label)] = axis[:guide]
|
kw[Symbol(letter,:label)] = axis[:guide]
|
||||||
|
|
||||||
@ -263,30 +292,67 @@ function pgf_axis(sp::Subplot, letter)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# ticks on or off
|
# ticks on or off
|
||||||
if axis[:ticks] in (nothing, false)
|
if axis[:ticks] in (nothing, false) || framestyle == :none
|
||||||
push!(style, "$(letter)majorticks=false")
|
push!(style, "$(letter)majorticks=false")
|
||||||
end
|
end
|
||||||
|
|
||||||
# grid on or off
|
# grid on or off
|
||||||
if axis[:grid]
|
if axis[:grid] && framestyle != :none
|
||||||
push!(style, "$(letter)majorgrids = true")
|
push!(style, "$(letter)majorgrids = true")
|
||||||
|
else
|
||||||
|
push!(style, "$(letter)majorgrids = false")
|
||||||
end
|
end
|
||||||
|
|
||||||
# limits
|
# limits
|
||||||
# TODO: support zlims
|
# TODO: support zlims
|
||||||
if letter != :z
|
if letter != :z
|
||||||
lims = axis_limits(axis)
|
lims = ispolar(sp) && letter == :x ? rad2deg.(axis_limits(axis)) : axis_limits(axis)
|
||||||
kw[Symbol(letter,:min)] = lims[1]
|
kw[Symbol(letter,:min)] = lims[1]
|
||||||
kw[Symbol(letter,:max)] = lims[2]
|
kw[Symbol(letter,:max)] = lims[2]
|
||||||
end
|
end
|
||||||
|
|
||||||
if !(axis[:ticks] in (nothing, false, :none))
|
if !(axis[:ticks] in (nothing, false, :none)) && framestyle != :none
|
||||||
ticks = get_ticks(axis)
|
ticks = get_ticks(axis)
|
||||||
push!(style, string(letter, "tick = {", join(ticks[1],","), "}"))
|
#pgf plot ignores ticks with angle below 90 when xmin = 90 so shift values
|
||||||
push!(style, string(letter, "ticklabels = {", join(ticks[2],","), "}"))
|
tick_values = ispolar(sp) && letter == :x ? [rad2deg.(ticks[1])[3:end]..., 360, 405] : ticks[1]
|
||||||
|
push!(style, string(letter, "tick = {", join(tick_values,","), "}"))
|
||||||
|
if axis[:showaxis] && axis[:scale] in (:ln, :log2, :log10) && axis[:ticks] == :auto
|
||||||
|
# wrap the power part of label with }
|
||||||
|
tick_labels = String[begin
|
||||||
|
base, power = split(label, "^")
|
||||||
|
power = string("{", power, "}")
|
||||||
|
string(base, "^", power)
|
||||||
|
end for label in ticks[2]]
|
||||||
|
push!(style, string(letter, "ticklabels = {\$", join(tick_labels,"\$,\$"), "\$}"))
|
||||||
|
elseif axis[:showaxis]
|
||||||
|
tick_labels = ispolar(sp) && letter == :x ? [ticks[2][3:end]..., "0", "45"] : ticks[2]
|
||||||
|
push!(style, string(letter, "ticklabels = {", join(tick_labels,","), "}"))
|
||||||
|
else
|
||||||
|
push!(style, string(letter, "ticklabels = {}"))
|
||||||
|
end
|
||||||
push!(style, string(letter, "tick align = ", (axis[:tick_direction] == :out ? "outside" : "inside")))
|
push!(style, string(letter, "tick align = ", (axis[:tick_direction] == :out ? "outside" : "inside")))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# framestyle
|
||||||
|
if framestyle in (:axes, :origin)
|
||||||
|
axispos = framestyle == :axes ? "left" : "middle"
|
||||||
|
# the * after lines disables the arrows at the axes
|
||||||
|
push!(style, string("axis lines* = ", axispos))
|
||||||
|
end
|
||||||
|
|
||||||
|
if framestyle == :zerolines
|
||||||
|
push!(style, string("extra ", letter, " ticks = 0"))
|
||||||
|
push!(style, string("extra ", letter, " tick labels = "))
|
||||||
|
push!(style, string("extra ", letter, " tick style = {grid = major, major grid style = {color = black, draw opacity=1.0, line width=0.5), solid}}"))
|
||||||
|
end
|
||||||
|
|
||||||
|
if !axis[:showaxis]
|
||||||
|
push!(style, "separate axis lines")
|
||||||
|
end
|
||||||
|
if !axis[:showaxis] || framestyle in (:zerolines, :grid, :none)
|
||||||
|
push!(style, string(letter, " axis line style = {draw opacity = 0}"))
|
||||||
|
end
|
||||||
|
|
||||||
# return the style list and KW args
|
# return the style list and KW args
|
||||||
style, kw
|
style, kw
|
||||||
end
|
end
|
||||||
@ -340,9 +406,17 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend})
|
|||||||
kw[:legendPos] = _pgfplots_legend_pos[legpos]
|
kw[:legendPos] = _pgfplots_legend_pos[legpos]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if is3d(sp)
|
||||||
|
azim, elev = sp[:camera]
|
||||||
|
kw[:view] = "{$(azim)}{$(elev)}"
|
||||||
|
end
|
||||||
|
|
||||||
axisf = PGFPlots.Axis
|
axisf = PGFPlots.Axis
|
||||||
if sp[:projection] == :polar
|
if sp[:projection] == :polar
|
||||||
axisf = PGFPlots.PolarAxis
|
axisf = PGFPlots.PolarAxis
|
||||||
|
#make radial axis vertical
|
||||||
|
kw[:xmin] = 90
|
||||||
|
kw[:xmax] = 450
|
||||||
end
|
end
|
||||||
|
|
||||||
# Search series for any gradient. In case one series uses a gradient set
|
# Search series for any gradient. In case one series uses a gradient set
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
|
|
||||||
# https://plot.ly/javascript/getting-started
|
# https://plot.ly/javascript/getting-started
|
||||||
|
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "plotly.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
const _plotly_attr = merge_with_base_supported([
|
const _plotly_attr = merge_with_base_supported([
|
||||||
:annotations,
|
:annotations,
|
||||||
:background_color_legend, :background_color_inside, :background_color_outside,
|
:background_color_legend, :background_color_inside, :background_color_outside,
|
||||||
@ -15,7 +19,12 @@ const _plotly_attr = merge_with_base_supported([
|
|||||||
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle,
|
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokestyle,
|
||||||
:fillrange, :fillcolor, :fillalpha,
|
:fillrange, :fillcolor, :fillalpha,
|
||||||
:bins,
|
:bins,
|
||||||
:title, :title_location, :titlefont,
|
:title, :title_location,
|
||||||
|
:titlefontfamily, :titlefontsize, :titlefonthalign, :titlefontvalign,
|
||||||
|
:titlefontcolor,
|
||||||
|
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
||||||
|
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
||||||
|
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
||||||
:window_title,
|
:window_title,
|
||||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
:tickfont, :guidefont, :legendfont,
|
:tickfont, :guidefont, :legendfont,
|
||||||
@ -35,6 +44,7 @@ const _plotly_attr = merge_with_base_supported([
|
|||||||
:clims,
|
:clims,
|
||||||
:framestyle,
|
:framestyle,
|
||||||
:tick_direction,
|
:tick_direction,
|
||||||
|
:camera,
|
||||||
])
|
])
|
||||||
|
|
||||||
const _plotly_seriestype = [
|
const _plotly_seriestype = [
|
||||||
@ -121,7 +131,7 @@ const _plotly_legend_pos = KW(
|
|||||||
)
|
)
|
||||||
|
|
||||||
plotly_legend_pos(pos::Symbol) = get(_plotly_legend_pos, pos, [1.,1.])
|
plotly_legend_pos(pos::Symbol) = get(_plotly_legend_pos, pos, [1.,1.])
|
||||||
plotly_legend_pos{S<:Real, T<:Real}(v::Tuple{S,T}) = v
|
plotly_legend_pos(v::Tuple{S,T}) where {S<:Real, T<:Real} = v
|
||||||
|
|
||||||
function plotly_font(font::Font, color = font.color)
|
function plotly_font(font::Font, color = font.color)
|
||||||
KW(
|
KW(
|
||||||
@ -234,10 +244,11 @@ function plotly_axis(axis::Axis, sp::Subplot)
|
|||||||
:gridwidth => axis[:gridlinewidth],
|
:gridwidth => axis[:gridlinewidth],
|
||||||
:zeroline => framestyle == :zerolines,
|
:zeroline => framestyle == :zerolines,
|
||||||
:zerolinecolor => rgba_string(axis[:foreground_color_axis]),
|
:zerolinecolor => rgba_string(axis[:foreground_color_axis]),
|
||||||
:showline => framestyle in (:box, :axes),
|
:showline => framestyle in (:box, :axes) && axis[:showaxis],
|
||||||
:linecolor => rgba_string(plot_color(axis[:foreground_color_axis])),
|
:linecolor => rgba_string(plot_color(axis[:foreground_color_axis])),
|
||||||
:ticks => axis[:tick_direction] == :out ? "outside" : "inside",
|
:ticks => axis[:tick_direction] == :out ? "outside" : "inside",
|
||||||
:mirror => framestyle == :box,
|
:mirror => framestyle == :box,
|
||||||
|
:showticklabels => axis[:showaxis],
|
||||||
)
|
)
|
||||||
|
|
||||||
if letter in (:x,:y)
|
if letter in (:x,:y)
|
||||||
@ -246,20 +257,16 @@ function plotly_axis(axis::Axis, sp::Subplot)
|
|||||||
end
|
end
|
||||||
|
|
||||||
ax[:tickangle] = -axis[:rotation]
|
ax[:tickangle] = -axis[:rotation]
|
||||||
|
lims = axis_limits(axis)
|
||||||
|
ax[:range] = map(scalefunc(axis[:scale]), lims)
|
||||||
|
|
||||||
if !(axis[:ticks] in (nothing, :none))
|
if !(axis[:ticks] in (nothing, :none))
|
||||||
ax[:titlefont] = plotly_font(axis[:guidefont], axis[:foreground_color_guide])
|
ax[:titlefont] = plotly_font(guidefont(axis))
|
||||||
ax[:type] = plotly_scale(axis[:scale])
|
ax[:type] = plotly_scale(axis[:scale])
|
||||||
ax[:tickfont] = plotly_font(axis[:tickfont], axis[:foreground_color_text])
|
ax[:tickfont] = plotly_font(tickfont(axis))
|
||||||
ax[:tickcolor] = framestyle in (:zerolines, :grid) ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis])
|
ax[:tickcolor] = framestyle in (:zerolines, :grid) || !axis[:showaxis] ? rgba_string(invisible()) : rgb_string(axis[:foreground_color_axis])
|
||||||
ax[:linecolor] = rgba_string(axis[:foreground_color_axis])
|
ax[:linecolor] = rgba_string(axis[:foreground_color_axis])
|
||||||
|
|
||||||
# lims
|
|
||||||
lims = axis[:lims]
|
|
||||||
if lims != :auto && limsType(lims) == :limits
|
|
||||||
ax[:range] = map(scalefunc(axis[:scale]), lims)
|
|
||||||
end
|
|
||||||
|
|
||||||
# flip
|
# flip
|
||||||
if axis[:flip]
|
if axis[:flip]
|
||||||
ax[:autorange] = "reversed"
|
ax[:autorange] = "reversed"
|
||||||
@ -282,6 +289,23 @@ function plotly_axis(axis::Axis, sp::Subplot)
|
|||||||
ax[:showgrid] = false
|
ax[:showgrid] = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
ax
|
||||||
|
end
|
||||||
|
|
||||||
|
function plotly_polaraxis(axis::Axis)
|
||||||
|
ax = KW(
|
||||||
|
:visible => axis[:showaxis],
|
||||||
|
:showline => axis[:grid],
|
||||||
|
)
|
||||||
|
|
||||||
|
if axis[:letter] == :x
|
||||||
|
ax[:range] = rad2deg.(axis_limits(axis))
|
||||||
|
else
|
||||||
|
ax[:range] = axis_limits(axis)
|
||||||
|
ax[:orientation] = -90
|
||||||
|
end
|
||||||
|
|
||||||
ax
|
ax
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -312,8 +336,8 @@ function plotly_layout(plt::Plot)
|
|||||||
0.5 * (left(bb) + right(bb))
|
0.5 * (left(bb) + right(bb))
|
||||||
end
|
end
|
||||||
titlex, titley = xy_mm_to_pcts(xmm, top(bbox(sp)), w*px, h*px)
|
titlex, titley = xy_mm_to_pcts(xmm, top(bbox(sp)), w*px, h*px)
|
||||||
titlefont = font(sp[:titlefont], :top, sp[:foreground_color_title])
|
title_font = font(titlefont(sp), :top)
|
||||||
push!(d_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], titlefont)))
|
push!(d_out[:annotations], plotly_annotation_dict(titlex, titley, text(sp[:title], title_font)))
|
||||||
end
|
end
|
||||||
|
|
||||||
d_out[:plot_bgcolor] = rgba_string(sp[:background_color_inside])
|
d_out[:plot_bgcolor] = rgba_string(sp[:background_color_inside])
|
||||||
@ -323,11 +347,25 @@ function plotly_layout(plt::Plot)
|
|||||||
|
|
||||||
# if any(is3d, seriesargs)
|
# if any(is3d, seriesargs)
|
||||||
if is3d(sp)
|
if is3d(sp)
|
||||||
|
azim = sp[:camera][1] - 90 #convert azimuthal to match GR behaviour
|
||||||
|
theta = 90 - sp[:camera][2] #spherical coordinate angle from z axis
|
||||||
d_out[:scene] = KW(
|
d_out[:scene] = KW(
|
||||||
Symbol("xaxis$spidx") => plotly_axis(sp[:xaxis], sp),
|
Symbol("xaxis$spidx") => plotly_axis(sp[:xaxis], sp),
|
||||||
Symbol("yaxis$spidx") => plotly_axis(sp[:yaxis], sp),
|
Symbol("yaxis$spidx") => plotly_axis(sp[:yaxis], sp),
|
||||||
Symbol("zaxis$spidx") => plotly_axis(sp[:zaxis], sp),
|
Symbol("zaxis$spidx") => plotly_axis(sp[:zaxis], sp),
|
||||||
|
|
||||||
|
#2.6 multiplier set camera eye such that whole plot can be seen
|
||||||
|
:camera => KW(
|
||||||
|
:eye => KW(
|
||||||
|
:x => cosd(azim)*sind(theta)*2.6,
|
||||||
|
:y => sind(azim)*sind(theta)*2.6,
|
||||||
|
:z => cosd(theta)*2.6,
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
elseif ispolar(sp)
|
||||||
|
d_out[Symbol("angularaxis$spidx")] = plotly_polaraxis(sp[:xaxis])
|
||||||
|
d_out[Symbol("radialaxis$spidx")] = plotly_polaraxis(sp[:yaxis])
|
||||||
else
|
else
|
||||||
d_out[Symbol("xaxis$spidx")] = plotly_axis(sp[:xaxis], sp)
|
d_out[Symbol("xaxis$spidx")] = plotly_axis(sp[:xaxis], sp)
|
||||||
d_out[Symbol("yaxis$spidx")] = plotly_axis(sp[:yaxis], sp)
|
d_out[Symbol("yaxis$spidx")] = plotly_axis(sp[:yaxis], sp)
|
||||||
@ -340,7 +378,7 @@ function plotly_layout(plt::Plot)
|
|||||||
d_out[:legend] = KW(
|
d_out[:legend] = KW(
|
||||||
:bgcolor => rgba_string(sp[:background_color_legend]),
|
:bgcolor => rgba_string(sp[:background_color_legend]),
|
||||||
:bordercolor => rgba_string(sp[:foreground_color_legend]),
|
:bordercolor => rgba_string(sp[:foreground_color_legend]),
|
||||||
:font => plotly_font(sp[:legendfont], sp[:foreground_color_legend]),
|
:font => plotly_font(legendfont(sp)),
|
||||||
:x => xpos,
|
:x => xpos,
|
||||||
:y => ypos
|
:y => ypos
|
||||||
)
|
)
|
||||||
@ -428,7 +466,7 @@ end
|
|||||||
|
|
||||||
plotly_data(v) = collect(v)
|
plotly_data(v) = collect(v)
|
||||||
plotly_data(surf::Surface) = surf.surf
|
plotly_data(surf::Surface) = surf.surf
|
||||||
plotly_data{R<:Rational}(v::AbstractArray{R}) = float(v)
|
plotly_data(v::AbstractArray{R}) where {R<:Rational} = float(v)
|
||||||
|
|
||||||
plotly_surface_data(series::Series, a::AbstractVector) = a
|
plotly_surface_data(series::Series, a::AbstractVector) = a
|
||||||
plotly_surface_data(series::Series, a::AbstractMatrix) = transpose_z(series, a, false)
|
plotly_surface_data(series::Series, a::AbstractMatrix) = transpose_z(series, a, false)
|
||||||
@ -509,7 +547,7 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
d_out[:type] = "heatmap"
|
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[: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[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
|
||||||
d_out[:showscale] = sp[:legend] != :none
|
d_out[:showscale] = hascolorbar(sp)
|
||||||
|
|
||||||
elseif st == :contour
|
elseif st == :contour
|
||||||
d_out[:type] = "contour"
|
d_out[:type] = "contour"
|
||||||
@ -518,7 +556,7 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
d_out[:ncontours] = series[:levels]
|
d_out[:ncontours] = series[:levels]
|
||||||
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines")
|
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines")
|
||||||
d_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
|
d_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
|
||||||
d_out[:showscale] = sp[:legend] != :none
|
d_out[:showscale] = hascolorbar(sp)
|
||||||
|
|
||||||
elseif st in (:surface, :wireframe)
|
elseif st in (:surface, :wireframe)
|
||||||
d_out[:type] = "surface"
|
d_out[:type] = "surface"
|
||||||
@ -538,7 +576,7 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
if series[:fill_z] != nothing
|
if series[:fill_z] != nothing
|
||||||
d_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
|
d_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
|
||||||
end
|
end
|
||||||
d_out[:showscale] = sp[:legend] != :none
|
d_out[:showscale] = hascolorbar(sp)
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif st == :pie
|
elseif st == :pie
|
||||||
@ -681,8 +719,9 @@ end
|
|||||||
function plotly_polar!(d_out::KW, series::Series)
|
function plotly_polar!(d_out::KW, series::Series)
|
||||||
# convert polar plots x/y to theta/radius
|
# convert polar plots x/y to theta/radius
|
||||||
if ispolar(series[:subplot])
|
if ispolar(series[:subplot])
|
||||||
d_out[:t] = rad2deg(pop!(d_out, :x))
|
theta, r = filter_radial_data(pop!(d_out, :x), pop!(d_out, :y), axis_limits(series[:subplot][:yaxis]))
|
||||||
d_out[:r] = pop!(d_out, :y)
|
d_out[:t] = rad2deg.(theta)
|
||||||
|
d_out[:r] = r
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -711,7 +750,7 @@ end
|
|||||||
const _use_remote = Ref(false)
|
const _use_remote = Ref(false)
|
||||||
|
|
||||||
function html_head(plt::Plot{PlotlyBackend})
|
function html_head(plt::Plot{PlotlyBackend})
|
||||||
jsfilename = _use_remote[] ? _plotly_js_path_remote : _plotly_js_path
|
jsfilename = _use_remote[] ? _plotly_js_path_remote : ("file://" * _plotly_js_path)
|
||||||
# "<script src=\"$(joinpath(dirname(@__FILE__),"..","..","deps","plotly-latest.min.js"))\"></script>"
|
# "<script src=\"$(joinpath(dirname(@__FILE__),"..","..","deps","plotly-latest.min.js"))\"></script>"
|
||||||
"<script src=\"$jsfilename\"></script>"
|
"<script src=\"$jsfilename\"></script>"
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "plotlyjs.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
# https://github.com/spencerlyon2/PlotlyJS.jl
|
# https://github.com/spencerlyon2/PlotlyJS.jl
|
||||||
|
|
||||||
@ -85,7 +88,8 @@ end
|
|||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
function _show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend})
|
function Base.show(io::IO, ::MIME"text/html", plt::Plot{PlotlyJSBackend})
|
||||||
|
prepare_output(plt)
|
||||||
if isijulia() && !_use_remote[]
|
if isijulia() && !_use_remote[]
|
||||||
write(io, PlotlyJS.html_body(PlotlyJS.JupyterPlot(plt.o)))
|
write(io, PlotlyJS.html_body(PlotlyJS.JupyterPlot(plt.o)))
|
||||||
else
|
else
|
||||||
@ -98,6 +102,7 @@ function plotlyjs_save_hack(io::IO, plt::Plot{PlotlyJSBackend}, ext::String)
|
|||||||
PlotlyJS.savefig(plt.o, tmpfn)
|
PlotlyJS.savefig(plt.o, tmpfn)
|
||||||
write(io, read(open(tmpfn)))
|
write(io, read(open(tmpfn)))
|
||||||
end
|
end
|
||||||
|
_show(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "svg")
|
||||||
_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "png")
|
_show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "png")
|
||||||
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "pdf")
|
_show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "pdf")
|
||||||
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "eps")
|
_show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "eps")
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
# https://github.com/stevengj/PyPlot.jl
|
# https://github.com/stevengj/PyPlot.jl
|
||||||
|
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "pyplot.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
const _pyplot_attr = merge_with_base_supported([
|
const _pyplot_attr = merge_with_base_supported([
|
||||||
:annotations,
|
:annotations,
|
||||||
@ -16,7 +19,10 @@ const _pyplot_attr = merge_with_base_supported([
|
|||||||
:title, :title_location, :titlefont,
|
:title, :title_location, :titlefont,
|
||||||
:window_title,
|
:window_title,
|
||||||
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
:guide, :lims, :ticks, :scale, :flip, :rotation,
|
||||||
:tickfont, :guidefont, :legendfont,
|
:titlefontfamily, :titlefontsize, :titlefontcolor,
|
||||||
|
:legendfontfamily, :legendfontsize, :legendfontcolor,
|
||||||
|
:tickfontfamily, :tickfontsize, :tickfontcolor,
|
||||||
|
:guidefontfamily, :guidefontsize, :guidefontcolor,
|
||||||
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
:grid, :gridalpha, :gridstyle, :gridlinewidth,
|
||||||
:legend, :legendtitle, :colorbar,
|
:legend, :legendtitle, :colorbar,
|
||||||
:marker_z, :line_z, :fill_z,
|
:marker_z, :line_z, :fill_z,
|
||||||
@ -35,6 +41,7 @@ const _pyplot_attr = merge_with_base_supported([
|
|||||||
:stride,
|
:stride,
|
||||||
:framestyle,
|
:framestyle,
|
||||||
:tick_direction,
|
:tick_direction,
|
||||||
|
:camera,
|
||||||
])
|
])
|
||||||
const _pyplot_seriestype = [
|
const _pyplot_seriestype = [
|
||||||
:path, :steppre, :steppost, :shape,
|
:path, :steppre, :steppost, :shape,
|
||||||
@ -124,6 +131,7 @@ end
|
|||||||
# # anything else just gets a bluesred gradient
|
# # anything else just gets a bluesred gradient
|
||||||
# py_colormap(c, α=nothing) = py_colormap(default_gradient(), α)
|
# py_colormap(c, α=nothing) = py_colormap(default_gradient(), α)
|
||||||
|
|
||||||
|
py_color(s) = py_color(parse(Colorant, string(s)))
|
||||||
py_color(c::Colorant) = (red(c), green(c), blue(c), alpha(c))
|
py_color(c::Colorant) = (red(c), green(c), blue(c), alpha(c))
|
||||||
py_color(cs::AVec) = map(py_color, cs)
|
py_color(cs::AVec) = map(py_color, cs)
|
||||||
py_color(grad::ColorGradient) = py_color(grad.colors)
|
py_color(grad::ColorGradient) = py_color(grad.colors)
|
||||||
@ -499,20 +507,19 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
:zorder => plt.n,
|
:zorder => plt.n,
|
||||||
:cmap => py_linecolormap(series),
|
:cmap => py_linecolormap(series),
|
||||||
:linewidth => py_dpi_scale(plt, series[:linewidth]),
|
:linewidth => py_dpi_scale(plt, series[:linewidth]),
|
||||||
:linestyle => py_linestyle(st, series[:linestyle])
|
:linestyle => py_linestyle(st, series[:linestyle]),
|
||||||
|
:norm => pycolors["Normalize"](; extrakw...)
|
||||||
)
|
)
|
||||||
if needs_colorbar
|
lz = _cycle(series[:line_z], 1:n)
|
||||||
kw[:norm] = pycolors["Normalize"](; extrakw...)
|
|
||||||
end
|
|
||||||
lz = collect(series[:line_z])
|
|
||||||
handle = if is3d(st)
|
handle = if is3d(st)
|
||||||
for rng in iter_segments(x, y, z)
|
for rng in iter_segments(x, y, z)
|
||||||
length(rng) < 2 && continue
|
length(rng) < 2 && continue
|
||||||
push!(segments, [(_cycle(x,i),_cycle(y,i),_cycle(z,i)) for i in rng])
|
for i in rng[1:end-1]
|
||||||
|
push!(segments, [(_cycle(x,i),_cycle(y,i),_cycle(z,i)),
|
||||||
|
(_cycle(x,i+1),_cycle(y,i+1),_cycle(z,i+1))])
|
||||||
|
end
|
||||||
end
|
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))]
|
|
||||||
# end
|
|
||||||
lc = pyart3d["Line3DCollection"](segments; kw...)
|
lc = pyart3d["Line3DCollection"](segments; kw...)
|
||||||
lc[:set_array](lz)
|
lc[:set_array](lz)
|
||||||
ax[:add_collection3d](lc, zs=z) #, zdir='y')
|
ax[:add_collection3d](lc, zs=z) #, zdir='y')
|
||||||
@ -520,11 +527,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
|||||||
else
|
else
|
||||||
for rng in iter_segments(x, y)
|
for rng in iter_segments(x, y)
|
||||||
length(rng) < 2 && continue
|
length(rng) < 2 && continue
|
||||||
push!(segments, [(_cycle(x,i),_cycle(y,i)) for i in rng])
|
for i in rng[1:end-1]
|
||||||
|
push!(segments, [(_cycle(x,i),_cycle(y,i)), (_cycle(x,i+1),_cycle(y,i+1))])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
# for i=1:n
|
|
||||||
# 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)
|
lc[:set_array](lz)
|
||||||
ax[:add_collection](lc)
|
ax[:add_collection](lc)
|
||||||
@ -917,11 +924,11 @@ function py_set_axis_colors(sp, ax, a::Axis)
|
|||||||
end
|
end
|
||||||
axissym = Symbol(a[:letter], :axis)
|
axissym = Symbol(a[:letter], :axis)
|
||||||
if haskey(ax, axissym)
|
if haskey(ax, axissym)
|
||||||
tickcolor = sp[:framestyle] == :zerolines ? py_color(plot_color(a[:foreground_color_grid], a[:gridalpha])) : py_color(a[:foreground_color_axis])
|
tickcolor = sp[:framestyle] in (:zerolines, :grid) ? py_color(plot_color(a[:foreground_color_grid], a[:gridalpha])) : py_color(a[:foreground_color_axis])
|
||||||
ax[:tick_params](axis=string(a[:letter]), which="both",
|
ax[:tick_params](axis=string(a[:letter]), which="both",
|
||||||
colors=tickcolor,
|
colors=tickcolor,
|
||||||
labelcolor=py_color(a[:foreground_color_text]))
|
labelcolor=py_color(a[:tickfontcolor]))
|
||||||
ax[axissym][:label][:set_color](py_color(a[:foreground_color_guide]))
|
ax[axissym][:label][:set_color](py_color(a[:guidefontcolor]))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -975,9 +982,9 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
:title
|
:title
|
||||||
end
|
end
|
||||||
ax[func][:set_text](sp[:title])
|
ax[func][:set_text](sp[:title])
|
||||||
ax[func][:set_fontsize](py_dpi_scale(plt, sp[:titlefont].pointsize))
|
ax[func][:set_fontsize](py_dpi_scale(plt, sp[:titlefontsize]))
|
||||||
ax[func][:set_family](sp[:titlefont].family)
|
ax[func][:set_family](sp[:titlefontfamily])
|
||||||
ax[func][:set_color](py_color(sp[:foreground_color_title]))
|
ax[func][:set_color](py_color(sp[:titlefontcolor]))
|
||||||
# ax[:set_title](sp[:title], loc = loc)
|
# ax[:set_title](sp[:title], loc = loc)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1002,7 +1009,12 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
fig = plt.o
|
fig = plt.o
|
||||||
cbax = fig[:add_axes]([0.8,0.1,0.03,0.8], label = string(gensym()))
|
cbax = fig[:add_axes]([0.8,0.1,0.03,0.8], label = string(gensym()))
|
||||||
cb = fig[:colorbar](handle; cax = cbax, kw...)
|
cb = fig[:colorbar](handle; cax = cbax, kw...)
|
||||||
cb[:set_label](sp[:colorbar_title])
|
cb[:set_label](sp[:colorbar_title],size=py_dpi_scale(plt, sp[:yaxis][:guidefontsize]),family=sp[:yaxis][:guidefontfamily], color = py_color(sp[:yaxis][:guidefontcolor]))
|
||||||
|
for lab in cb[:ax][:yaxis][:get_ticklabels]()
|
||||||
|
lab[:set_fontsize](py_dpi_scale(plt, sp[:yaxis][:tickfontsize]))
|
||||||
|
lab[:set_family](sp[:yaxis][:tickfontfamily])
|
||||||
|
lab[:set_color](py_color(sp[:yaxis][:tickfontcolor]))
|
||||||
|
end
|
||||||
sp.attr[:cbar_handle] = cb
|
sp.attr[:cbar_handle] = cb
|
||||||
sp.attr[:cbar_ax] = cbax
|
sp.attr[:cbar_ax] = cbax
|
||||||
end
|
end
|
||||||
@ -1047,6 +1059,9 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
end
|
end
|
||||||
py_set_scale(ax, axis)
|
py_set_scale(ax, axis)
|
||||||
py_set_lims(ax, axis)
|
py_set_lims(ax, axis)
|
||||||
|
if ispolar(sp) && letter == :y
|
||||||
|
ax[:set_rlabel_position](90)
|
||||||
|
end
|
||||||
ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
|
ticks = sp[:framestyle] == :none ? nothing : get_ticks(axis)
|
||||||
# don't show the 0 tick label for the origin framestyle
|
# don't show the 0 tick label for the origin framestyle
|
||||||
if sp[:framestyle] == :origin && length(ticks) > 1
|
if sp[:framestyle] == :origin && length(ticks) > 1
|
||||||
@ -1058,11 +1073,11 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
if get(axis.d, :flip, false)
|
if get(axis.d, :flip, false)
|
||||||
ax[Symbol("invert_", letter, "axis")]()
|
ax[Symbol("invert_", letter, "axis")]()
|
||||||
end
|
end
|
||||||
pyaxis[:label][:set_fontsize](py_dpi_scale(plt, axis[:guidefont].pointsize))
|
pyaxis[:label][:set_fontsize](py_dpi_scale(plt, axis[:guidefontsize]))
|
||||||
pyaxis[:label][:set_family](axis[:guidefont].family)
|
pyaxis[:label][:set_family](axis[:guidefontfamily])
|
||||||
for lab in ax[Symbol("get_", letter, "ticklabels")]()
|
for lab in ax[Symbol("get_", letter, "ticklabels")]()
|
||||||
lab[:set_fontsize](py_dpi_scale(plt, axis[:tickfont].pointsize))
|
lab[:set_fontsize](py_dpi_scale(plt, axis[:tickfontsize]))
|
||||||
lab[:set_family](axis[:tickfont].family)
|
lab[:set_family](axis[:tickfontfamily])
|
||||||
lab[:set_rotation](axis[:rotation])
|
lab[:set_rotation](axis[:rotation])
|
||||||
end
|
end
|
||||||
if axis[:grid] && !(ticks in (:none, nothing, false))
|
if axis[:grid] && !(ticks in (:none, nothing, false))
|
||||||
@ -1073,16 +1088,49 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
linewidth = axis[:gridlinewidth],
|
linewidth = axis[:gridlinewidth],
|
||||||
alpha = axis[:gridalpha])
|
alpha = axis[:gridalpha])
|
||||||
ax[:set_axisbelow](true)
|
ax[:set_axisbelow](true)
|
||||||
|
else
|
||||||
|
pyaxis[:grid](false)
|
||||||
end
|
end
|
||||||
py_set_axis_colors(sp, ax, axis)
|
py_set_axis_colors(sp, ax, axis)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# showaxis
|
||||||
|
if !sp[:xaxis][:showaxis]
|
||||||
|
kw = KW()
|
||||||
|
for dir in (:top, :bottom)
|
||||||
|
if ispolar(sp)
|
||||||
|
ax[:spines]["polar"][:set_visible](false)
|
||||||
|
else
|
||||||
|
ax[:spines][string(dir)][:set_visible](false)
|
||||||
|
end
|
||||||
|
kw[dir] = kw[Symbol(:label,dir)] = "off"
|
||||||
|
end
|
||||||
|
ax[:xaxis][:set_tick_params](; which="both", kw...)
|
||||||
|
end
|
||||||
|
if !sp[:yaxis][:showaxis]
|
||||||
|
kw = KW()
|
||||||
|
for dir in (:left, :right)
|
||||||
|
if !ispolar(sp)
|
||||||
|
ax[:spines][string(dir)][:set_visible](false)
|
||||||
|
end
|
||||||
|
kw[dir] = kw[Symbol(:label,dir)] = "off"
|
||||||
|
end
|
||||||
|
ax[:yaxis][:set_tick_params](; which="both", kw...)
|
||||||
|
end
|
||||||
|
|
||||||
# aspect ratio
|
# aspect ratio
|
||||||
aratio = sp[:aspect_ratio]
|
aratio = sp[:aspect_ratio]
|
||||||
if aratio != :none
|
if aratio != :none
|
||||||
ax[:set_aspect](isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C")
|
ax[:set_aspect](isa(aratio, Symbol) ? string(aratio) : aratio, anchor = "C")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
#camera/view angle
|
||||||
|
if is3d(sp)
|
||||||
|
#convert azimuthal to match GR behaviour
|
||||||
|
#view_init(elevation, azimuthal) so reverse :camera args
|
||||||
|
ax[:view_init]((sp[:camera].-(90,0))[end:-1:1]...)
|
||||||
|
end
|
||||||
|
|
||||||
# legend
|
# legend
|
||||||
py_add_legend(plt, sp, ax)
|
py_add_legend(plt, sp, ax)
|
||||||
|
|
||||||
@ -1178,10 +1226,19 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
|
|||||||
for series in series_list(sp)
|
for series in series_list(sp)
|
||||||
if should_add_to_legend(series)
|
if should_add_to_legend(series)
|
||||||
# add a line/marker and a label
|
# add a line/marker and a label
|
||||||
push!(handles, if series[:seriestype] == :shape
|
push!(handles, if series[:seriestype] == :shape || series[:fillrange] != nothing
|
||||||
|
pypatches[:Patch](
|
||||||
|
edgecolor = py_color(_cycle(series[:linecolor],1)),
|
||||||
|
facecolor = py_color(_cycle(series[:fillcolor],1)),
|
||||||
|
linewidth = py_dpi_scale(plt, clamp(series[:linewidth], 0, 5)),
|
||||||
|
)
|
||||||
|
elseif series[:seriestype] == :path
|
||||||
PyPlot.plt[:Line2D]((0,1),(0,0),
|
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)
|
linewidth = py_dpi_scale(plt, clamp(series[:linewidth], 0, 5)),
|
||||||
|
marker = py_marker(series[:markershape]),
|
||||||
|
markeredgecolor = py_markerstrokecolor(series),
|
||||||
|
markerfacecolor = py_markercolor(series)
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
series[:serieshandle][1]
|
series[:serieshandle][1]
|
||||||
@ -1196,7 +1253,7 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
|
|||||||
labels,
|
labels,
|
||||||
loc = get(_pyplot_legend_pos, leg, "best"),
|
loc = get(_pyplot_legend_pos, leg, "best"),
|
||||||
scatterpoints = 1,
|
scatterpoints = 1,
|
||||||
fontsize = py_dpi_scale(plt, sp[:legendfont].pointsize)
|
fontsize = py_dpi_scale(plt, sp[:legendfontsize])
|
||||||
# family = sp[:legendfont].family
|
# family = sp[:legendfont].family
|
||||||
# framealpha = 0.6
|
# framealpha = 0.6
|
||||||
)
|
)
|
||||||
@ -1204,8 +1261,9 @@ function py_add_legend(plt::Plot, sp::Subplot, ax)
|
|||||||
sp[:legendtitle] != nothing && leg[:set_title](sp[:legendtitle])
|
sp[:legendtitle] != nothing && leg[:set_title](sp[:legendtitle])
|
||||||
|
|
||||||
fgcolor = py_color(sp[:foreground_color_legend])
|
fgcolor = py_color(sp[:foreground_color_legend])
|
||||||
|
lfcolor = py_color(sp[:legendfontcolor])
|
||||||
for txt in leg[:get_texts]()
|
for txt in leg[:get_texts]()
|
||||||
PyPlot.plt[:setp](txt, color = fgcolor, family = sp[:legendfont].family)
|
PyPlot.plt[:setp](txt, color = lfcolor, family = sp[:legendfontfamily])
|
||||||
end
|
end
|
||||||
|
|
||||||
# set some legend properties
|
# set some legend properties
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
|
|
||||||
# https://github.com/Evizero/UnicodePlots.jl
|
# https://github.com/Evizero/UnicodePlots.jl
|
||||||
|
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "unicodeplots.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
const _unicodeplots_attr = merge_with_base_supported([
|
const _unicodeplots_attr = merge_with_base_supported([
|
||||||
:label,
|
:label,
|
||||||
:legend,
|
:legend,
|
||||||
|
|||||||
@ -2,7 +2,9 @@
|
|||||||
# NOTE: backend should implement `html_body` and `html_head`
|
# NOTE: backend should implement `html_body` and `html_head`
|
||||||
|
|
||||||
# CREDIT: parts of this implementation were inspired by @joshday's PlotlyLocal.jl
|
# CREDIT: parts of this implementation were inspired by @joshday's PlotlyLocal.jl
|
||||||
|
@require Revise begin
|
||||||
|
Revise.track(Plots, joinpath(Pkg.dir("Plots"), "src", "backends", "web.jl"))
|
||||||
|
end
|
||||||
|
|
||||||
function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr, :window_title, "Plots.jl"))
|
function standalone_html(plt::AbstractPlot; title::AbstractString = get(plt.attr, :window_title, "Plots.jl"))
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -11,7 +11,7 @@ compute_angle(v::P2) = (angle = atan2(v[2], v[1]); angle < 0 ? 2π - angle : ang
|
|||||||
|
|
||||||
# -------------------------------------------------------------
|
# -------------------------------------------------------------
|
||||||
|
|
||||||
immutable Shape
|
struct Shape
|
||||||
x::Vector{Float64}
|
x::Vector{Float64}
|
||||||
y::Vector{Float64}
|
y::Vector{Float64}
|
||||||
# function Shape(x::AVec, y::AVec)
|
# function Shape(x::AVec, y::AVec)
|
||||||
@ -246,7 +246,7 @@ end
|
|||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
type Font
|
mutable struct Font
|
||||||
family::AbstractString
|
family::AbstractString
|
||||||
pointsize::Int
|
pointsize::Int
|
||||||
halign::Symbol
|
halign::Symbol
|
||||||
@ -336,7 +336,7 @@ function scalefontsizes()
|
|||||||
end
|
end
|
||||||
|
|
||||||
"Wrap a string with font info"
|
"Wrap a string with font info"
|
||||||
immutable PlotText
|
struct PlotText
|
||||||
str::AbstractString
|
str::AbstractString
|
||||||
font::Font
|
font::Font
|
||||||
end
|
end
|
||||||
@ -359,7 +359,7 @@ Base.length(t::PlotText) = length(t.str)
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
|
|
||||||
immutable Stroke
|
struct Stroke
|
||||||
width
|
width
|
||||||
color
|
color
|
||||||
alpha
|
alpha
|
||||||
@ -401,7 +401,7 @@ function stroke(args...; alpha = nothing)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
immutable Brush
|
struct Brush
|
||||||
size # fillrange, markersize, or any other sizey attribute
|
size # fillrange, markersize, or any other sizey attribute
|
||||||
color
|
color
|
||||||
alpha
|
alpha
|
||||||
@ -434,7 +434,7 @@ end
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
|
|
||||||
type SeriesAnnotations
|
mutable struct SeriesAnnotations
|
||||||
strs::AbstractVector # the labels/names
|
strs::AbstractVector # the labels/names
|
||||||
font::Font
|
font::Font
|
||||||
baseshape::Nullable
|
baseshape::Nullable
|
||||||
@ -513,7 +513,7 @@ function series_annotations_shapes!(series::Series, scaletype::Symbol = :pixels)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
type EachAnn
|
mutable struct EachAnn
|
||||||
anns
|
anns
|
||||||
x
|
x
|
||||||
y
|
y
|
||||||
@ -538,12 +538,12 @@ annotations(sa::SeriesAnnotations) = sa
|
|||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
|
|
||||||
"type which represents z-values for colors and sizes (and anything else that might come up)"
|
"type which represents z-values for colors and sizes (and anything else that might come up)"
|
||||||
immutable ZValues
|
struct ZValues
|
||||||
values::Vector{Float64}
|
values::Vector{Float64}
|
||||||
zrange::Tuple{Float64,Float64}
|
zrange::Tuple{Float64,Float64}
|
||||||
end
|
end
|
||||||
|
|
||||||
function zvalues{T<:Real}(values::AVec{T}, zrange::Tuple{T,T} = (ignorenan_minimum(values), ignorenan_maximum(values)))
|
function zvalues(values::AVec{T}, zrange::Tuple{T,T} = (ignorenan_minimum(values), ignorenan_maximum(values))) where T<:Real
|
||||||
ZValues(collect(float(values)), map(Float64, zrange))
|
ZValues(collect(float(values)), map(Float64, zrange))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -552,7 +552,7 @@ end
|
|||||||
abstract type AbstractSurface end
|
abstract type AbstractSurface end
|
||||||
|
|
||||||
"represents a contour or surface mesh"
|
"represents a contour or surface mesh"
|
||||||
immutable Surface{M<:AMat} <: AbstractSurface
|
struct Surface{M<:AMat} <: AbstractSurface
|
||||||
surf::M
|
surf::M
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -564,7 +564,7 @@ for f in (:length, :size)
|
|||||||
@eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...)
|
@eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...)
|
||||||
end
|
end
|
||||||
Base.copy(surf::Surface) = Surface(copy(surf.surf))
|
Base.copy(surf::Surface) = Surface(copy(surf.surf))
|
||||||
Base.eltype{T}(surf::Surface{T}) = eltype(T)
|
Base.eltype(surf::Surface{T}) where {T} = eltype(T)
|
||||||
|
|
||||||
function expand_extrema!(a::Axis, surf::Surface)
|
function expand_extrema!(a::Axis, surf::Surface)
|
||||||
ex = a[:extrema]
|
ex = a[:extrema]
|
||||||
@ -575,7 +575,7 @@ function expand_extrema!(a::Axis, surf::Surface)
|
|||||||
end
|
end
|
||||||
|
|
||||||
"For the case of representing a surface as a function of x/y... can possibly avoid allocations."
|
"For the case of representing a surface as a function of x/y... can possibly avoid allocations."
|
||||||
immutable SurfaceFunction <: AbstractSurface
|
struct SurfaceFunction <: AbstractSurface
|
||||||
f::Function
|
f::Function
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -585,19 +585,19 @@ end
|
|||||||
# # I don't want to clash with ValidatedNumerics, but this would be nice:
|
# # I don't want to clash with ValidatedNumerics, but this would be nice:
|
||||||
# ..(a::T, b::T) = (a,b)
|
# ..(a::T, b::T) = (a,b)
|
||||||
|
|
||||||
immutable Volume{T}
|
struct Volume{T}
|
||||||
v::Array{T,3}
|
v::Array{T,3}
|
||||||
x_extents::Tuple{T,T}
|
x_extents::Tuple{T,T}
|
||||||
y_extents::Tuple{T,T}
|
y_extents::Tuple{T,T}
|
||||||
z_extents::Tuple{T,T}
|
z_extents::Tuple{T,T}
|
||||||
end
|
end
|
||||||
|
|
||||||
default_extents{T}(::Type{T}) = (zero(T), one(T))
|
default_extents(::Type{T}) where {T} = (zero(T), one(T))
|
||||||
|
|
||||||
function Volume{T}(v::Array{T,3},
|
function Volume(v::Array{T,3},
|
||||||
x_extents = default_extents(T),
|
x_extents = default_extents(T),
|
||||||
y_extents = default_extents(T),
|
y_extents = default_extents(T),
|
||||||
z_extents = default_extents(T))
|
z_extents = default_extents(T)) where T
|
||||||
Volume(v, x_extents, y_extents, z_extents)
|
Volume(v, x_extents, y_extents, z_extents)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -605,13 +605,13 @@ Base.Array(vol::Volume) = vol.v
|
|||||||
for f in (:length, :size)
|
for f in (:length, :size)
|
||||||
@eval Base.$f(vol::Volume, args...) = $f(vol.v, args...)
|
@eval Base.$f(vol::Volume, args...) = $f(vol.v, args...)
|
||||||
end
|
end
|
||||||
Base.copy{T}(vol::Volume{T}) = Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents)
|
Base.copy(vol::Volume{T}) where {T} = Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents)
|
||||||
Base.eltype{T}(vol::Volume{T}) = T
|
Base.eltype(vol::Volume{T}) where {T} = T
|
||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
|
|
||||||
# style is :open or :closed (for now)
|
# style is :open or :closed (for now)
|
||||||
immutable Arrow
|
struct Arrow
|
||||||
style::Symbol
|
style::Symbol
|
||||||
side::Symbol # :head (default), :tail, or :both
|
side::Symbol # :head (default), :tail, or :both
|
||||||
headlength::Float64
|
headlength::Float64
|
||||||
@ -673,14 +673,14 @@ end
|
|||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
|
|
||||||
"Represents data values with formatting that should apply to the tick labels."
|
"Represents data values with formatting that should apply to the tick labels."
|
||||||
immutable Formatted{T}
|
struct Formatted{T}
|
||||||
data::T
|
data::T
|
||||||
formatter::Function
|
formatter::Function
|
||||||
end
|
end
|
||||||
|
|
||||||
# -----------------------------------------------------------------------
|
# -----------------------------------------------------------------------
|
||||||
"create a BezierCurve for plotting"
|
"create a BezierCurve for plotting"
|
||||||
type BezierCurve{T <: FixedSizeArrays.Vec}
|
mutable struct BezierCurve{T <: FixedSizeArrays.Vec}
|
||||||
control_points::Vector{T}
|
control_points::Vector{T}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -558,7 +558,7 @@ function createGadflyAnnotationObject(x, y, txt::PlotText)
|
|||||||
))
|
))
|
||||||
end
|
end
|
||||||
|
|
||||||
function _add_annotations{X,Y,V}(plt::Plot{GadflyBackend}, anns::AVec{Tuple{X,Y,V}})
|
function _add_annotations(plt::Plot{GadflyBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
||||||
for ann in anns
|
for ann in anns
|
||||||
push!(plt.o.guides, createGadflyAnnotationObject(ann...))
|
push!(plt.o.guides, createGadflyAnnotationObject(ann...))
|
||||||
end
|
end
|
||||||
@ -614,7 +614,7 @@ function getxy(plt::Plot{GadflyBackend}, i::Integer)
|
|||||||
mapping[:x], mapping[:y]
|
mapping[:x], mapping[:y]
|
||||||
end
|
end
|
||||||
|
|
||||||
function setxy!{X,Y}(plt::Plot{GadflyBackend}, xy::Tuple{X,Y}, i::Integer)
|
function setxy!(plt::Plot{GadflyBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
|
||||||
for mapping in getGadflyMappings(plt, i)
|
for mapping in getGadflyMappings(plt, i)
|
||||||
mapping[:x], mapping[:y] = xy
|
mapping[:x], mapping[:y] = xy
|
||||||
end
|
end
|
||||||
@ -677,7 +677,7 @@ setGadflyDisplaySize(plt::Plot) = setGadflyDisplaySize(plt.attr[:size]...)
|
|||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
function doshow{P<:Union{GadflyBackend,ImmerseBackend}}(io::IO, func, plt::AbstractPlot{P})
|
function doshow(io::IO, func, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend}
|
||||||
gplt = getGadflyContext(plt)
|
gplt = getGadflyContext(plt)
|
||||||
setGadflyDisplaySize(plt)
|
setGadflyDisplaySize(plt)
|
||||||
Gadfly.draw(func(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
|
Gadfly.draw(func(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
|
||||||
@ -692,7 +692,7 @@ getGadflyWriteFunc(::MIME"application/x-tex") = Gadfly.PGF
|
|||||||
getGadflyWriteFunc(m::MIME) = error("Unsupported in Gadfly/Immerse: ", m)
|
getGadflyWriteFunc(m::MIME) = error("Unsupported in Gadfly/Immerse: ", m)
|
||||||
|
|
||||||
for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript", MIME"application/x-tex")
|
for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript", MIME"application/x-tex")
|
||||||
@eval function Base.show{P<:Union{GadflyBackend,ImmerseBackend}}(io::IO, ::$mime, plt::AbstractPlot{P})
|
@eval function Base.show(io::IO, ::$mime, plt::AbstractPlot{P}) where P<:Union{GadflyBackend,ImmerseBackend}
|
||||||
func = getGadflyWriteFunc($mime())
|
func = getGadflyWriteFunc($mime())
|
||||||
doshow(io, func, plt)
|
doshow(io, func, plt)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
# Geometry which displays arbitrary shapes at given (x, y) positions.
|
# Geometry which displays arbitrary shapes at given (x, y) positions.
|
||||||
# note: vertices is a list of shapes
|
# note: vertices is a list of shapes
|
||||||
immutable ShapeGeometry <: Gadfly.GeometryElement
|
struct ShapeGeometry <: Gadfly.GeometryElement
|
||||||
vertices::AbstractVector #{Tuple{Float64,Float64}}
|
vertices::AbstractVector #{Tuple{Float64,Float64}}
|
||||||
tag::Symbol
|
tag::Symbol
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ end
|
|||||||
|
|
||||||
# ----------------------------------------------------------------
|
# ----------------------------------------------------------------
|
||||||
|
|
||||||
function _add_annotations{X,Y,V}(plt::Plot{ImmerseBackend}, anns::AVec{Tuple{X,Y,V}})
|
function _add_annotations(plt::Plot{ImmerseBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
||||||
for ann in anns
|
for ann in anns
|
||||||
push!(getGadflyContext(plt).guides, createGadflyAnnotationObject(ann...))
|
push!(getGadflyContext(plt).guides, createGadflyAnnotationObject(ann...))
|
||||||
end
|
end
|
||||||
@ -76,7 +76,7 @@ function getxy(plt::Plot{ImmerseBackend}, i::Integer)
|
|||||||
mapping[:x], mapping[:y]
|
mapping[:x], mapping[:y]
|
||||||
end
|
end
|
||||||
|
|
||||||
function setxy!{X,Y}(plt::Plot{ImmerseBackend}, xy::Tuple{X,Y}, i::Integer)
|
function setxy!(plt::Plot{ImmerseBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
|
||||||
for mapping in getGadflyMappings(plt, i)
|
for mapping in getGadflyMappings(plt, i)
|
||||||
mapping[:x], mapping[:y] = xy
|
mapping[:x], mapping[:y] = xy
|
||||||
end
|
end
|
||||||
|
|||||||
@ -218,7 +218,7 @@ function createQwtAnnotation(plt::Plot, x, y, val::AbstractString)
|
|||||||
marker[:attach](plt.o.widget)
|
marker[:attach](plt.o.widget)
|
||||||
end
|
end
|
||||||
|
|
||||||
function _add_annotations{X,Y,V}(plt::Plot{QwtBackend}, anns::AVec{Tuple{X,Y,V}})
|
function _add_annotations(plt::Plot{QwtBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
||||||
for ann in anns
|
for ann in anns
|
||||||
createQwtAnnotation(plt, ann...)
|
createQwtAnnotation(plt, ann...)
|
||||||
end
|
end
|
||||||
@ -233,7 +233,7 @@ function getxy(plt::Plot{QwtBackend}, i::Int)
|
|||||||
series.x, series.y
|
series.x, series.y
|
||||||
end
|
end
|
||||||
|
|
||||||
function setxy!{X,Y}(plt::Plot{QwtBackend}, xy::Tuple{X,Y}, i::Integer)
|
function setxy!(plt::Plot{QwtBackend}, xy::Tuple{X,Y}, i::Integer) where {X,Y}
|
||||||
series = plt.o.lines[i]
|
series = plt.o.lines[i]
|
||||||
series.x, series.y = xy
|
series.x, series.y = xy
|
||||||
plt
|
plt
|
||||||
|
|||||||
@ -217,7 +217,7 @@ function createWinstonAnnotationObject(plt::Plot{WinstonBackend}, x, y, val::Abs
|
|||||||
Winston.text(x, y, val)
|
Winston.text(x, y, val)
|
||||||
end
|
end
|
||||||
|
|
||||||
function _add_annotations{X,Y,V}(plt::Plot{WinstonBackend}, anns::AVec{Tuple{X,Y,V}})
|
function _add_annotations(plt::Plot{WinstonBackend}, anns::AVec{Tuple{X,Y,V}}) where {X,Y,V}
|
||||||
for ann in anns
|
for ann in anns
|
||||||
createWinstonAnnotationObject(plt, ann...)
|
createWinstonAnnotationObject(plt, ann...)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -34,9 +34,9 @@ getColorVector(scheme::ColorScheme) = [getColor(scheme)]
|
|||||||
colorscheme(scheme::ColorScheme) = scheme
|
colorscheme(scheme::ColorScheme) = scheme
|
||||||
colorscheme(s::AbstractString; kw...) = colorscheme(Symbol(s); kw...)
|
colorscheme(s::AbstractString; kw...) = colorscheme(Symbol(s); kw...)
|
||||||
colorscheme(s::Symbol; kw...) = haskey(_gradients, s) ? ColorGradient(s; kw...) : ColorWrapper(convertColor(s); kw...)
|
colorscheme(s::Symbol; kw...) = haskey(_gradients, s) ? ColorGradient(s; kw...) : ColorWrapper(convertColor(s); kw...)
|
||||||
colorscheme{T<:Real}(s::Symbol, vals::AVec{T}; kw...) = ColorGradient(s, vals; kw...)
|
colorscheme(s::Symbol, vals::AVec{T}; kw...) where {T<:Real} = ColorGradient(s, vals; kw...)
|
||||||
colorscheme(cs::AVec, vs::AVec; kw...) = ColorGradient(cs, vs; kw...)
|
colorscheme(cs::AVec, vs::AVec; kw...) = ColorGradient(cs, vs; kw...)
|
||||||
colorscheme{T<:Colorant}(cs::AVec{T}; kw...) = ColorGradient(cs; kw...)
|
colorscheme(cs::AVec{T}; kw...) where {T<:Colorant} = ColorGradient(cs; kw...)
|
||||||
colorscheme(f::Function; kw...) = ColorFunction(f; kw...)
|
colorscheme(f::Function; kw...) = ColorFunction(f; kw...)
|
||||||
colorscheme(v::AVec; kw...) = ColorVector(v; kw...)
|
colorscheme(v::AVec; kw...) = ColorVector(v; kw...)
|
||||||
colorscheme(m::AMat; kw...) = size(m,1) == 1 ? map(c->colorscheme(c; kw...), m) : [colorscheme(m[:,i]; kw...) for i in 1:size(m,2)]'
|
colorscheme(m::AMat; kw...) = size(m,1) == 1 ? map(c->colorscheme(c; kw...), m) : [colorscheme(m[:,i]; kw...) for i in 1:size(m,2)]'
|
||||||
@ -98,7 +98,7 @@ const _gradients = KW(
|
|||||||
:lighttest => map(c -> lighten(c, 0.3), _testColors),
|
:lighttest => map(c -> lighten(c, 0.3), _testColors),
|
||||||
)
|
)
|
||||||
|
|
||||||
function register_gradient_colors{C<:Colorant}(name::Symbol, colors::AVec{C})
|
function register_gradient_colors(name::Symbol, colors::AVec{C}) where C<:Colorant
|
||||||
_gradients[name] = colors
|
_gradients[name] = colors
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -109,11 +109,11 @@ default_gradient() = ColorGradient(:inferno)
|
|||||||
# --------------------------------------------------------------
|
# --------------------------------------------------------------
|
||||||
|
|
||||||
"Continuous gradient between values. Wraps a list of bounding colors and the values they represent."
|
"Continuous gradient between values. Wraps a list of bounding colors and the values they represent."
|
||||||
immutable ColorGradient <: ColorScheme
|
struct ColorGradient <: ColorScheme
|
||||||
colors::Vector
|
colors::Vector
|
||||||
values::Vector
|
values::Vector
|
||||||
|
|
||||||
function ColorGradient{S<:Real}(cs::AVec, vals::AVec{S} = linspace(0, 1, length(cs)); alpha = nothing)
|
function ColorGradient(cs::AVec, vals::AVec{S} = linspace(0, 1, length(cs)); alpha = nothing) where S<:Real
|
||||||
if length(cs) == length(vals)
|
if length(cs) == length(vals)
|
||||||
return new(convertColor(cs,alpha), collect(vals))
|
return new(convertColor(cs,alpha), collect(vals))
|
||||||
end
|
end
|
||||||
@ -138,7 +138,7 @@ Base.getindex(cs::ColorGradient, z::Number) = getColorZ(cs, z)
|
|||||||
|
|
||||||
|
|
||||||
# create a gradient from a symbol (blues, reds, etc) and vector of boundary values
|
# create a gradient from a symbol (blues, reds, etc) and vector of boundary values
|
||||||
function ColorGradient{T<:Real}(s::Symbol, vals::AVec{T} = 0:0; kw...)
|
function ColorGradient(s::Symbol, vals::AVec{T} = 0:0; kw...) where T<:Real
|
||||||
haskey(_gradients, s) || error("Invalid gradient symbol. Choose from: ", sort(collect(keys(_gradients))))
|
haskey(_gradients, s) || error("Invalid gradient symbol. Choose from: ", sort(collect(keys(_gradients))))
|
||||||
cs = _gradients[s]
|
cs = _gradients[s]
|
||||||
if vals == 0:0
|
if vals == 0:0
|
||||||
@ -208,7 +208,7 @@ end
|
|||||||
# --------------------------------------------------------------
|
# --------------------------------------------------------------
|
||||||
|
|
||||||
"Wraps a function, taking an index and returning a Colorant"
|
"Wraps a function, taking an index and returning a Colorant"
|
||||||
immutable ColorFunction <: ColorScheme
|
struct ColorFunction <: ColorScheme
|
||||||
f::Function
|
f::Function
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ getColor(scheme::ColorFunction, idx::Int) = scheme.f(idx)
|
|||||||
# --------------------------------------------------------------
|
# --------------------------------------------------------------
|
||||||
|
|
||||||
"Wraps a function, taking an z-value and returning a Colorant"
|
"Wraps a function, taking an z-value and returning a Colorant"
|
||||||
immutable ColorZFunction <: ColorScheme
|
struct ColorZFunction <: ColorScheme
|
||||||
f::Function
|
f::Function
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -226,7 +226,7 @@ getColorZ(scheme::ColorZFunction, z::Real) = scheme.f(z)
|
|||||||
# --------------------------------------------------------------
|
# --------------------------------------------------------------
|
||||||
|
|
||||||
"Wraps a vector of colors... may be vector of Symbol/String/Colorant"
|
"Wraps a vector of colors... may be vector of Symbol/String/Colorant"
|
||||||
immutable ColorVector <: ColorScheme
|
struct ColorVector <: ColorScheme
|
||||||
v::Vector{Colorant}
|
v::Vector{Colorant}
|
||||||
ColorVector(v::AVec; alpha = nothing) = new(convertColor(v,alpha))
|
ColorVector(v::AVec; alpha = nothing) = new(convertColor(v,alpha))
|
||||||
end
|
end
|
||||||
@ -238,7 +238,7 @@ getColorVector(scheme::ColorVector) = scheme.v
|
|||||||
# --------------------------------------------------------------
|
# --------------------------------------------------------------
|
||||||
|
|
||||||
"Wraps a single color"
|
"Wraps a single color"
|
||||||
immutable ColorWrapper <: ColorScheme
|
struct ColorWrapper <: ColorScheme
|
||||||
c::RGBA
|
c::RGBA
|
||||||
ColorWrapper(c::Colorant; alpha = nothing) = new(convertColor(c, alpha))
|
ColorWrapper(c::Colorant; alpha = nothing) = new(convertColor(c, alpha))
|
||||||
end
|
end
|
||||||
@ -347,8 +347,8 @@ function get_color_palette(palette, bgcolor::Union{Colorant,ColorWrapper}, numco
|
|||||||
RGBA[getColorZ(grad, z) for z in zrng]
|
RGBA[getColorZ(grad, z) for z in zrng]
|
||||||
end
|
end
|
||||||
|
|
||||||
function get_color_palette{C<:Colorant}(palette::Vector{C},
|
function get_color_palette(palette::Vector{C},
|
||||||
bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer)
|
bgcolor::Union{Colorant,ColorWrapper}, numcolors::Integer) where C<:Colorant
|
||||||
palette
|
palette
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -5,21 +5,21 @@
|
|||||||
# This should cut down on boilerplate code and allow more focused dispatch on type
|
# 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
|
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
|
||||||
|
|
||||||
const FuncOrFuncs = @compat(Union{Function, AVec{Function}})
|
const FuncOrFuncs = Union{Function, AVec{Function}}
|
||||||
|
|
||||||
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
|
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
|
||||||
|
|
||||||
# missing
|
# missing
|
||||||
convertToAnyVector(v::@compat(Void), d::KW) = Any[nothing], nothing
|
convertToAnyVector(v::Void, d::KW) = Any[nothing], nothing
|
||||||
|
|
||||||
# fixed number of blank series
|
# fixed number of blank series
|
||||||
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing
|
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing
|
||||||
|
|
||||||
# numeric vector
|
# numeric vector
|
||||||
convertToAnyVector{T<:Number}(v::AVec{T}, d::KW) = Any[v], nothing
|
convertToAnyVector(v::AVec{T}, d::KW) where {T<:Number} = Any[v], nothing
|
||||||
|
|
||||||
# string vector
|
# string vector
|
||||||
convertToAnyVector{T<:@compat(AbstractString)}(v::AVec{T}, d::KW) = Any[v], nothing
|
convertToAnyVector(v::AVec{T}, d::KW) where {T<:AbstractString} = Any[v], nothing
|
||||||
|
|
||||||
function convertToAnyVector(v::AMat, d::KW)
|
function convertToAnyVector(v::AMat, d::KW)
|
||||||
if all3D(d)
|
if all3D(d)
|
||||||
@ -39,7 +39,7 @@ convertToAnyVector(s::Surface, d::KW) = Any[s], nothing
|
|||||||
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing
|
# convertToAnyVector(v::AVec{OHLC}, d::KW) = Any[v], nothing
|
||||||
|
|
||||||
# dates
|
# dates
|
||||||
convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}, d::KW) = Any[dts], nothing
|
convertToAnyVector(dts::AVec{D}, d::KW) where {D<:Union{Date,DateTime}} = Any[dts], nothing
|
||||||
|
|
||||||
# list of things (maybe other vectors, functions, or something else)
|
# list of things (maybe other vectors, functions, or something else)
|
||||||
function convertToAnyVector(v::AVec, d::KW)
|
function convertToAnyVector(v::AVec, d::KW)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Holds all data needed for a documentation example... header, description, and plotting expression (Expr)
|
Holds all data needed for a documentation example... header, description, and plotting expression (Expr)
|
||||||
"""
|
"""
|
||||||
type PlotExample
|
mutable struct PlotExample
|
||||||
header::AbstractString
|
header::AbstractString
|
||||||
desc::AbstractString
|
desc::AbstractString
|
||||||
exprs::Vector{Expr}
|
exprs::Vector{Expr}
|
||||||
@ -172,7 +172,7 @@ PlotExample("Bar",
|
|||||||
PlotExample("Histogram",
|
PlotExample("Histogram",
|
||||||
"",
|
"",
|
||||||
[:(begin
|
[:(begin
|
||||||
histogram(randn(1000), nbins=20)
|
histogram(randn(1000), bins = :scott, weights = repeat(1:5, outer = 200))
|
||||||
end)]
|
end)]
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ PlotExample("DataFrames",
|
|||||||
[:(begin
|
[:(begin
|
||||||
import RDatasets
|
import RDatasets
|
||||||
iris = RDatasets.dataset("datasets", "iris")
|
iris = RDatasets.dataset("datasets", "iris")
|
||||||
scatter(iris, :SepalLength, :SepalWidth, group=:Species,
|
@df iris scatter(:SepalLength, :SepalWidth, group=:Species,
|
||||||
title = "My awesome plot", xlabel = "Length", ylabel = "Width",
|
title = "My awesome plot", xlabel = "Length", ylabel = "Width",
|
||||||
marker = (0.5, [:cross :hex :star7], 12), bg=RGB(.2,.2,.2))
|
marker = (0.5, [:cross :hex :star7], 12), bg=RGB(.2,.2,.2))
|
||||||
end)]
|
end)]
|
||||||
@ -314,9 +314,9 @@ PlotExample("DataFrames",
|
|||||||
PlotExample("Groups and Subplots",
|
PlotExample("Groups and Subplots",
|
||||||
"",
|
"",
|
||||||
[:(begin
|
[:(begin
|
||||||
group = rand(map(i->"group $i",1:4),100)
|
group = rand(map(i->"group $i",1:4),100)
|
||||||
plot(rand(100), layout=@layout([a b;c]), group=group,
|
plot(rand(100), layout=@layout([a b;c]), group=group,
|
||||||
linetype=[:bar :scatter :steppre])
|
linetype=[:bar :scatter :steppre], linecolor = :match)
|
||||||
end)]
|
end)]
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -354,8 +354,8 @@ PlotExample("Boxplot and Violin series recipes",
|
|||||||
[:(begin
|
[:(begin
|
||||||
import RDatasets
|
import RDatasets
|
||||||
singers = RDatasets.dataset("lattice", "singer")
|
singers = RDatasets.dataset("lattice", "singer")
|
||||||
violin(singers, :VoicePart, :Height, line = 0, fill = (0.2, :blue))
|
@df singers violin(:VoicePart, :Height, line = 0, fill = (0.2, :blue))
|
||||||
boxplot!(singers, :VoicePart, :Height, line = (2,:black), fill = (0.3, :orange))
|
@df singers boxplot!(:VoicePart, :Height, line = (2,:black), fill = (0.3, :orange))
|
||||||
end)]
|
end)]
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -377,16 +377,14 @@ PlotExample("Animation with subplots",
|
|||||||
|
|
||||||
PlotExample("Spy",
|
PlotExample("Spy",
|
||||||
"""
|
"""
|
||||||
For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat`
|
For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat` has
|
||||||
has various different nonzero values, a colorbar is added. The colorbar can be disabled
|
various different nonzero values, a colorbar is added. The colorbar can be disabled with
|
||||||
with `legend = nothing`. As always, the marker shape and size can be changed with
|
`legend = nothing`.
|
||||||
`spy(mat, markersize = 3, markershape = :star)`.
|
"""
|
||||||
""",
|
|
||||||
[:(begin
|
[:(begin
|
||||||
a = spdiagm((ones(50), ones(49), ones(49), ones(40), ones(40)),(0, 1, -1, 10, -10))
|
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))
|
b = spdiagm((1:50, 1:49, 1:49, 1:40, 1:40),(0, 1, -1, 10, -10))
|
||||||
plot(spy(a, markershape = :dtriangle), spy(b), markersize = 3,
|
plot(spy(a), spy(b), title = ["Unique nonzeros" "Different nonzeros"])
|
||||||
title = ["Unique nonzeros" "Different nonzeros"])
|
|
||||||
end)]
|
end)]
|
||||||
),
|
),
|
||||||
|
|
||||||
@ -410,9 +408,11 @@ The style of the frame/axes of a (sub)plot can be changed with the `framestyle`
|
|||||||
attribute. The default framestyle is `:axes`.
|
attribute. The default framestyle is `:axes`.
|
||||||
""",
|
""",
|
||||||
[:(begin
|
[:(begin
|
||||||
histogram(fill(randn(1000), 5), framestyle = [:box :semi :axes :grid :none],
|
scatter(fill(randn(10), 6), fill(randn(10), 6),
|
||||||
title = [":box" ":semi" ":axes" ":grid" ":none"],
|
framestyle = [:box :semi :origin :zerolines :grid :none],
|
||||||
color = RowVector(1:5), layout = 5, label = "")
|
title = [":box" ":semi" ":origin" ":zerolines" ":grid" ":none"],
|
||||||
|
color = RowVector(1:6), layout = 6, label = "", markerstrokewidth = 0,
|
||||||
|
ticks = -2:2)
|
||||||
end)]
|
end)]
|
||||||
),
|
),
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,6 @@
|
|||||||
|
|
||||||
# NOTE: (0,0) is the top-left !!!
|
# NOTE: (0,0) is the top-left !!!
|
||||||
|
|
||||||
# allow pixels and percentages
|
|
||||||
const px = AbsoluteLength(0.254)
|
|
||||||
const pct = Length{:pct, Float64}(1.0)
|
|
||||||
|
|
||||||
to_pixels(m::AbsoluteLength) = m.value / 0.254
|
to_pixels(m::AbsoluteLength) = m.value / 0.254
|
||||||
|
|
||||||
const _cbar_width = 5mm
|
const _cbar_width = 5mm
|
||||||
@ -17,7 +13,7 @@ Base.zero(::Type{typeof(mm)}) = 0mm
|
|||||||
Base.one(::Type{typeof(mm)}) = 1mm
|
Base.one(::Type{typeof(mm)}) = 1mm
|
||||||
Base.typemin(::typeof(mm)) = -Inf*mm
|
Base.typemin(::typeof(mm)) = -Inf*mm
|
||||||
Base.typemax(::typeof(mm)) = Inf*mm
|
Base.typemax(::typeof(mm)) = Inf*mm
|
||||||
Base.convert{F<:AbstractFloat}(::Type{F}, l::AbsoluteLength) = convert(F, l.value)
|
Base.convert(::Type{F}, l::AbsoluteLength) where {F<:AbstractFloat} = convert(F, l.value)
|
||||||
|
|
||||||
# TODO: these are unintuitive and may cause tricky bugs
|
# TODO: these are unintuitive and may cause tricky bugs
|
||||||
# Base.:+(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * (1 + m2.value))
|
# Base.:+(m1::AbsoluteLength, m2::Length{:pct}) = AbsoluteLength(m1.value * (1 + m2.value))
|
||||||
@ -99,7 +95,7 @@ end
|
|||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# points combined by x/y, pct, and length
|
# points combined by x/y, pct, and length
|
||||||
type MixedMeasures
|
mutable struct MixedMeasures
|
||||||
xy::Float64
|
xy::Float64
|
||||||
pct::Float64
|
pct::Float64
|
||||||
len::AbsoluteLength
|
len::AbsoluteLength
|
||||||
@ -220,7 +216,7 @@ bottompad(layout::AbstractLayout) = 0mm
|
|||||||
# RootLayout
|
# RootLayout
|
||||||
|
|
||||||
# this is the parent of the top-level layout
|
# this is the parent of the top-level layout
|
||||||
immutable RootLayout <: AbstractLayout end
|
struct RootLayout <: AbstractLayout end
|
||||||
|
|
||||||
Base.parent(::RootLayout) = nothing
|
Base.parent(::RootLayout) = nothing
|
||||||
parent_bbox(::RootLayout) = defaultbox
|
parent_bbox(::RootLayout) = defaultbox
|
||||||
@ -230,7 +226,7 @@ bbox(::RootLayout) = defaultbox
|
|||||||
# EmptyLayout
|
# EmptyLayout
|
||||||
|
|
||||||
# contains blank space
|
# contains blank space
|
||||||
type EmptyLayout <: AbstractLayout
|
mutable struct EmptyLayout <: AbstractLayout
|
||||||
parent::AbstractLayout
|
parent::AbstractLayout
|
||||||
bbox::BoundingBox
|
bbox::BoundingBox
|
||||||
attr::KW # store label, width, and height for initialization
|
attr::KW # store label, width, and height for initialization
|
||||||
@ -248,7 +244,7 @@ _update_min_padding!(layout::EmptyLayout) = nothing
|
|||||||
# GridLayout
|
# GridLayout
|
||||||
|
|
||||||
# nested, gridded layout with optional size percentages
|
# nested, gridded layout with optional size percentages
|
||||||
type GridLayout <: AbstractLayout
|
mutable struct GridLayout <: AbstractLayout
|
||||||
parent::AbstractLayout
|
parent::AbstractLayout
|
||||||
minpad::Tuple # leftpad, toppad, rightpad, bottompad
|
minpad::Tuple # leftpad, toppad, rightpad, bottompad
|
||||||
bbox::BoundingBox
|
bbox::BoundingBox
|
||||||
@ -485,12 +481,12 @@ function layout_args(n::Integer)
|
|||||||
GridLayout(nr, nc), n
|
GridLayout(nr, nc), n
|
||||||
end
|
end
|
||||||
|
|
||||||
function layout_args{I<:Integer}(sztup::NTuple{2,I})
|
function layout_args(sztup::NTuple{2,I}) where I<:Integer
|
||||||
nr, nc = sztup
|
nr, nc = sztup
|
||||||
GridLayout(nr, nc), nr*nc
|
GridLayout(nr, nc), nr*nc
|
||||||
end
|
end
|
||||||
|
|
||||||
function layout_args{I<:Integer}(sztup::NTuple{3,I})
|
function layout_args(sztup::NTuple{3,I}) where I<:Integer
|
||||||
n, nr, nc = sztup
|
n, nr, nc = sztup
|
||||||
nr, nc = compute_gridsize(n, nr, nc)
|
nr, nc = compute_gridsize(n, nr, nc)
|
||||||
GridLayout(nr, nc), n
|
GridLayout(nr, nc), n
|
||||||
|
|||||||
@ -193,7 +193,7 @@ function Base.show(io::IO, ::MIME"text/html", plt::Plot)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function _show{B}(io::IO, m, plt::Plot{B})
|
function _show(io::IO, m, plt::Plot{B}) where B
|
||||||
# Base.show_backtrace(STDOUT, backtrace())
|
# Base.show_backtrace(STDOUT, backtrace())
|
||||||
warn("_show is not defined for this backend. m=", string(m))
|
warn("_show is not defined for this backend. m=", string(m))
|
||||||
end
|
end
|
||||||
@ -203,7 +203,7 @@ end
|
|||||||
|
|
||||||
# for writing to io streams... first prepare, then callback
|
# for writing to io streams... first prepare, then callback
|
||||||
for mime in keys(_mimeformats)
|
for mime in keys(_mimeformats)
|
||||||
@eval function Base.show{B}(io::IO, m::MIME{Symbol($mime)}, plt::Plot{B})
|
@eval function Base.show(io::IO, m::MIME{Symbol($mime)}, plt::Plot{B}) where B
|
||||||
prepare_output(plt)
|
prepare_output(plt)
|
||||||
_show(io, m, plt)
|
_show(io, m, plt)
|
||||||
end
|
end
|
||||||
@ -258,7 +258,6 @@ end
|
|||||||
|
|
||||||
const _ijulia_output = String["text/html"]
|
const _ijulia_output = String["text/html"]
|
||||||
|
|
||||||
using Requires
|
|
||||||
@require IJulia begin
|
@require IJulia begin
|
||||||
if IJulia.inited
|
if IJulia.inited
|
||||||
export set_ijulia_output
|
export set_ijulia_output
|
||||||
@ -293,7 +292,7 @@ end
|
|||||||
Media.media(Plot, Media.Plot)
|
Media.media(Plot, Media.Plot)
|
||||||
|
|
||||||
|
|
||||||
_show{B}(io::IO, m::MIME"text/plain", plt::Plot{B}) = print(io, "Plot{$B}()")
|
_show(io::IO, m::MIME"text/plain", plt::Plot{B}) where {B} = print(io, "Plot{$B}()")
|
||||||
|
|
||||||
function Juno.render(e::Juno.Editor, plt::Plot)
|
function Juno.render(e::Juno.Editor, plt::Plot)
|
||||||
Juno.render(e, nothing)
|
Juno.render(e, nothing)
|
||||||
|
|||||||
@ -301,7 +301,7 @@ end
|
|||||||
|
|
||||||
# getting ready to add the series... last update to subplot from anything
|
# getting ready to add the series... last update to subplot from anything
|
||||||
# that might have been added during series recipes
|
# that might have been added during series recipes
|
||||||
function _prepare_subplot{T}(plt::Plot{T}, d::KW)
|
function _prepare_subplot(plt::Plot{T}, d::KW) where T
|
||||||
st::Symbol = d[:seriestype]
|
st::Symbol = d[:seriestype]
|
||||||
sp::Subplot{T} = d[:subplot]
|
sp::Subplot{T} = d[:subplot]
|
||||||
sp_idx = get_subplot_index(plt, sp)
|
sp_idx = get_subplot_index(plt, sp)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
type CurrentPlot
|
mutable struct CurrentPlot
|
||||||
nullableplot::Nullable{AbstractPlot}
|
nullableplot::Nullable{AbstractPlot}
|
||||||
end
|
end
|
||||||
const CURRENT_PLOT = CurrentPlot(Nullable{AbstractPlot}())
|
const CURRENT_PLOT = CurrentPlot(Nullable{AbstractPlot}())
|
||||||
|
|||||||
@ -47,7 +47,7 @@ end
|
|||||||
num_series(x::AMat) = size(x,2)
|
num_series(x::AMat) = size(x,2)
|
||||||
num_series(x) = 1
|
num_series(x) = 1
|
||||||
|
|
||||||
RecipesBase.apply_recipe{T}(d::KW, ::Type{T}, plt::AbstractPlot) = throw(MethodError("Unmatched plot recipe: $T"))
|
RecipesBase.apply_recipe(d::KW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError("Unmatched plot recipe: $T"))
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -343,9 +343,9 @@ _bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2
|
|||||||
|
|
||||||
_is_positive(x) = (x > 0) && !(x ≈ 0)
|
_is_positive(x) = (x > 0) && !(x ≈ 0)
|
||||||
|
|
||||||
_positive_else_nan{T}(::Type{T}, x::Real) = _is_positive(x) ? T(x) : T(NaN)
|
_positive_else_nan(::Type{T}, x::Real) where {T} = _is_positive(x) ? T(x) : T(NaN)
|
||||||
|
|
||||||
function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector, scale::Symbol)
|
function _scale_adjusted_values(::Type{T}, V::AbstractVector, scale::Symbol) where T<:AbstractFloat
|
||||||
if scale in _logScales
|
if scale in _logScales
|
||||||
[_positive_else_nan(T, x) for x in V]
|
[_positive_else_nan(T, x) for x in V]
|
||||||
else
|
else
|
||||||
@ -354,7 +354,7 @@ function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector,
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol)
|
function _binbarlike_baseline(min_value::T, scale::Symbol) where T<:Real
|
||||||
if (scale in _logScales)
|
if (scale in _logScales)
|
||||||
!isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3)
|
!isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3)
|
||||||
else
|
else
|
||||||
@ -363,7 +363,7 @@ function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol)
|
function _preprocess_binbarlike_weights(::Type{T}, w, wscale::Symbol) where T<:AbstractFloat
|
||||||
w_adj = _scale_adjusted_values(T, w, wscale)
|
w_adj = _scale_adjusted_values(T, w, wscale)
|
||||||
w_min = ignorenan_minimum(w_adj)
|
w_min = ignorenan_minimum(w_adj)
|
||||||
w_max = ignorenan_maximum(w_adj)
|
w_max = ignorenan_maximum(w_adj)
|
||||||
@ -499,7 +499,7 @@ Plots.@deps stepbins path
|
|||||||
|
|
||||||
wand_edges(x...) = (warn("Load the StatPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto)
|
wand_edges(x...) = (warn("Load the StatPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto)
|
||||||
|
|
||||||
function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto)
|
function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) where N
|
||||||
_cl(x) = ceil(Int, NaNMath.max(x, one(x)))
|
_cl(x) = ceil(Int, NaNMath.max(x, one(x)))
|
||||||
_iqr(v) = (q = quantile(v, 0.75) - quantile(v, 0.25); q > 0 ? q : oftype(q, 1))
|
_iqr(v) = (q = quantile(v, 0.75) - quantile(v, 0.25); q > 0 ? q : oftype(q, 1))
|
||||||
_span(v) = ignorenan_maximum(v) - ignorenan_minimum(v)
|
_span(v) = ignorenan_maximum(v) - ignorenan_minimum(v)
|
||||||
@ -533,24 +533,24 @@ function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) = StatsBase.histrange(vs[dim], binning, :left)
|
_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) where {N} = StatsBase.histrange(vs[dim], binning, :left)
|
||||||
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) = _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning))
|
_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) where {N} = _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning))
|
||||||
_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) = binning
|
_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) where {N} = binning
|
||||||
|
|
||||||
_hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::NTuple{N}) =
|
_hist_edges(vs::NTuple{N,AbstractVector}, binning::NTuple{N}) where {N} =
|
||||||
map(dim -> _hist_edge(vs, dim, binning[dim]), (1:N...))
|
map(dim -> _hist_edge(vs, dim, binning[dim]), (1:N...))
|
||||||
|
|
||||||
_hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, AbstractVector}) =
|
_hist_edges(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, AbstractVector}) where {N} =
|
||||||
map(dim -> _hist_edge(vs, dim, binning), (1:N...))
|
map(dim -> _hist_edge(vs, dim, binning), (1:N...))
|
||||||
|
|
||||||
_hist_norm_mode(mode::Symbol) = mode
|
_hist_norm_mode(mode::Symbol) = mode
|
||||||
_hist_norm_mode(mode::Bool) = mode ? :pdf : :none
|
_hist_norm_mode(mode::Bool) = mode ? :pdf : :none
|
||||||
|
|
||||||
function _make_hist{N}(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing)
|
function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N
|
||||||
edges = _hist_edges(vs, binning)
|
edges = _hist_edges(vs, binning)
|
||||||
h = float( weights == nothing ?
|
h = float( weights == nothing ?
|
||||||
StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) :
|
StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) :
|
||||||
StatsBase.fit(StatsBase.Histogram, vs, weights, edges, closed = :left)
|
StatsBase.fit(StatsBase.Histogram, vs, StatsBase.Weights(weights), edges, closed = :left)
|
||||||
)
|
)
|
||||||
normalize!(h, mode = _hist_norm_mode(normed))
|
normalize!(h, mode = _hist_norm_mode(normed))
|
||||||
end
|
end
|
||||||
@ -590,7 +590,7 @@ end
|
|||||||
@deps scatterhist scatterbins
|
@deps scatterhist scatterbins
|
||||||
|
|
||||||
|
|
||||||
@recipe function f{T, E}(h::StatsBase.Histogram{T, 1, E})
|
@recipe function f(h::StatsBase.Histogram{T, 1, E}) where {T, E}
|
||||||
seriestype --> :barbins
|
seriestype --> :barbins
|
||||||
|
|
||||||
st_map = Dict(
|
st_map = Dict(
|
||||||
@ -611,7 +611,7 @@ end
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@recipe function f{H <: StatsBase.Histogram}(hv::AbstractVector{H})
|
@recipe function f(hv::AbstractVector{H}) where H <: StatsBase.Histogram
|
||||||
for h in hv
|
for h in hv
|
||||||
@series begin
|
@series begin
|
||||||
h
|
h
|
||||||
@ -658,7 +658,7 @@ end
|
|||||||
@deps histogram2d bins2d
|
@deps histogram2d bins2d
|
||||||
|
|
||||||
|
|
||||||
@recipe function f{T, E}(h::StatsBase.Histogram{T, 2, E})
|
@recipe function f(h::StatsBase.Histogram{T, 2, E}) where {T, E}
|
||||||
seriestype --> :bins2d
|
seriestype --> :bins2d
|
||||||
(h.edges[1], h.edges[2], Surface(h.weights))
|
(h.edges[1], h.edges[2], Surface(h.weights))
|
||||||
end
|
end
|
||||||
@ -855,7 +855,7 @@ end
|
|||||||
# TODO: move OHLC to PlotRecipes finance.jl
|
# TODO: move OHLC to PlotRecipes finance.jl
|
||||||
|
|
||||||
"Represent Open High Low Close data (used in finance)"
|
"Represent Open High Low Close data (used in finance)"
|
||||||
type OHLC{T<:Real}
|
mutable struct OHLC{T<:Real}
|
||||||
open::T
|
open::T
|
||||||
high::T
|
high::T
|
||||||
low::T
|
low::T
|
||||||
@ -894,10 +894,10 @@ end
|
|||||||
|
|
||||||
# to squash ambiguity warnings...
|
# to squash ambiguity warnings...
|
||||||
@recipe f(x::AVec{Function}, v::AVec{OHLC}) = error()
|
@recipe f(x::AVec{Function}, v::AVec{OHLC}) = error()
|
||||||
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(x::AVec{Function}, v::AVec{Tuple{R1,R2,R3,R4}}) = error()
|
@recipe f(x::AVec{Function}, v::AVec{Tuple{R1,R2,R3,R4}}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = error()
|
||||||
|
|
||||||
# this must be OHLC?
|
# this must be OHLC?
|
||||||
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(x::AVec, ohlc::AVec{Tuple{R1,R2,R3,R4}}) = x, OHLC[OHLC(t...) for t in ohlc]
|
@recipe f(x::AVec, ohlc::AVec{Tuple{R1,R2,R3,R4}}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = x, OHLC[OHLC(t...) for t in ohlc]
|
||||||
|
|
||||||
@recipe function f(x::AVec, v::AVec{OHLC})
|
@recipe function f(x::AVec, v::AVec{OHLC})
|
||||||
seriestype := :path
|
seriestype := :path
|
||||||
@ -937,6 +937,7 @@ end
|
|||||||
mat = g.args[1]
|
mat = g.args[1]
|
||||||
if length(unique(mat[mat .!= 0])) < 2
|
if length(unique(mat[mat .!= 0])) < 2
|
||||||
legend --> nothing
|
legend --> nothing
|
||||||
|
seriescolor --> cgrad([invisible(), fg_color(plotattributes)])
|
||||||
end
|
end
|
||||||
n,m = size(mat)
|
n,m = size(mat)
|
||||||
Plots.SliceIt, 1:m, 1:n, Surface(mat)
|
Plots.SliceIt, 1:m, 1:n, Surface(mat)
|
||||||
@ -945,23 +946,21 @@ end
|
|||||||
@recipe function f(::Type{Val{:spy}}, x,y,z)
|
@recipe function f(::Type{Val{:spy}}, x,y,z)
|
||||||
yflip := true
|
yflip := true
|
||||||
aspect_ratio := 1
|
aspect_ratio := 1
|
||||||
|
|
||||||
rs, cs, zs = findnz(z.surf)
|
rs, cs, zs = findnz(z.surf)
|
||||||
xlim := ignorenan_extrema(cs)
|
newz = fill(NaN, size(z)...)
|
||||||
ylim := ignorenan_extrema(rs)
|
|
||||||
if plotattributes[:markershape] == :none
|
for i in eachindex(zs)
|
||||||
markershape := :circle
|
newz[rs[i],cs[i]] = zs[i]
|
||||||
end
|
end
|
||||||
if plotattributes[:markersize] == default(:markersize)
|
|
||||||
markersize := 1
|
seriestype := :heatmap
|
||||||
end
|
|
||||||
markerstrokewidth := 0
|
|
||||||
marker_z := zs
|
|
||||||
label := ""
|
|
||||||
x := cs
|
|
||||||
y := rs
|
|
||||||
z := nothing
|
|
||||||
seriestype := :scatter
|
|
||||||
grid --> false
|
grid --> false
|
||||||
|
framestyle --> :box
|
||||||
|
|
||||||
|
x := x
|
||||||
|
y := y
|
||||||
|
z := Surface(newz)
|
||||||
()
|
()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -987,7 +986,7 @@ datetimeformatter(dt) = string(DateTime(Dates.UTM(dt)))
|
|||||||
# -------------------------------------------------
|
# -------------------------------------------------
|
||||||
# Complex Numbers
|
# Complex Numbers
|
||||||
|
|
||||||
@recipe function f{T<:Number}(A::Array{Complex{T}})
|
@recipe function f(A::Array{Complex{T}}) where T<:Number
|
||||||
xguide --> "Re(x)"
|
xguide --> "Re(x)"
|
||||||
yguide --> "Im(x)"
|
yguide --> "Im(x)"
|
||||||
real.(A), imag.(A)
|
real.(A), imag.(A)
|
||||||
@ -996,7 +995,7 @@ end
|
|||||||
# Splits a complex matrix to its real and complex parts
|
# Splits a complex matrix to its real and complex parts
|
||||||
# Reals defaults solid, imaginary defaults dashed
|
# Reals defaults solid, imaginary defaults dashed
|
||||||
# Label defaults are changed to match the real-imaginary reference / indexing
|
# Label defaults are changed to match the real-imaginary reference / indexing
|
||||||
@recipe function f{T<:Real,T2}(x::AbstractArray{T},y::Array{Complex{T2}})
|
@recipe function f(x::AbstractArray{T},y::Array{Complex{T2}}) where {T<:Real,T2}
|
||||||
ylabel --> "Re(y)"
|
ylabel --> "Re(y)"
|
||||||
zlabel --> "Im(y)"
|
zlabel --> "Im(y)"
|
||||||
x,real.(y),imag.(y)
|
x,real.(y),imag.(y)
|
||||||
|
|||||||
@ -20,10 +20,10 @@ convertToAnyVector(v::Void, d::KW) = Any[nothing], nothing
|
|||||||
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing
|
convertToAnyVector(n::Integer, d::KW) = Any[zeros(0) for i in 1:n], nothing
|
||||||
|
|
||||||
# numeric vector
|
# numeric vector
|
||||||
convertToAnyVector{T<:Number}(v::AVec{T}, d::KW) = Any[v], nothing
|
convertToAnyVector(v::AVec{T}, d::KW) where {T<:Number} = Any[v], nothing
|
||||||
|
|
||||||
# string vector
|
# string vector
|
||||||
convertToAnyVector{T<:AbstractString}(v::AVec{T}, d::KW) = Any[v], nothing
|
convertToAnyVector(v::AVec{T}, d::KW) where {T<:AbstractString} = Any[v], nothing
|
||||||
|
|
||||||
function convertToAnyVector(v::AMat, d::KW)
|
function convertToAnyVector(v::AMat, d::KW)
|
||||||
if all3D(d)
|
if all3D(d)
|
||||||
@ -99,8 +99,8 @@ nobigs(v) = v
|
|||||||
end
|
end
|
||||||
|
|
||||||
# not allowed
|
# not allowed
|
||||||
compute_xyz{F<:Function}(x::Void, y::FuncOrFuncs{F}, z) = error("If you want to plot the function `$y`, you need to define the x values!")
|
compute_xyz(x::Void, y::FuncOrFuncs{F}, z) where {F<:Function} = error("If you want to plot the function `$y`, you need to define the x values!")
|
||||||
compute_xyz{F<:Function}(x::Void, y::Void, z::FuncOrFuncs{F}) = error("If you want to plot the function `$z`, you need to define x and y values!")
|
compute_xyz(x::Void, y::Void, z::FuncOrFuncs{F}) where {F<:Function} = error("If you want to plot the function `$z`, you need to define x and y values!")
|
||||||
compute_xyz(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
|
compute_xyz(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
|
||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
@ -109,7 +109,7 @@ compute_xyz(x::Void, y::Void, z::Void) = error("x/y/z are all nothing!")
|
|||||||
# we are going to build recipes to do the processing and splitting of the args
|
# we are going to build recipes to do the processing and splitting of the args
|
||||||
|
|
||||||
# ensure we dispatch to the slicer
|
# ensure we dispatch to the slicer
|
||||||
immutable SliceIt end
|
struct SliceIt end
|
||||||
|
|
||||||
# the catch-all recipes
|
# the catch-all recipes
|
||||||
@recipe function f(::Type{SliceIt}, x, y, z)
|
@recipe function f(::Type{SliceIt}, x, y, z)
|
||||||
@ -163,10 +163,10 @@ immutable SliceIt end
|
|||||||
end
|
end
|
||||||
|
|
||||||
# this is the default "type recipe"... just pass the object through
|
# this is the default "type recipe"... just pass the object through
|
||||||
@recipe f{T<:Any}(::Type{T}, v::T) = v
|
@recipe f(::Type{T}, v::T) where {T<:Any} = v
|
||||||
|
|
||||||
# this should catch unhandled "series recipes" and error with a nice message
|
# this should catch unhandled "series recipes" and error with a nice message
|
||||||
@recipe f{V<:Val}(::Type{V}, x, y, z) = error("The backend must not support the series type $V, and there isn't a series recipe defined.")
|
@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.")
|
||||||
|
|
||||||
_apply_type_recipe(d, v) = RecipesBase.apply_recipe(d, typeof(v), v)[1].args[1]
|
_apply_type_recipe(d, v) = RecipesBase.apply_recipe(d, typeof(v), v)[1].args[1]
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ end
|
|||||||
# end
|
# end
|
||||||
|
|
||||||
# don't do anything for ints or floats
|
# don't do anything for ints or floats
|
||||||
_apply_type_recipe{T<:Union{Integer,AbstractFloat}}(d, v::AbstractArray{T}) = v
|
_apply_type_recipe(d, v::AbstractArray{T}) where {T<:Union{Integer,AbstractFloat}} = v
|
||||||
|
|
||||||
# handle "type recipes" by converting inputs, and then either re-calling or slicing
|
# handle "type recipes" by converting inputs, and then either re-calling or slicing
|
||||||
@recipe function f(x, y, z)
|
@recipe function f(x, y, z)
|
||||||
@ -274,7 +274,7 @@ end
|
|||||||
@recipe f(n::Integer) = is3d(get(plotattributes,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing)
|
@recipe f(n::Integer) = is3d(get(plotattributes,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing)
|
||||||
|
|
||||||
# return a surface if this is a 3d plot, otherwise let it be sliced up
|
# return a surface if this is a 3d plot, otherwise let it be sliced up
|
||||||
@recipe function f{T<:Union{Integer,AbstractFloat}}(mat::AMat{T})
|
@recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat}
|
||||||
if all3D(plotattributes)
|
if all3D(plotattributes)
|
||||||
n,m = size(mat)
|
n,m = size(mat)
|
||||||
wrap_surfaces(plotattributes)
|
wrap_surfaces(plotattributes)
|
||||||
@ -285,7 +285,7 @@ end
|
|||||||
end
|
end
|
||||||
|
|
||||||
# if a matrix is wrapped by Formatted, do similar logic, but wrap data with Surface
|
# if a matrix is wrapped by Formatted, do similar logic, but wrap data with Surface
|
||||||
@recipe function f{T<:AbstractMatrix}(fmt::Formatted{T})
|
@recipe function f(fmt::Formatted{T}) where T<:AbstractMatrix
|
||||||
if all3D(plotattributes)
|
if all3D(plotattributes)
|
||||||
mat = fmt.data
|
mat = fmt.data
|
||||||
n,m = size(mat)
|
n,m = size(mat)
|
||||||
@ -297,7 +297,7 @@ end
|
|||||||
end
|
end
|
||||||
|
|
||||||
# assume this is a Volume, so construct one
|
# assume this is a Volume, so construct one
|
||||||
@recipe function f{T<:Number}(vol::AbstractArray{T,3}, args...)
|
@recipe function f(vol::AbstractArray{T,3}, args...) where T<:Number
|
||||||
seriestype := :volume
|
seriestype := :volume
|
||||||
SliceIt, nothing, Volume(vol, args...), nothing
|
SliceIt, nothing, Volume(vol, args...), nothing
|
||||||
end
|
end
|
||||||
@ -305,7 +305,7 @@ end
|
|||||||
|
|
||||||
# # images - grays
|
# # images - grays
|
||||||
|
|
||||||
@recipe function f{T<:Gray}(mat::AMat{T})
|
@recipe function f(mat::AMat{T}) where T<:Gray
|
||||||
if is_seriestype_supported(:image)
|
if is_seriestype_supported(:image)
|
||||||
seriestype := :image
|
seriestype := :image
|
||||||
n, m = size(mat)
|
n, m = size(mat)
|
||||||
@ -320,7 +320,7 @@ end
|
|||||||
|
|
||||||
# # images - colors
|
# # images - colors
|
||||||
|
|
||||||
@recipe function f{T<:Colorant}(mat::AMat{T})
|
@recipe function f(mat::AMat{T}) where T<:Colorant
|
||||||
n, m = size(mat)
|
n, m = size(mat)
|
||||||
|
|
||||||
if is_seriestype_supported(:image)
|
if is_seriestype_supported(:image)
|
||||||
@ -358,7 +358,7 @@ end
|
|||||||
|
|
||||||
# function without range... use the current range of the x-axis
|
# function without range... use the current range of the x-axis
|
||||||
|
|
||||||
@recipe function f{F<:Function}(f::FuncOrFuncs{F})
|
@recipe function f(f::FuncOrFuncs{F}) where F<:Function
|
||||||
plt = plotattributes[:plot_object]
|
plt = plotattributes[:plot_object]
|
||||||
xmin, xmax = try
|
xmin, xmax = try
|
||||||
axis_limits(plt[1][:xaxis])
|
axis_limits(plt[1][:xaxis])
|
||||||
@ -371,6 +371,13 @@ end
|
|||||||
end
|
end
|
||||||
|
|
||||||
# try some intervals over which the function may be defined
|
# try some intervals over which the function may be defined
|
||||||
|
function tryrange(F::AbstractArray, vec)
|
||||||
|
rets = [tryrange(f, vec) for f in F] # get the preferred for each
|
||||||
|
maxind = maximum(indexin(rets, vec)) # get the last attempt that succeeded (most likely to fit all)
|
||||||
|
rets .= [tryrange(f, vec[maxind:maxind]) for f in F] # ensure that all functions compute there
|
||||||
|
rets[1]
|
||||||
|
end
|
||||||
|
|
||||||
function tryrange(F, vec)
|
function tryrange(F, vec)
|
||||||
for v in vec
|
for v in vec
|
||||||
try
|
try
|
||||||
@ -379,7 +386,7 @@ function tryrange(F, vec)
|
|||||||
catch
|
catch
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
error("Function not defined over the given interval, $vec")
|
error("$F is not a Function, or is not defined at any of the values $vec")
|
||||||
end
|
end
|
||||||
#
|
#
|
||||||
# # --------------------------------------------------------------------
|
# # --------------------------------------------------------------------
|
||||||
@ -390,7 +397,7 @@ end
|
|||||||
# # if functions come first, just swap the order (not to be confused with parametric functions...
|
# # if functions come first, just swap the order (not to be confused with parametric functions...
|
||||||
# # as there would be more than one function passed in)
|
# # as there would be more than one function passed in)
|
||||||
|
|
||||||
@recipe function f{F<:Function}(f::FuncOrFuncs{F}, x)
|
@recipe function f(f::FuncOrFuncs{F}, x) where F<:Function
|
||||||
F2 = typeof(x)
|
F2 = typeof(x)
|
||||||
@assert !(F2 <: Function || (F2 <: AbstractArray && F2.parameters[1] <: Function)) # otherwise we'd hit infinite recursion here
|
@assert !(F2 <: Function || (F2 <: AbstractArray && F2.parameters[1] <: Function)) # otherwise we'd hit infinite recursion here
|
||||||
x, f
|
x, f
|
||||||
@ -458,19 +465,19 @@ end
|
|||||||
xs = adapted_grid(f, (xmin, xmax))
|
xs = adapted_grid(f, (xmin, xmax))
|
||||||
xs, f
|
xs, f
|
||||||
end
|
end
|
||||||
@recipe function f{F<:Function}(fs::AbstractArray{F}, xmin::Number, xmax::Number)
|
@recipe function f(fs::AbstractArray{F}, xmin::Number, xmax::Number) where F<:Function
|
||||||
xs = Any[adapted_grid(f, (xmin, xmax)) for f in fs]
|
xs = Any[adapted_grid(f, (xmin, xmax)) for f in fs]
|
||||||
xs, fs
|
xs, fs
|
||||||
end
|
end
|
||||||
@recipe f{F<:Function,G<:Function}(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, u::AVec) = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)
|
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, u::AVec) where {F<:Function,G<:Function} = mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)
|
||||||
@recipe f{F<:Function,G<:Function}(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, umin::Number, umax::Number, n = 200) = fx, fy, linspace(umin, umax, n)
|
@recipe f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, umin::Number, umax::Number, n = 200) where {F<:Function,G<:Function} = fx, fy, linspace(umin, umax, n)
|
||||||
|
|
||||||
#
|
#
|
||||||
# # special handling... 3D parametric function(s)
|
# # special handling... 3D parametric function(s)
|
||||||
@recipe function f{F<:Function,G<:Function,H<:Function}(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, u::AVec)
|
@recipe function f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, u::AVec) where {F<:Function,G<:Function,H<:Function}
|
||||||
mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)
|
mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)
|
||||||
end
|
end
|
||||||
@recipe function f{F<:Function,G<:Function,H<:Function}(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, umin::Number, umax::Number, numPoints = 200)
|
@recipe function f(fx::FuncOrFuncs{F}, fy::FuncOrFuncs{G}, fz::FuncOrFuncs{H}, umin::Number, umax::Number, numPoints = 200) where {F<:Function,G<:Function,H<:Function}
|
||||||
fx, fy, fz, linspace(umin, umax, numPoints)
|
fx, fy, fz, linspace(umin, umax, numPoints)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -485,28 +492,28 @@ end
|
|||||||
|
|
||||||
#
|
#
|
||||||
# # (x,y) tuples
|
# # (x,y) tuples
|
||||||
@recipe f{R1<:Number,R2<:Number}(xy::AVec{Tuple{R1,R2}}) = unzip(xy)
|
@recipe f(xy::AVec{Tuple{R1,R2}}) where {R1<:Number,R2<:Number} = unzip(xy)
|
||||||
@recipe f{R1<:Number,R2<:Number}(xy::Tuple{R1,R2}) = [xy[1]], [xy[2]]
|
@recipe f(xy::Tuple{R1,R2}) where {R1<:Number,R2<:Number} = [xy[1]], [xy[2]]
|
||||||
|
|
||||||
#
|
#
|
||||||
# # (x,y,z) tuples
|
# # (x,y,z) tuples
|
||||||
@recipe f{R1<:Number,R2<:Number,R3<:Number}(xyz::AVec{Tuple{R1,R2,R3}}) = unzip(xyz)
|
@recipe f(xyz::AVec{Tuple{R1,R2,R3}}) where {R1<:Number,R2<:Number,R3<:Number} = unzip(xyz)
|
||||||
@recipe f{R1<:Number,R2<:Number,R3<:Number}(xyz::Tuple{R1,R2,R3}) = [xyz[1]], [xyz[2]], [xyz[3]]
|
@recipe f(xyz::Tuple{R1,R2,R3}) where {R1<:Number,R2<:Number,R3<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
|
||||||
|
|
||||||
# these might be points+velocity, or OHLC or something else
|
# these might be points+velocity, or OHLC or something else
|
||||||
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(xyuv::AVec{Tuple{R1,R2,R3,R4}}) = get(plotattributes,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv)
|
@recipe f(xyuv::AVec{Tuple{R1,R2,R3,R4}}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = get(plotattributes,:seriestype,:path)==:ohlc ? OHLC[OHLC(t...) for t in xyuv] : unzip(xyuv)
|
||||||
@recipe f{R1<:Number,R2<:Number,R3<:Number,R4<:Number}(xyuv::Tuple{R1,R2,R3,R4}) = [xyuv[1]], [xyuv[2]], [xyuv[3]], [xyuv[4]]
|
@recipe f(xyuv::Tuple{R1,R2,R3,R4}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = [xyuv[1]], [xyuv[2]], [xyuv[3]], [xyuv[4]]
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# # 2D FixedSizeArrays
|
# # 2D FixedSizeArrays
|
||||||
@recipe f{T<:Number}(xy::AVec{FixedSizeArrays.Vec{2,T}}) = unzip(xy)
|
@recipe f(xy::AVec{FixedSizeArrays.Vec{2,T}}) where {T<:Number} = unzip(xy)
|
||||||
@recipe f{T<:Number}(xy::FixedSizeArrays.Vec{2,T}) = [xy[1]], [xy[2]]
|
@recipe f(xy::FixedSizeArrays.Vec{2,T}) where {T<:Number} = [xy[1]], [xy[2]]
|
||||||
|
|
||||||
#
|
#
|
||||||
# # 3D FixedSizeArrays
|
# # 3D FixedSizeArrays
|
||||||
@recipe f{T<:Number}(xyz::AVec{FixedSizeArrays.Vec{3,T}}) = unzip(xyz)
|
@recipe f(xyz::AVec{FixedSizeArrays.Vec{3,T}}) where {T<:Number} = unzip(xyz)
|
||||||
@recipe f{T<:Number}(xyz::FixedSizeArrays.Vec{3,T}) = [xyz[1]], [xyz[2]], [xyz[3]]
|
@recipe f(xyz::FixedSizeArrays.Vec{3,T}) where {T<:Number} = [xyz[1]], [xyz[2]], [xyz[3]]
|
||||||
|
|
||||||
#
|
#
|
||||||
# # --------------------------------------------------------------------
|
# # --------------------------------------------------------------------
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
|
|
||||||
function Subplot{T<:AbstractBackend}(::T; parent = RootLayout())
|
function Subplot(::T; parent = RootLayout()) where T<:AbstractBackend
|
||||||
Subplot{T}(
|
Subplot{T}(
|
||||||
parent,
|
parent,
|
||||||
Series[],
|
Series[],
|
||||||
|
|||||||
16
src/types.jl
16
src/types.jl
@ -6,20 +6,20 @@ const AVec = AbstractVector
|
|||||||
const AMat = AbstractMatrix
|
const AMat = AbstractMatrix
|
||||||
const KW = Dict{Symbol,Any}
|
const KW = Dict{Symbol,Any}
|
||||||
|
|
||||||
immutable PlotsDisplay <: Display end
|
struct PlotsDisplay <: Display end
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
immutable InputWrapper{T}
|
struct InputWrapper{T}
|
||||||
obj::T
|
obj::T
|
||||||
end
|
end
|
||||||
wrap{T}(obj::T) = InputWrapper{T}(obj)
|
wrap(obj::T) where {T} = InputWrapper{T}(obj)
|
||||||
Base.isempty(wrapper::InputWrapper) = false
|
Base.isempty(wrapper::InputWrapper) = false
|
||||||
|
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
type Series
|
mutable struct Series
|
||||||
d::KW
|
d::KW
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ attr!(series::Series, v, k::Symbol) = (series.d[k] = v)
|
|||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# a single subplot
|
# a single subplot
|
||||||
type Subplot{T<:AbstractBackend} <: AbstractLayout
|
mutable struct Subplot{T<:AbstractBackend} <: AbstractLayout
|
||||||
parent::AbstractLayout
|
parent::AbstractLayout
|
||||||
series_list::Vector{Series} # arguments for each series
|
series_list::Vector{Series} # arguments for each series
|
||||||
minpad::Tuple # leftpad, toppad, rightpad, bottompad
|
minpad::Tuple # leftpad, toppad, rightpad, bottompad
|
||||||
@ -45,12 +45,12 @@ Base.show(io::IO, sp::Subplot) = print(io, "Subplot{$(sp[:subplot_index])}")
|
|||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
# simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place
|
# simple wrapper around a KW so we can hold all attributes pertaining to the axis in one place
|
||||||
type Axis
|
mutable struct Axis
|
||||||
sps::Vector{Subplot}
|
sps::Vector{Subplot}
|
||||||
d::KW
|
d::KW
|
||||||
end
|
end
|
||||||
|
|
||||||
type Extrema
|
mutable struct Extrema
|
||||||
emin::Float64
|
emin::Float64
|
||||||
emax::Float64
|
emax::Float64
|
||||||
end
|
end
|
||||||
@ -63,7 +63,7 @@ const SubplotMap = Dict{Any, Subplot}
|
|||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
type Plot{T<:AbstractBackend} <: AbstractPlot{T}
|
mutable struct Plot{T<:AbstractBackend} <: AbstractPlot{T}
|
||||||
backend::T # the backend type
|
backend::T # the backend type
|
||||||
n::Int # number of series
|
n::Int # number of series
|
||||||
attr::KW # arguments for the whole plot
|
attr::KW # arguments for the whole plot
|
||||||
|
|||||||
145
src/utils.jl
145
src/utils.jl
@ -114,7 +114,7 @@ function regressionXY(x, y)
|
|||||||
regx, regy
|
regx, regy
|
||||||
end
|
end
|
||||||
|
|
||||||
function replace_image_with_heatmap{T<:Colorant}(z::Array{T})
|
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
|
||||||
@show T, size(z)
|
@show T, size(z)
|
||||||
n, m = size(z)
|
n, m = size(z)
|
||||||
# idx = 0
|
# idx = 0
|
||||||
@ -138,14 +138,14 @@ end
|
|||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
|
|
||||||
"Build line segments for plotting"
|
"Build line segments for plotting"
|
||||||
type Segments{T}
|
mutable struct Segments{T}
|
||||||
pts::Vector{T}
|
pts::Vector{T}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Segments() = Segments{Float64}(zeros(0))
|
# Segments() = Segments{Float64}(zeros(0))
|
||||||
|
|
||||||
Segments() = Segments(Float64)
|
Segments() = Segments(Float64)
|
||||||
Segments{T}(::Type{T}) = Segments(T[])
|
Segments(::Type{T}) where {T} = Segments(T[])
|
||||||
Segments(p::Int) = Segments(NTuple{2,Float64}[])
|
Segments(p::Int) = Segments(NTuple{2,Float64}[])
|
||||||
|
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ to_nan(::Type{NTuple{2,Float64}}) = (NaN, NaN)
|
|||||||
coords(segs::Segments{Float64}) = segs.pts
|
coords(segs::Segments{Float64}) = segs.pts
|
||||||
coords(segs::Segments{NTuple{2,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts]
|
coords(segs::Segments{NTuple{2,Float64}}) = Float64[p[1] for p in segs.pts], Float64[p[2] for p in segs.pts]
|
||||||
|
|
||||||
function Base.push!{T}(segments::Segments{T}, vs...)
|
function Base.push!(segments::Segments{T}, vs...) where T
|
||||||
if !isempty(segments.pts)
|
if !isempty(segments.pts)
|
||||||
push!(segments.pts, to_nan(T))
|
push!(segments.pts, to_nan(T))
|
||||||
end
|
end
|
||||||
@ -167,7 +167,7 @@ function Base.push!{T}(segments::Segments{T}, vs...)
|
|||||||
segments
|
segments
|
||||||
end
|
end
|
||||||
|
|
||||||
function Base.push!{T}(segments::Segments{T}, vs::AVec)
|
function Base.push!(segments::Segments{T}, vs::AVec) where T
|
||||||
if !isempty(segments.pts)
|
if !isempty(segments.pts)
|
||||||
push!(segments.pts, to_nan(T))
|
push!(segments.pts, to_nan(T))
|
||||||
end
|
end
|
||||||
@ -181,7 +181,7 @@ end
|
|||||||
# -----------------------------------------------------
|
# -----------------------------------------------------
|
||||||
# helper to manage NaN-separated segments
|
# helper to manage NaN-separated segments
|
||||||
|
|
||||||
type SegmentsIterator
|
mutable struct SegmentsIterator
|
||||||
args::Tuple
|
args::Tuple
|
||||||
n::Int
|
n::Int
|
||||||
end
|
end
|
||||||
@ -232,8 +232,8 @@ end
|
|||||||
# Find minimal type that can contain NaN and x
|
# Find minimal type that can contain NaN and x
|
||||||
# To allow use of NaN separated segments with categorical x axis
|
# To allow use of NaN separated segments with categorical x axis
|
||||||
|
|
||||||
float_extended_type{T}(x::AbstractArray{T}) = Union{T,Float64}
|
float_extended_type(x::AbstractArray{T}) where {T} = Union{T,Float64}
|
||||||
float_extended_type{T<:Real}(x::AbstractArray{T}) = Float64
|
float_extended_type(x::AbstractArray{T}) where {T<:Real} = Float64
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@ -259,27 +259,27 @@ _cycle(grad::ColorGradient, idx::Int) = _cycle(grad.colors, idx)
|
|||||||
_cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices)
|
_cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices)
|
||||||
|
|
||||||
makevec(v::AVec) = v
|
makevec(v::AVec) = v
|
||||||
makevec{T}(v::T) = T[v]
|
makevec(v::T) where {T} = T[v]
|
||||||
|
|
||||||
"duplicate a single value, or pass the 2-tuple through"
|
"duplicate a single value, or pass the 2-tuple through"
|
||||||
maketuple(x::Real) = (x,x)
|
maketuple(x::Real) = (x,x)
|
||||||
maketuple{T,S}(x::Tuple{T,S}) = x
|
maketuple(x::Tuple{T,S}) where {T,S} = x
|
||||||
|
|
||||||
mapFuncOrFuncs(f::Function, u::AVec) = map(f, u)
|
mapFuncOrFuncs(f::Function, u::AVec) = map(f, u)
|
||||||
mapFuncOrFuncs{F<:Function}(fs::AVec{F}, u::AVec) = [map(f, u) for f in fs]
|
mapFuncOrFuncs(fs::AVec{F}, u::AVec) where {F<:Function} = [map(f, u) for f in fs]
|
||||||
|
|
||||||
unzip{X,Y}(xy::AVec{Tuple{X,Y}}) = [t[1] for t in xy], [t[2] for t in xy]
|
unzip(xy::AVec{Tuple{X,Y}}) where {X,Y} = [t[1] for t in xy], [t[2] for t in xy]
|
||||||
unzip{X,Y,Z}(xyz::AVec{Tuple{X,Y,Z}}) = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
|
unzip(xyz::AVec{Tuple{X,Y,Z}}) where {X,Y,Z} = [t[1] for t in xyz], [t[2] for t in xyz], [t[3] for t in xyz]
|
||||||
unzip{X,Y,U,V}(xyuv::AVec{Tuple{X,Y,U,V}}) = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
|
unzip(xyuv::AVec{Tuple{X,Y,U,V}}) where {X,Y,U,V} = [t[1] for t in xyuv], [t[2] for t in xyuv], [t[3] for t in xyuv], [t[4] for t in xyuv]
|
||||||
|
|
||||||
unzip{T}(xy::AVec{FixedSizeArrays.Vec{2,T}}) = T[t[1] for t in xy], T[t[2] for t in xy]
|
unzip(xy::AVec{FixedSizeArrays.Vec{2,T}}) where {T} = T[t[1] for t in xy], T[t[2] for t in xy]
|
||||||
unzip{T}(xy::FixedSizeArrays.Vec{2,T}) = T[xy[1]], T[xy[2]]
|
unzip(xy::FixedSizeArrays.Vec{2,T}) where {T} = T[xy[1]], T[xy[2]]
|
||||||
|
|
||||||
unzip{T}(xyz::AVec{FixedSizeArrays.Vec{3,T}}) = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
|
unzip(xyz::AVec{FixedSizeArrays.Vec{3,T}}) where {T} = T[t[1] for t in xyz], T[t[2] for t in xyz], T[t[3] for t in xyz]
|
||||||
unzip{T}(xyz::FixedSizeArrays.Vec{3,T}) = T[xyz[1]], T[xyz[2]], T[xyz[3]]
|
unzip(xyz::FixedSizeArrays.Vec{3,T}) where {T} = T[xyz[1]], T[xyz[2]], T[xyz[3]]
|
||||||
|
|
||||||
unzip{T}(xyuv::AVec{FixedSizeArrays.Vec{4,T}}) = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
|
unzip(xyuv::AVec{FixedSizeArrays.Vec{4,T}}) where {T} = T[t[1] for t in xyuv], T[t[2] for t in xyuv], T[t[3] for t in xyuv], T[t[4] for t in xyuv]
|
||||||
unzip{T}(xyuv::FixedSizeArrays.Vec{4,T}) = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
|
unzip(xyuv::FixedSizeArrays.Vec{4,T}) where {T} = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
|
||||||
|
|
||||||
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
|
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
|
||||||
function _expand_limits(lims, x)
|
function _expand_limits(lims, x)
|
||||||
@ -363,15 +363,26 @@ end
|
|||||||
|
|
||||||
function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y))
|
function convert_to_polar(x, y, r_extrema = calc_r_extrema(x, y))
|
||||||
rmin, rmax = r_extrema
|
rmin, rmax = r_extrema
|
||||||
phi, r = x, y
|
theta, r = filter_radial_data(x, y, r_extrema)
|
||||||
r = (r - rmin) / (rmax - rmin)
|
r = (r - rmin) / (rmax - rmin)
|
||||||
n = max(length(phi), length(r))
|
x = r.*cos.(theta)
|
||||||
x = zeros(n)
|
y = r.*sin.(theta)
|
||||||
y = zeros(n)
|
x, y
|
||||||
|
end
|
||||||
|
|
||||||
|
# Filters radial data for points within the axis limits
|
||||||
|
function filter_radial_data(theta, r, r_extrema::Tuple{Real, Real})
|
||||||
|
n = max(length(theta), length(r))
|
||||||
|
rmin, rmax = r_extrema
|
||||||
|
x, y = zeros(n), zeros(n)
|
||||||
for i in 1:n
|
for i in 1:n
|
||||||
x[i] = _cycle(r,i) * cos.(_cycle(phi,i))
|
x[i] = _cycle(theta, i)
|
||||||
y[i] = _cycle(r,i) * sin.(_cycle(phi,i))
|
y[i] = _cycle(r, i)
|
||||||
end
|
end
|
||||||
|
points = map((a, b) -> (a, b), x, y)
|
||||||
|
filter!(a -> a[2] >= rmin && a[2] <= rmax, points)
|
||||||
|
x = map(a -> a[1], points)
|
||||||
|
y = map(a -> a[2], points)
|
||||||
x, y
|
x, y
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -388,7 +399,7 @@ isatom() = isdefined(Main, :Atom) && Main.Atom.isconnected()
|
|||||||
|
|
||||||
function is_installed(pkgstr::AbstractString)
|
function is_installed(pkgstr::AbstractString)
|
||||||
try
|
try
|
||||||
Pkg.installed(pkgstr) === nothing ? false: true
|
Pkg.installed(pkgstr) === nothing ? false : true
|
||||||
catch
|
catch
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
@ -410,20 +421,20 @@ isvertical(d::KW) = get(d, :orientation, :vertical) in (:vertical, :v, :vert)
|
|||||||
isvertical(series::Series) = isvertical(series.d)
|
isvertical(series::Series) = isvertical(series.d)
|
||||||
|
|
||||||
|
|
||||||
ticksType{T<:Real}(ticks::AVec{T}) = :ticks
|
ticksType(ticks::AVec{T}) where {T<:Real} = :ticks
|
||||||
ticksType{T<:AbstractString}(ticks::AVec{T}) = :labels
|
ticksType(ticks::AVec{T}) where {T<:AbstractString} = :labels
|
||||||
ticksType{T<:AVec,S<:AVec}(ticks::Tuple{T,S}) = :ticks_and_labels
|
ticksType(ticks::Tuple{T,S}) where {T<:AVec,S<:AVec} = :ticks_and_labels
|
||||||
ticksType(ticks) = :invalid
|
ticksType(ticks) = :invalid
|
||||||
|
|
||||||
limsType{T<:Real,S<:Real}(lims::Tuple{T,S}) = :limits
|
limsType(lims::Tuple{T,S}) where {T<:Real,S<:Real} = :limits
|
||||||
limsType(lims::Symbol) = lims == :auto ? :auto : :invalid
|
limsType(lims::Symbol) = lims == :auto ? :auto : :invalid
|
||||||
limsType(lims) = :invalid
|
limsType(lims) = :invalid
|
||||||
|
|
||||||
# axis_Symbol(letter, postfix) = Symbol(letter * postfix)
|
# axis_Symbol(letter, postfix) = Symbol(letter * postfix)
|
||||||
# axis_symbols(letter, postfix...) = map(s -> axis_Symbol(letter, s), postfix)
|
# axis_symbols(letter, postfix...) = map(s -> axis_Symbol(letter, s), postfix)
|
||||||
|
|
||||||
Base.convert{T<:Real}(::Type{Vector{T}}, rng::Range{T}) = T[x for x in rng]
|
Base.convert(::Type{Vector{T}}, rng::Range{T}) where {T<:Real} = T[x for x in rng]
|
||||||
Base.convert{T<:Real,S<:Real}(::Type{Vector{T}}, rng::Range{S}) = T[x for x in rng]
|
Base.convert(::Type{Vector{T}}, rng::Range{S}) where {T<:Real,S<:Real} = T[x for x in rng]
|
||||||
|
|
||||||
Base.merge(a::AbstractVector, b::AbstractVector) = sort(unique(vcat(a,b)))
|
Base.merge(a::AbstractVector, b::AbstractVector) = sort(unique(vcat(a,b)))
|
||||||
|
|
||||||
@ -727,7 +738,7 @@ end
|
|||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
|
|
||||||
type DebugMode
|
mutable struct DebugMode
|
||||||
on::Bool
|
on::Bool
|
||||||
end
|
end
|
||||||
const _debugMode = DebugMode(false)
|
const _debugMode = DebugMode(false)
|
||||||
@ -765,10 +776,10 @@ end
|
|||||||
|
|
||||||
extendSeriesByOne(v::UnitRange{Int}, n::Int = 1) = isempty(v) ? (1:n) : (minimum(v):maximum(v)+n)
|
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(v::Range{T}, z::Real) where {T} = extendSeriesData(float(collect(v)), z)
|
||||||
extendSeriesData{T}(v::Range{T}, z::AVec) = extendSeriesData(float(collect(v)), z)
|
extendSeriesData(v::Range{T}, z::AVec) where {T} = extendSeriesData(float(collect(v)), z)
|
||||||
extendSeriesData{T}(v::AVec{T}, z::Real) = (push!(v, convert(T, z)); v)
|
extendSeriesData(v::AVec{T}, z::Real) where {T} = (push!(v, convert(T, z)); v)
|
||||||
extendSeriesData{T}(v::AVec{T}, z::AVec) = (append!(v, convert(Vector{T}, z)); v)
|
extendSeriesData(v::AVec{T}, z::AVec) where {T} = (append!(v, convert(Vector{T}, z)); v)
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
@ -786,14 +797,14 @@ function getxyz(plt::Plot, i::Integer)
|
|||||||
tovec(d[:x]), tovec(d[:y]), tovec(d[:z])
|
tovec(d[:x]), tovec(d[:y]), tovec(d[:z])
|
||||||
end
|
end
|
||||||
|
|
||||||
function setxy!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer)
|
function setxy!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y}
|
||||||
series = plt.series_list[i]
|
series = plt.series_list[i]
|
||||||
series.d[:x], series.d[:y] = xy
|
series.d[:x], series.d[:y] = xy
|
||||||
sp = series.d[:subplot]
|
sp = series.d[:subplot]
|
||||||
reset_extrema!(sp)
|
reset_extrema!(sp)
|
||||||
_series_updated(plt, series)
|
_series_updated(plt, series)
|
||||||
end
|
end
|
||||||
function setxyz!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
|
function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z}
|
||||||
series = plt.series_list[i]
|
series = plt.series_list[i]
|
||||||
series.d[:x], series.d[:y], series.d[:z] = xyz
|
series.d[:x], series.d[:y], series.d[:z] = xyz
|
||||||
sp = series.d[:subplot]
|
sp = series.d[:subplot]
|
||||||
@ -801,7 +812,7 @@ function setxyz!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
|
|||||||
_series_updated(plt, series)
|
_series_updated(plt, series)
|
||||||
end
|
end
|
||||||
|
|
||||||
function setxyz!{X,Y,Z<:AbstractMatrix}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
|
function setxyz!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z<:AbstractMatrix}
|
||||||
setxyz!(plt, (xyz[1], xyz[2], Surface(xyz[3])), i)
|
setxyz!(plt, (xyz[1], xyz[2], Surface(xyz[3])), i)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -810,8 +821,8 @@ end
|
|||||||
# indexing notation
|
# indexing notation
|
||||||
|
|
||||||
# Base.getindex(plt::Plot, i::Integer) = getxy(plt, i)
|
# Base.getindex(plt::Plot, i::Integer) = getxy(plt, i)
|
||||||
Base.setindex!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer) = (setxy!(plt, xy, i); plt)
|
Base.setindex!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y} = (setxy!(plt, xy, i); plt)
|
||||||
Base.setindex!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) = (setxyz!(plt, xyz, i); plt)
|
Base.setindex!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z} = (setxyz!(plt, xyz, i); plt)
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
|
|
||||||
@ -923,10 +934,10 @@ function Base.append!(plt::Plot, i::Integer, x::AVec, y::AVec, z::AVec)
|
|||||||
end
|
end
|
||||||
|
|
||||||
# tuples
|
# tuples
|
||||||
Base.push!{X,Y}(plt::Plot, xy::Tuple{X,Y}) = push!(plt, 1, xy...)
|
Base.push!(plt::Plot, xy::Tuple{X,Y}) where {X,Y} = push!(plt, 1, xy...)
|
||||||
Base.push!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}) = push!(plt, 1, xyz...)
|
Base.push!(plt::Plot, xyz::Tuple{X,Y,Z}) where {X,Y,Z} = push!(plt, 1, xyz...)
|
||||||
Base.push!{X,Y}(plt::Plot, i::Integer, xy::Tuple{X,Y}) = push!(plt, i, xy...)
|
Base.push!(plt::Plot, i::Integer, xy::Tuple{X,Y}) where {X,Y} = push!(plt, i, xy...)
|
||||||
Base.push!{X,Y,Z}(plt::Plot, i::Integer, xyz::Tuple{X,Y,Z}) = push!(plt, i, xyz...)
|
Base.push!(plt::Plot, i::Integer, xyz::Tuple{X,Y,Z}) where {X,Y,Z} = push!(plt, i, xyz...)
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
# push/append for all series
|
# push/append for all series
|
||||||
@ -996,3 +1007,43 @@ xmax(plt::Plot) = ignorenan_maximum([ignorenan_maximum(series.d[:x]) for series
|
|||||||
|
|
||||||
"Extrema of x-values in plot"
|
"Extrema of x-values in plot"
|
||||||
ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))
|
ignorenan_extrema(plt::Plot) = (xmin(plt), xmax(plt))
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------
|
||||||
|
# get fonts from objects:
|
||||||
|
|
||||||
|
titlefont(sp::Subplot) = font(
|
||||||
|
sp[:titlefontfamily],
|
||||||
|
sp[:titlefontsize],
|
||||||
|
sp[:titlefontvalign],
|
||||||
|
sp[:titlefonthalign],
|
||||||
|
sp[:titlefontrotation],
|
||||||
|
sp[:titlefontcolor],
|
||||||
|
)
|
||||||
|
|
||||||
|
legendfont(sp::Subplot) = font(
|
||||||
|
sp[:legendfontfamily],
|
||||||
|
sp[:legendfontsize],
|
||||||
|
sp[:legendfontvalign],
|
||||||
|
sp[:legendfonthalign],
|
||||||
|
sp[:legendfontrotation],
|
||||||
|
sp[:legendfontcolor],
|
||||||
|
)
|
||||||
|
|
||||||
|
tickfont(ax::Axis) = font(
|
||||||
|
ax[:tickfontfamily],
|
||||||
|
ax[:tickfontsize],
|
||||||
|
ax[:tickfontvalign],
|
||||||
|
ax[:tickfonthalign],
|
||||||
|
ax[:tickfontrotation],
|
||||||
|
ax[:tickfontcolor],
|
||||||
|
)
|
||||||
|
|
||||||
|
guidefont(ax::Axis) = font(
|
||||||
|
ax[:guidefontfamily],
|
||||||
|
ax[:guidefontsize],
|
||||||
|
ax[:guidefontvalign],
|
||||||
|
ax[:guidefonthalign],
|
||||||
|
ax[:guidefontrotation],
|
||||||
|
ax[:guidefontcolor],
|
||||||
|
)
|
||||||
|
|||||||
@ -23,7 +23,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
|
# 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)
|
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
|
||||||
|
|
||||||
const _current_plots_version = v"0.12.4"
|
const _current_plots_version = v"0.13.1"
|
||||||
|
|
||||||
|
|
||||||
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
|
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
|
||||||
|
|||||||
@ -16,12 +16,12 @@ img_eps = isinteractive() ? 1e-2 : 10e-2
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@testset "PyPlot" begin
|
#@testset "PyPlot" begin
|
||||||
@test pyplot() == Plots.PyPlotBackend()
|
# @test pyplot() == Plots.PyPlotBackend()
|
||||||
@test backend() == Plots.PyPlotBackend()
|
# @test backend() == Plots.PyPlotBackend()
|
||||||
|
#
|
||||||
image_comparison_facts(:pyplot, eps=img_eps)
|
# image_comparison_facts(:pyplot, eps=img_eps)
|
||||||
end
|
#end
|
||||||
|
|
||||||
@testset "UnicodePlots" begin
|
@testset "UnicodePlots" begin
|
||||||
@test unicodeplots() == Plots.UnicodePlotsBackend()
|
@test unicodeplots() == Plots.UnicodePlotsBackend()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user