Compare commits

..

21 Commits

Author SHA1 Message Date
Tom Breloff 25bf71aff2 0.6 fixes 2017-02-21 12:10:38 -05:00
Tom Breloff 33d6c3426a inline docs for plot 2017-01-18 13:45:02 -05:00
Tom Breloff 9d038ea05e starting no-conditional reorg; replaced FixedSizeArrays with StaticArrays 2017-01-18 12:08:20 -05:00
Tom Breloff 3b570edea1 added back precompilation 2017-01-13 09:33:02 -05:00
Tom Breloff 199a3306db fix support for fill_z in pyplot 2017-01-11 10:37:54 -05:00
Tom Breloff 3236e06fb9 wrap_surfaces for 3 matrices 2017-01-10 11:35:57 -05:00
Tom Breloff 492618ae67 Merge pull request #641 from tbreloff/surfacecolor
Add fill_z attribute and plotly impl
2017-01-09 16:17:49 -05:00
Naoki Saito c5737db4f5 Add fill_z attribute and plotly impl 2017-01-09 16:03:14 -05:00
Tom Breloff 40b49b9873 Merge pull request #631 from ma-laforge/inspectdr
Inspectdr
2017-01-09 15:18:04 -05:00
MA Laforge 1fa34574e8 More fixes requested by Tom:
Add add_backend_string().
Remove un-necessary test: true == plt[:show].
2017-01-09 15:14:39 -05:00
Tom Breloff 1c522159df Merge remote-tracking branch 'origin/master' into dev 2017-01-09 13:22:07 -05:00
Tom Breloff 967dca7912 Merge remote-tracking branch 'origin/dev' into dev 2017-01-09 13:20:18 -05:00
Tom Breloff 7d66c502f4 support tex in pgfplots; closes #637 2017-01-09 13:19:37 -05:00
Tom Breloff 9b9e2fe6cd Merge pull request #636 from jheinen/dev
gr: use GKSwstype environment (required for QML)
2017-01-09 12:07:09 -05:00
Tom Breloff 47ee0a4c97 Merge pull request #633 from tbreloff/dev
fix arrays of funcs; closes #632
2017-01-09 12:06:45 -05:00
Tom Breloff f10bda463c Merge pull request #635 from anowacki/nowacki/default-font-family
Use `sans-serif` as default font family (fix #593)
2017-01-09 12:05:53 -05:00
Josef Heinen 72d336265b gr: use GKSwstype environment (required for QML) 2017-01-06 19:48:41 +01:00
Andy Nowacki a087a6694b Use sans-serif as default font family (fix #593)
Rather than specifying a specific typeface, set the font
*family* in the `family` field of `Font` as `sans-serif`
by default.

Fixes #593.
2017-01-06 16:45:40 +00:00
MA Laforge edf1daa7d7 Improve gui handling & remove global state.
Also:
Add AVec support for colors.
Move init code back to _initialize_backend.
2017-01-05 14:39:50 -05:00
MA Laforge c78444fc24 Improve support for Shapes, markers & colors.
Details:
Control font & background color.
Support arbitrary marker shapes.
Support more pre-defined markers.
Support Shapes in plots.
Support ln-plots.

Also:
Fix ncolumns.
Update supported section.
2017-01-04 17:41:05 -05:00
MA Laforge e381c13dc6 Initial support for InspectDR. 2016-12-31 15:41:11 -05:00
15 changed files with 610 additions and 83 deletions
+1 -1
View File
@@ -4,6 +4,6 @@ RecipesBase
PlotUtils
PlotThemes
Reexport
FixedSizeArrays
Measures
Showoff
StaticArrays
+2 -2
View File
@@ -1,9 +1,9 @@
__precompile__(false)
__precompile__(true)
module Plots
using Reexport
using FixedSizeArrays
using StaticArrays
@reexport using RecipesBase
using Base.Meta
@reexport using PlotUtils
+1
View File
@@ -29,6 +29,7 @@ const _arg_desc = KW(
:z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.",
:marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.",
:line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).",
:fill_z => "Matrix{Float64} of the same size as z matrix, which specifies the color of the 3D surface; the default value is `nothing`.",
:levels => "Integer, NTuple{2,Integer}. Number of levels (or x-levels/y-levels) for a contour type.",
:orientation => "Symbol. Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).",
:bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)",
+2 -20
View File
@@ -188,6 +188,7 @@ const _series_defaults = KW(
:z => nothing, # depth for contour, surface, etc
:marker_z => nothing, # value for color scale
:line_z => nothing,
:fill_z => nothing,
:levels => 15,
:orientation => :vertical,
:bar_position => :overlay, # for bar plots and histograms: could also be stack (stack up) or dodge (side by side)
@@ -259,15 +260,6 @@ const _subplot_defaults = KW(
:bottom_margin => :match,
:subplot_index => -1,
:colorbar_title => "",
:fontfamily => "Helvetica",
:fontsize => 10,
:fontcolor => :match, # matches foreground_color
:titlefontfamily => :match,
:titlefontsize => :match,
:titlefontcolor => :match,
:legendfontfamily => :match,
:legendfontsize => :match,
:legendfontcolor => :match,
)
const _axis_defaults = KW(
@@ -287,12 +279,6 @@ const _axis_defaults = KW(
:discrete_values => [],
:formatter => :auto,
:mirror => false,
:tickfontfamily => :match,
:tickfontsize => :match,
:tickfontcolor => :match,
:guidefontfamily => :match,
:guidefontsize => :match,
:guidefontcolor => :match,
)
const _suppress_warnings = Set{Symbol}([
@@ -446,6 +432,7 @@ add_aliases(:zguide, :zlabel, :zlab, :zl)
add_aliases(:zlims, :zlim, :zlimit, :zlimits)
add_aliases(:zticks, :ztick)
add_aliases(:zrotation, :zrot, :zr)
add_aliases(:fill_z, :fillz, :fz, :surfacecolor, :surfacecolour, :sc, :surfcolor, :surfcolour)
add_aliases(:legend, :leg, :key)
add_aliases(:colorbar, :cb, :cbar, :colorkey)
add_aliases(:clims, :clim, :cbarlims, :cbar_lims, :climits, :color_limits)
@@ -957,13 +944,8 @@ const _match_map2 = KW(
:foreground_color_border => :foreground_color_subplot,
:foreground_color_guide => :foreground_color_subplot,
:foreground_color_text => :foreground_color_subplot,
:fontcolor => :foreground_color_subplot,
)
for prefix in (:title,:legend,:guide,:tick), postfix in (:family,:size,:color)
_match_map2[Symbol(prefix,:font,postfix)] = Symbol(:font,postfix)
end
# properly retrieve from plt.attr, passing `:match` to the correct key
function Base.getindex(plt::Plot, k::Symbol)
v = plt.attr[k]
+57 -21
View File
@@ -19,10 +19,11 @@ macro init_backend(s)
export $sym
$sym(; kw...) = (default(; kw...); backend(Symbol($str)))
backend_name(::$T) = Symbol($str)
backend_package_name(::$T) = Symbol("Plots", $(string(s)))
push!(_backends, Symbol($str))
_backendType[Symbol($str)] = $T
_backendSymbol[$T] = Symbol($str)
include("backends/" * $str * ".jl")
# include("backends/" * $str * ".jl")
end)
end
@@ -48,8 +49,8 @@ _series_updated(plt::Plot, series::Series) = nothing
_before_layout_calcs(plt::Plot) = nothing
title_padding(sp::Subplot) = sp[:title] == "" ? 0mm : sp[:titlefontsize] * pt
guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefontsize] * pt
title_padding(sp::Subplot) = sp[:title] == "" ? 0mm : sp[:titlefont].pointsize * pt
guide_padding(axis::Axis) = axis[:guide] == "" ? 0mm : axis[:guidefont].pointsize * pt
"Returns the (width,height) of a text label."
function text_size(lablen::Int, sz::Number, rot::Number = 0)
@@ -90,7 +91,7 @@ function tick_padding(axis::Axis)
# hgt
# get the height of the rotated label
text_size(longest_label, axis[:tickfontsize], rot)[2]
text_size(longest_label, axis[:tickfont].pointsize, rot)[2]
end
end
@@ -148,7 +149,7 @@ function pickDefaultBackend()
# the ordering/inclusion of this package list is my semi-arbitrary guess at
# which one someone will want to use if they have the package installed...accounting for
# features, speed, and robustness
for pkgstr in ("PyPlot", "GR", "PlotlyJS", "Immerse", "Gadfly", "UnicodePlots")
for pkgstr in ("GR", "PlotlyJS", "PyPlot", "UnicodePlots")
if Pkg.installed(pkgstr) != nothing
return backend(Symbol(lowercase(pkgstr)))
end
@@ -263,22 +264,32 @@ function merge_with_base_supported(v::AVec)
end
# @init_backend Immerse
# @init_backend Gadfly
@init_backend PyPlot
# @init_backend Qwt
@init_backend UnicodePlots
# @init_backend Winston
# @init_backend Bokeh
# @init_backend PyPlot
# @init_backend UnicodePlots
@init_backend Plotly
@init_backend PlotlyJS
# @init_backend PlotlyJS
@init_backend GR
@init_backend GLVisualize
@init_backend PGFPlots
# @init_backend GLVisualize
# @init_backend PGFPlots
# @init_backend InspectDR
_initialize_backend(::PlotlyBackend) = include("backends/plotly.jl")
function _initialize_backend(b::AbstractBackend)
bname = backend_name(b)
@eval import $(backend_package_name(b))
end
# ---------------------------------------------------------
const _attr = KW()
const _seriestype = KW()
const _marker = KW()
const _style = KW()
const _scale = KW()
using Base.Meta
# create the various `is_xxx_supported` and `supported_xxxs` methods
# by default they pass through to checking membership in `_gr_xxx`
for s in (:attr, :seriestype, :marker, :style, :scale)
@@ -293,13 +304,38 @@ for s in (:attr, :seriestype, :marker, :style, :scale)
for bend in backends()
bend_type = typeof(_backend_instance(bend))
v = Symbol("_", bend, "_", s)
# v = Symbol("_", bend, "_", s)
v = Symbol("_", s)
@eval begin
$f(::$bend_type, $s::Symbol) = $s in $v
$f2(::$bend_type) = $v
$f(::$bend_type, $s::Symbol) = $s in $v[$(quot(bend))]
$f2(::$bend_type) = $v[$(quot(bend))]
end
end
end
# is_subplot_supported(::AbstractBackend) = false
# is_subplot_supported() = is_subplot_supported(backend())
# ---------------------------------------------------------
# # create the various `is_xxx_supported` and `supported_xxxs` methods
# # by default they pass through to checking membership in `_gr_xxx`
# for s in (:attr, :seriestype, :marker, :style, :scale)
# f = Symbol("is_", s, "_supported")
# f2 = Symbol("supported_", s, "s")
# @eval begin
# $f(::AbstractBackend, $s) = false
# $f(bend::AbstractBackend, $s::AbstractVector) = all(v -> $f(bend, v), $s)
# $f($s) = $f(backend(), $s)
# $f2() = $f2(backend())
# end
#
# for bend in backends()
# bend_type = typeof(_backend_instance(bend))
# v = Symbol("_", bend, "_", s)
# @eval begin
# $f(::$bend_type, $s::Symbol) = $s in $v
# $f2(::$bend_type) = $v
# end
# end
# end
#
# # is_subplot_supported(::AbstractBackend) = false
# # is_subplot_supported() = is_subplot_supported(backend())
+4 -4
View File
@@ -1077,14 +1077,14 @@ else
"use_default"
end
const _gr_wstype = Ref(get(ENV, "GKS_WSTYPE", _gr_wstype_default))
const _gr_wstype = Ref(get(ENV, "GKSwstype", _gr_wstype_default))
gr_set_output(wstype::String) = (_gr_wstype[] = wstype)
for (mime, fmt) in _gr_mimeformats
@eval function _show(io::IO, ::MIME{Symbol($mime)}, plt::Plot{GRBackend})
GR.emergencyclosegks()
filepath = tempname() * "." * $fmt
ENV["GKS_WSTYPE"] = $fmt
ENV["GKSwstype"] = $fmt
ENV["GKS_FILEPATH"] = filepath
gr_display(plt)
GR.emergencyclosegks()
@@ -1097,7 +1097,7 @@ function _display(plt::Plot{GRBackend})
if plt[:display_type] == :inline
GR.emergencyclosegks()
filepath = tempname() * ".pdf"
ENV["GKS_WSTYPE"] = "pdf"
ENV["GKSwstype"] = "pdf"
ENV["GKS_FILEPATH"] = filepath
gr_display(plt)
GR.emergencyclosegks()
@@ -1107,7 +1107,7 @@ function _display(plt::Plot{GRBackend})
else
ENV["GKS_DOUBLE_BUF"] = true
if _gr_wstype[] != "use_default"
ENV["GKS_WSTYPE"] = _gr_wstype[]
ENV["GKSwstype"] = _gr_wstype[]
end
gr_display(plt)
end
+488
View File
@@ -0,0 +1,488 @@
# https://github.com/ma-laforge/InspectDR.jl
#=TODO:
Tweak scale factor for width & other sizes
Not supported by InspectDR:
:foreground_color_grid
:foreground_color_border
:polar,
Add in functionality to Plots.jl:
:aspect_ratio,
=#
# ---------------------------------------------------------------------------
#TODO: remove features
const _inspectdr_attr = merge_with_base_supported([
:annotations,
:background_color_legend, :background_color_inside, :background_color_outside,
:foreground_color_grid, :foreground_color_legend, :foreground_color_title,
:foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text,
:label,
:linecolor, :linestyle, :linewidth, :linealpha,
:markershape, :markercolor, :markersize, :markeralpha,
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
:markerstrokestyle, #Causes warning not to have it... what is this?
:fillcolor, :fillalpha, #:fillrange,
# :bins, :bar_width, :bar_edges, :bar_position,
:title, :title_location, :titlefont,
:window_title,
:guide, :lims, :scale, #:ticks, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, #:colorbar,
# :marker_z,
# :line_z,
# :levels,
# :ribbon, :quiver, :arrow,
# :orientation,
:overwrite_figure,
# :polar,
# :normalize, :weights,
# :contours, :aspect_ratio,
:match_dimensions,
# :clims,
# :inset_subplots,
:dpi,
# :colorbar_title,
])
const _inspectdr_style = [:auto, :solid, :dash, :dot, :dashdot]
const _inspectdr_seriestype = [
:path, :scatter, :shape #, :steppre, :steppost
]
#see: _allMarkers, _shape_keys
const _inspectdr_marker = Symbol[
:none, :auto,
:circle, :rect, :diamond,
:cross, :xcross,
:utriangle, :dtriangle, :rtriangle, :ltriangle,
:pentagon, :hexagon, :heptagon, :octagon,
:star4, :star5, :star6, :star7, :star8,
:vline, :hline, :+, :x,
]
const _inspectdr_scale = [:identity, :ln, :log2, :log10]
is_marker_supported(::InspectDRBackend, shape::Shape) = true
#Do we avoid Map to avoid possible pre-comile issues?
function _inspectdr_mapglyph(s::Symbol)
s == :rect && return :square
return s
end
function _inspectdr_mapglyph(s::Shape)
x, y = coords(s)
return InspectDR.GlyphPolyline(x, y)
end
# py_marker(markers::AVec) = map(py_marker, markers)
function _inspectdr_mapglyph(markers::AVec)
warn("Vectors of markers are currently unsupported in InspectDR.")
_inspectdr_mapglyph(markers[1])
end
_inspectdr_mapglyphsize(v::Real) = v
function _inspectdr_mapglyphsize(v::Vector)
warn("Vectors of marker sizes are currently unsupported in InspectDR.")
_inspectdr_mapglyphsize(v[1])
end
_inspectdr_mapcolor(v::Colorant) = v
function _inspectdr_mapcolor(g::PlotUtils.ColorGradient)
warn("Color gradients are currently unsupported in InspectDR.")
#Pick middle color:
_inspectdr_mapcolor(g.colors[div(1+end,2)])
end
function _inspectdr_mapcolor(v::AVec)
warn("Vectors of colors are currently unsupported in InspectDR.")
#Pick middle color:
_inspectdr_mapcolor(v[div(1+end,2)])
end
#Hack: suggested point size does not seem adequate relative to plot size, for some reason.
_inspectdr_mapptsize(v) = 1.5*v
function _inspectdr_add_annotations(plot, x, y, val)
#What kind of annotation is this?
end
#plot::InspectDR.Plot2D
function _inspectdr_add_annotations(plot, x, y, val::PlotText)
vmap = Dict{Symbol, Symbol}(:top=>:t, :bottom=>:b) #:vcenter
hmap = Dict{Symbol, Symbol}(:left=>:l, :right=>:r) #:hcenter
align = Symbol(get(vmap, val.font.valign, :c), get(hmap, val.font.halign, :c))
fnt = InspectDR.Font(val.font.family, val.font.pointsize,
color =_inspectdr_mapcolor(val.font.color)
)
ann = InspectDR.atext(val.str, x=x, y=y,
font=fnt, angle=val.font.rotation, align=align
)
InspectDR.add(plot, ann)
return
end
# ---------------------------------------------------------------------------
function _inspectdr_getscale(s::Symbol)
#TODO: Support :asinh, :sqrt
if :log2 == s
return InspectDR.AxisScale(:log2)
elseif :log10 == s
return InspectDR.AxisScale(:log10)
elseif :ln == s
return InspectDR.AxisScale(:ln)
else #identity
return InspectDR.AxisScale(:lin)
end
end
# ---------------------------------------------------------------------------
function add_backend_string(::InspectDRBackend)
"""
if !Plots.is_installed("InspectDR")
Pkg.add("InspectDR")
end
"""
end
function _initialize_backend(::InspectDRBackend; kw...)
@eval begin
import InspectDR
export InspectDR
#Glyph used when plotting "Shape"s:
const INSPECTDR_GLYPH_SHAPE = InspectDR.GlyphPolyline(
2*InspectDR.GLYPH_SQUARE.x, InspectDR.GLYPH_SQUARE.y
)
type InspecDRPlotRef
mplot::Union{Void, InspectDR.Multiplot}
gui::Union{Void, InspectDR.GtkPlot}
end
_inspectdr_getmplot(::Any) = nothing
_inspectdr_getmplot(r::InspecDRPlotRef) = r.mplot
_inspectdr_getgui(::Any) = nothing
_inspectdr_getgui(gplot::InspectDR.GtkPlot) = (gplot.destroyed? nothing: gplot)
_inspectdr_getgui(r::InspecDRPlotRef) = _inspectdr_getgui(r.gui)
end
end
# ---------------------------------------------------------------------------
# Create the window/figure for this backend.
function _create_backend_figure(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o)
gplot = _inspectdr_getgui(plt.o)
#:overwrite_figure: want to reuse current figure
if plt[:overwrite_figure] && mplot != nothing
mplot.subplots = [] #Reset
if gplot != nothing #Ensure still references current plot
gplot.src = mplot
end
else #want new one:
mplot = InspectDR.Multiplot()
gplot = nothing #Will be created later
end
#break link with old subplots
for sp in plt.subplots
sp.o = nothing
end
return InspecDRPlotRef(mplot, gplot)
end
# ---------------------------------------------------------------------------
# # this is called early in the pipeline, use it to make the plot current or something
# function _prepare_plot_object(plt::Plot{InspectDRBackend})
# end
# ---------------------------------------------------------------------------
# Set up the subplot within the backend object.
function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend})
plot = sp.o
#Don't do anything without a "subplot" object: Will process later.
if nothing == plot; return; end
plot.data = []
plot.markers = [] #Clear old markers
plot.atext = [] #Clear old annotation
plot.apline = [] #Clear old poly lines
return plot
end
# ---------------------------------------------------------------------------
# Add one series to the underlying backend object.
# Called once per series
# NOTE: Seems to be called when user calls plot()... even if backend
# plot, sp.o has not yet been constructed...
function _series_added(plt::Plot{InspectDRBackend}, series::Series)
st = series[:seriestype]
sp = series[:subplot]
plot = sp.o
#Don't do anything without a "subplot" object: Will process later.
if nothing == plot; return; end
_vectorize(v) = isa(v, Vector)? v: collect(v) #InspectDR only supports vectors
x = _vectorize(series[:x]); y = _vectorize(series[:y])
# doesn't handle mismatched x/y - wrap data (pyplot behaviour):
nx = length(x); ny = length(y)
if nx < ny
series[:x] = Float64[x[mod1(i,nx)] for i=1:ny]
elseif ny > nx
series[:y] = Float64[y[mod1(i,ny)] for i=1:nx]
end
#= TODO: Eventually support
series[:fillcolor] #I think this is fill under line
zorder = series[:series_plotindex]
For st in :shape:
zorder = series[:series_plotindex],
=#
if st in (:shape,)
nmax = 0
for (i,rng) in enumerate(iter_segments(x, y))
nmax = i
if length(rng) > 1
linewidth = series[:linewidth]
linecolor = _inspectdr_mapcolor(cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(cycle(series[:fillcolor], i))
line = InspectDR.line(
style=:solid, width=linewidth, color=linecolor
)
apline = InspectDR.PolylineAnnotation(
x[rng], y[rng], line=line, fillcolor=fillcolor
)
push!(plot.apline, apline)
end
end
i = (nmax >= 2? div(nmax, 2): nmax) #Must pick one set of colors for legend
if i > 1 #Add dummy waveform for legend entry:
linewidth = series[:linewidth]
linecolor = _inspectdr_mapcolor(cycle(series[:linecolor], i))
fillcolor = _inspectdr_mapcolor(cycle(series[:fillcolor], i))
wfrm = InspectDR.add(plot, Float64[], Float64[], id=series[:label])
wfrm.line = InspectDR.line(
style=:none, width=linewidth, #linewidth affects glyph
)
wfrm.glyph = InspectDR.glyph(
shape = INSPECTDR_GLYPH_SHAPE, size = 8,
color = linecolor, fillcolor = fillcolor
)
end
elseif st in (:path, :scatter) #, :steppre, :steppost)
#NOTE: In Plots.jl, :scatter plots have 0-linewidths (I think).
linewidth = series[:linewidth]
#More efficient & allows some support for markerstrokewidth:
_style = (0==linewidth? :none: series[:linestyle])
wfrm = InspectDR.add(plot, x, y, id=series[:label])
wfrm.line = InspectDR.line(
style = _style,
width = series[:linewidth],
color = series[:linecolor],
)
#InspectDR does not control markerstrokewidth independently.
if :none == _style
#Use this property only if no line is displayed:
wfrm.line.width = series[:markerstrokewidth]
end
wfrm.glyph = InspectDR.glyph(
shape = _inspectdr_mapglyph(series[:markershape]),
size = _inspectdr_mapglyphsize(series[:markersize]),
color = _inspectdr_mapcolor(series[:markerstrokecolor]),
fillcolor = _inspectdr_mapcolor(series[:markercolor]),
)
end
# this is all we need to add the series_annotations text
anns = series[:series_annotations]
for (xi,yi,str,fnt) in EachAnn(anns, x, y)
_inspectdr_add_annotations(plot, xi, yi, PlotText(str, fnt))
end
return
end
# ---------------------------------------------------------------------------
# When series data is added/changed, this callback can do dynamic updates to the backend object.
# note: if the backend rebuilds the plot from scratch on display, then you might not do anything here.
function _series_updated(plt::Plot{InspectDRBackend}, series::Series)
#Nothing to do
end
# ---------------------------------------------------------------------------
function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend})
const gridon = InspectDR.grid(vmajor=true, hmajor=true)
const gridoff = InspectDR.grid()
const plot = sp.o
xaxis = sp[:xaxis]; yaxis = sp[:yaxis]
xscale = _inspectdr_getscale(xaxis[:scale])
yscale = _inspectdr_getscale(yaxis[:scale])
plot.axes = InspectDR.AxesRect(xscale, yscale)
xmin, xmax = axis_limits(xaxis)
ymin, ymax = axis_limits(yaxis)
plot.ext = InspectDR.PExtents2D() #reset
plot.ext_full = InspectDR.PExtents2D(xmin, xmax, ymin, ymax)
a = plot.annotation
a.title = sp[:title]
a.xlabel = xaxis[:guide]; a.ylabel = yaxis[:guide]
l = plot.layout
l.framedata.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside])
l.framedata.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis])
l.fnttitle = InspectDR.Font(sp[:titlefont].family,
_inspectdr_mapptsize(sp[:titlefont].pointsize),
color = _inspectdr_mapcolor(sp[:foreground_color_title])
)
#Cannot independently control fonts of axes with InspectDR:
l.fntaxlabel = InspectDR.Font(xaxis[:guidefont].family,
_inspectdr_mapptsize(xaxis[:guidefont].pointsize),
color = _inspectdr_mapcolor(xaxis[:foreground_color_guide])
)
l.fntticklabel = InspectDR.Font(xaxis[:tickfont].family,
_inspectdr_mapptsize(xaxis[:tickfont].pointsize),
color = _inspectdr_mapcolor(xaxis[:foreground_color_text])
)
#No independent control of grid???
l.grid = sp[:grid]? gridon: gridoff
leg = l.legend
leg.enabled = (sp[:legend] != :none)
#leg.width = 150 #TODO: compute???
leg.font = InspectDR.Font(sp[:legendfont].family,
_inspectdr_mapptsize(sp[:legendfont].pointsize),
color = _inspectdr_mapcolor(sp[:foreground_color_legend])
)
leg.frame.fillcolor = _inspectdr_mapcolor(sp[:background_color_legend])
end
# called just before updating layout bounding boxes... in case you need to prep
# for the calcs
function _before_layout_calcs(plt::Plot{InspectDRBackend})
const mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end
resize!(mplot.subplots, length(plt.subplots))
nsubplots = length(plt.subplots)
for (i, sp) in enumerate(plt.subplots)
if !isassigned(mplot.subplots, i)
mplot.subplots[i] = InspectDR.Plot2D()
end
sp.o = mplot.subplots[i]
_initialize_subplot(plt, sp)
_inspectdr_setupsubplot(sp)
sp.o.layout.frame.fillcolor =
_inspectdr_mapcolor(plt[:background_color_outside])
# add the annotations
for ann in sp[:annotations]
_inspectdr_add_annotations(mplot.subplots[i], ann...)
end
end
#Do not yet support absolute plot positionning.
#Just try to make things look more-or less ok:
if nsubplots <= 1
mplot.ncolumns = 1
elseif nsubplots <= 4
mplot.ncolumns = 2
elseif nsubplots <= 6
mplot.ncolumns = 3
elseif nsubplots <= 12
mplot.ncolumns = 4
else
mplot.ncolumns = 5
end
for series in plt.series_list
_series_added(plt, series)
end
return
end
# ----------------------------------------------------------------
# Set the (left, top, right, bottom) minimum padding around the plot area
# to fit ticks, tick labels, guides, colorbars, etc.
function _update_min_padding!(sp::Subplot{InspectDRBackend})
sp.minpad = (20mm, 5mm, 2mm, 10mm)
#TODO: Add support for padding.
end
# ----------------------------------------------------------------
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations])
function _update_plot_object(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end
gplot = _inspectdr_getgui(plt.o)
if nothing == gplot; return; end
gplot.src = mplot #Ensure still references current plot
InspectDR.refresh(gplot)
return
end
# ----------------------------------------------------------------
const _inspectdr_mimeformats_dpi = Dict(
"image/png" => "png"
)
const _inspectdr_mimeformats_nodpi = Dict(
"image/svg+xml" => "svg",
"application/eps" => "eps",
"image/eps" => "eps",
# "application/postscript" => "ps", #TODO: support once Cairo supports PSSurface
"application/pdf" => "pdf"
)
_inspectdr_show(io::IO, mime::MIME, ::Void) =
throw(ErrorException("Cannot show(::IO, ...) plot - not yet generated"))
_inspectdr_show(io::IO, mime::MIME, mplot) = show(io, mime, mplot)
for (mime, fmt) in _inspectdr_mimeformats_dpi
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
dpi = plt[:dpi]#TODO: support
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o))
end
end
for (mime, fmt) in _inspectdr_mimeformats_nodpi
@eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend})
_inspectdr_show(io, mime, _inspectdr_getmplot(plt.o))
end
end
_show(io::IO, mime::MIME"text/plain", plt::Plot{InspectDRBackend}) = nothing #Don't show
# ----------------------------------------------------------------
# Display/show the plot (open a GUI window, or browser page, for example).
function _display(plt::Plot{InspectDRBackend})
mplot = _inspectdr_getmplot(plt.o)
if nothing == mplot; return; end
gplot = _inspectdr_getgui(plt.o)
if nothing == gplot
gplot = display(InspectDR.GtkDisplay(), mplot)
else
#redundant... Plots.jl will call _update_plot_object:
#InspectDR.refresh(gplot)
end
plt.o = InspecDRPlotRef(mplot, gplot)
return gplot
end
+7 -1
View File
@@ -314,12 +314,18 @@ function _show(io::IO, mime::MIME"application/pdf", plt::Plot{PGFPlotsBackend})
PGFPlots.save(PGFPlots.PDF(fn), pgfplt)
# read it into io
write(io, readall(open(fn)))
write(io, readstring(open(fn)))
# cleanup
PGFPlots.cleanup(plt.o)
end
function _show(io::IO, mime::MIME"application/x-tex", plt::Plot{PGFPlotsBackend})
fn = tempname()*".tex"
PGFPlots.save(fn, backend_object(plt), include_preamble=false)
write(io, readstring(open(fn)))
end
function _display(plt::Plot{PGFPlotsBackend})
# prepare the object
pgfplt = PGFPlots.plot(plt.o)
+5 -1
View File
@@ -20,7 +20,7 @@ const _plotly_attr = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :levels,
:marker_z, :fill_z, :levels,
:ribbon, :quiver,
:orientation,
# :overwrite_figure,
@@ -371,6 +371,7 @@ end
plotly_colorscale(c, α) = plotly_colorscale(cgrad(alpha=α), α)
# plotly_colorscale(c, alpha = nothing) = plotly_colorscale(cgrad(), alpha)
const _plotly_markers = KW(
:rect => "square",
:xcross => "x",
@@ -488,6 +489,9 @@ function plotly_series(plt::Plot, series::Series)
d_out[:contours] = KW(:x => wirelines, :y => wirelines, :z => wirelines)
else
d_out[:colorscale] = plotly_colorscale(series[:fillcolor], series[:fillalpha])
if series[:fill_z] != nothing
d_out[:surfacecolor] = plotly_surface_data(series, series[:fill_z])
end
end
elseif st == :pie
+7 -13
View File
@@ -18,8 +18,7 @@ const _pyplot_attr = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z,
:line_z,
:marker_z, :line_z, :fill_z,
:levels,
:ribbon, :quiver, :arrow,
:orientation,
@@ -124,8 +123,8 @@ end
py_colormap(c) = py_colormap(cgrad())
function py_shading(c, z, α=nothing)
cmap = py_colormap(c, α)
function py_shading(c, z)
cmap = py_colormap(c)
ls = pycolors.pymember("LightSource")(270,45)
ls[:shade](z, cmap, vert_exag=0.1, blend_mode="soft")
end
@@ -668,21 +667,16 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
x = repmat(x', length(y), 1)
y = repmat(y, 1, length(series[:x]))
end
# z = z'
z = transpose_z(series, z)
if st == :surface
if series[:marker_z] != nothing
extrakw[:facecolors] = py_shading(series[:fillcolor], series[:marker_z], series[:fillalpha])
if series[:fill_z] != nothing
# the surface colors are different than z-value
extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf))
extrakw[:shade] = false
clims = sp[:clims]
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
else
extrakw[:cmap] = py_fillcolormap(series)
needs_colorbar = true
end
needs_colorbar = true
end
handle = ax[st == :surface ? :plot_surface : :plot_wireframe](x, y, z;
label = series[:label],
+6 -6
View File
@@ -1,7 +1,7 @@
typealias P2 FixedSizeArrays.Vec{2,Float64}
typealias P3 FixedSizeArrays.Vec{3,Float64}
typealias P2 StaticArrays.SVector{2,Float64}
typealias P3 StaticArrays.SVector{3,Float64}
nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b))
nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b))
@@ -184,7 +184,7 @@ function Base.scale!(shape::Shape, x::Real, y::Real = x, c = center(shape))
shape
end
function Base.scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
function scale(shape::Shape, x::Real, y::Real = x, c = center(shape))
shapecopy = deepcopy(shape)
scale!(shapecopy, x, y, c)
end
@@ -248,7 +248,7 @@ end
function font(args...)
# defaults
family = "Helvetica"
family = "sans-serif"
pointsize = 14
halign = :hcenter
valign = :vcenter
@@ -632,7 +632,7 @@ end
# -----------------------------------------------------------------------
type BezierCurve{T <: FixedSizeArrays.Vec}
type BezierCurve{T <: StaticArrays.SVector}
control_points::Vector{T}
end
@@ -646,7 +646,7 @@ function (bc::BezierCurve)(t::Real)
end
Base.mean(x::Real, y::Real) = 0.5*(x+y)
Base.mean{N,T<:Real}(ps::FixedSizeArrays.Vec{N,T}...) = sum(ps) / length(ps)
Base.mean{N,T<:Real}(ps::StaticArrays.SVector{N,T}...) = sum(ps) / length(ps)
@deprecate curve_points coords
+1
View File
@@ -154,6 +154,7 @@ const _mimeformats = Dict(
"application/postscript" => "ps",
"image/svg+xml" => "svg",
"text/plain" => "txt",
"application/x-tex" => "tex",
)
const _best_html_output_type = KW(
+4 -4
View File
@@ -29,12 +29,12 @@ convertSeriesIndex(plt::Plot, n::Int) = n
"""
The main plot command. Use `plot` to create a new plot object, and `plot!` to add to an existing one:
The main plot command. Use `plot` to create a new plot object, and `plot!` to mutate an existing one:
```
plot(args...; kw...) # creates a new plot window, and sets it to be the current
plot!(args...; kw...) # adds to the `current`
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
plot(args...; kw...) # creates a new Plot, and sets it to be the current
plot!(args...; kw...) # adds to the `current` Plot
plot!(plotobj, args...; kw...) # adds to the Plot `plotobj`
```
There are lots of ways to pass in data, and lots of keyword arguments... just try it and it will likely work as expected.
+19 -4
View File
@@ -257,12 +257,23 @@ end
# # 1 argument
# # --------------------------------------------------------------------
# helper function to ensure relevant attributes are wrapped by Surface
function wrap_surfaces(d::KW)
if haskey(d, :fill_z)
v = d[:fill_z]
if !isa(v, Surface)
d[:fill_z] = Surface(v)
end
end
end
@recipe f(n::Integer) = is3d(get(d,: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
@recipe function f{T<:Union{Integer,AbstractFloat}}(mat::AMat{T})
if all3D(d)
n,m = size(mat)
wrap_surfaces(d)
SliceIt, 1:m, 1:n, Surface(mat)
else
SliceIt, nothing, mat, nothing
@@ -274,6 +285,7 @@ end
if all3D(d)
mat = fmt.data
n,m = size(mat)
wrap_surfaces(d)
SliceIt, 1:m, 1:n, Formatted(Surface(mat), fmt.formatter)
else
SliceIt, nothing, fmt, nothing
@@ -391,6 +403,7 @@ end
# seriestype := :path3d
# end
# end
wrap_surfaces(d)
SliceIt, x, y, z
end
@@ -400,6 +413,7 @@ end
@recipe function f(x::AVec, y::AVec, zf::Function)
# x = X <: Number ? sort(x) : x
# y = Y <: Number ? sort(y) : y
wrap_surfaces(d)
SliceIt, x, y, Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported
end
@@ -410,6 +424,7 @@ end
if !like_surface(get(d, :seriestype, :none))
d[:seriestype] = :contour
end
wrap_surfaces(d)
SliceIt, x, y, Surface(z)
end
@@ -467,13 +482,13 @@ end
#
# # 2D FixedSizeArrays
@recipe f{T<:Number}(xy::AVec{FixedSizeArrays.Vec{2,T}}) = unzip(xy)
@recipe f{T<:Number}(xy::FixedSizeArrays.Vec{2,T}) = [xy[1]], [xy[2]]
@recipe f{T<:Number}(xy::AVec{StaticArrays.SVector{2,T}}) = unzip(xy)
@recipe f{T<:Number}(xy::StaticArrays.SVector{2,T}) = [xy[1]], [xy[2]]
#
# # 3D FixedSizeArrays
@recipe f{T<:Number}(xyz::AVec{FixedSizeArrays.Vec{3,T}}) = unzip(xyz)
@recipe f{T<:Number}(xyz::FixedSizeArrays.Vec{3,T}) = [xyz[1]], [xyz[2]], [xyz[3]]
@recipe f{T<:Number}(xyz::AVec{StaticArrays.SVector{3,T}}) = unzip(xyz)
@recipe f{T<:Number}(xyz::StaticArrays.SVector{3,T}) = [xyz[1]], [xyz[2]], [xyz[3]]
#
# # --------------------------------------------------------------------
+6 -6
View File
@@ -271,14 +271,14 @@ unzip{X,Y}(xy::AVec{Tuple{X,Y}}) = [t[1] for t in xy], [t[2] for t
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{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{T}(xy::AVec{FixedSizeArrays.Vec{2,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{T}(xy::AVec{StaticArrays.SVector{2,T}}) = T[t[1] for t in xy], T[t[2] for t in xy]
unzip{T}(xy::StaticArrays.SVector{2,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{T}(xyz::FixedSizeArrays.Vec{3,T}) = T[xyz[1]], T[xyz[2]], T[xyz[3]]
unzip{T}(xyz::AVec{StaticArrays.SVector{3,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::StaticArrays.SVector{3,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{T}(xyuv::FixedSizeArrays.Vec{4,T}) = T[xyuv[1]], T[xyuv[2]], T[xyuv[3]], T[xyuv[4]]
unzip{T}(xyuv::AVec{StaticArrays.SVector{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{T}(xyuv::StaticArrays.SVector{4,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
function _expand_limits(lims, x)