working on axis/line/marker/fill overhaul

This commit is contained in:
Thomas Breloff 2015-10-06 08:45:53 -05:00
parent ea88877a11
commit b23f968d57
11 changed files with 197 additions and 48 deletions

View File

@ -300,12 +300,25 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": []
"outputs": [
{
"data": {
"text/plain": [
"Tuple{}"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"() |> typeof"
]
},
{
"cell_type": "code",

View File

@ -101,20 +101,23 @@ const _seriesDefaults = Dict{Symbol, Any}()
_seriesDefaults[:axis] = :left
_seriesDefaults[:color] = :auto
_seriesDefaults[:label] = "AUTO"
_seriesDefaults[:width] = 1
_seriesDefaults[:linetype] = :path
_seriesDefaults[:linestyle] = :solid
_seriesDefaults[:linewidth] = 1
_seriesDefaults[:marker] = :none
_seriesDefaults[:markercolor] = :match
_seriesDefaults[:markersize] = 6
_seriesDefaults[:fill] = nothing # ribbons, areas, etc
_seriesDefaults[:fillcolor] = :match
# _seriesDefaults[:ribbon] = nothing
# _seriesDefaults[:ribboncolor] = :match
_seriesDefaults[:nbins] = 100 # number of bins for heatmaps and hists
_seriesDefaults[:heatmap_c] = (0.15, 0.5)
_seriesDefaults[:fillto] = nothing # fills in the area
_seriesDefaults[:heatmap_c] = (0.15, 0.5) # TODO: this should be replaced with a ColorGradient
# _seriesDefaults[:fillto] = nothing # fills in the area
_seriesDefaults[:reg] = false # regression line?
_seriesDefaults[:group] = nothing
_seriesDefaults[:ribbon] = nothing
_seriesDefaults[:annotation] = nothing
_seriesDefaults[:z] = nothing
_seriesDefaults[:group] = nothing # groupby vector
_seriesDefaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation)
_seriesDefaults[:z] = nothing # depth for contour, color scale, etc
# _seriesDefaults[:args] = [] # additional args to pass to the backend
# _seriesDefaults[:kwargs] = [] # additional keyword args to pass to the backend
# # note: can be Vector{Dict} or Vector{Tuple}
@ -136,6 +139,8 @@ _plotDefaults[:xticks] = :auto
_plotDefaults[:yticks] = :auto
_plotDefaults[:xscale] = :identity
_plotDefaults[:yscale] = :identity
_plotDefaults[:xflip] = false
_plotDefaults[:yflip] = true
_plotDefaults[:size] = (800,600)
_plotDefaults[:pos] = (0,0)
_plotDefaults[:windowtitle] = "Plots.jl"
@ -184,8 +189,9 @@ end
const _keyAliases = Dict(
:c => :color,
:lab => :label,
:w => :width,
:linewidth => :width,
:w => :linewidth,
:width => :linewidth,
:lw => :linewidth,
:type => :linetype,
:lt => :linetype,
:t => :linetype,
@ -287,6 +293,125 @@ function default(; kw...)
end
end
# -----------------------------------------------------------------------------
wraptuple(x::Tuple) = x
wraptuple(x) = (x,)
# given one value (:log, or :flip, or (-1,1), etc), set the appropriate arg
function processAxisArg(d::Dict, axisletter::AbstractString, arg)
if isa(arg, Symbol)
# xscale/yscale
if haskey(_scaleAliases, arg)
arg = _scaleAliases[arg]
end
if arg in _allScales
d[symbol(axisletter * "scale")] = arg
end
# xflip/yflip
if arg in (:flip, :invert, :inverted)
d[symbol(axisletter * "flip")] = true
end
# xlims/ylims
elseif (arg <: Tuple || arg <: AVec) && length(arg) == 2
d[symbol(axisletter * "lims")] = arg
# xticks/yticks
elseif arg <: AVec
d[symbol(axisletter * "ticks")] = arg
else
warn("Skipped $(axisletter)axis arg $arg. Unhandled type $(typeof(arg))")
end
end
function processLineArg(d::Dict, arg)
if isa(arg, Symbol)
# linetype
if haskey(_typeAliases, arg)
arg = _typeAliases[arg]
end
if arg in _allTypes
d[:linetype] = arg
end
# linestyle
if haskey(_styleAliases, arg)
arg = _styleAliases[arg]
end
if arg in _allStyles
d[:linestyle] = arg
end
# linewidth
elseif arg <: Real
d[:linewidth] = arg
else
try
c = colorscheme(arg)
d[:color] = c
catch
warn("Skipped line arg $arg. Unhandled type $(typeof(arg))")
end
end
end
function processMarkerArg(d::Dict, arg)
if isa(arg, Symbol)
# shape
if haskey(_markerAliases, arg)
arg = _markerAliases[arg]
end
if arg in _allMarkers
d[:marker] = arg
end
# linestyle
if haskey(_styleAliases, arg)
arg = _styleAliases[arg]
end
if arg in _allStyles
d[:linestyle] = arg
end
# markersize
elseif arg <: Real
d[:markersize] = arg
else
warn("Skipped line arg $arg. Unhandled type $(typeof(arg))")
end
end
"Handle all preprocessing of args... break out colors/sizes/etc and replace aliases."
function preprocessArgs!(d::Dict)
replaceAliases!(d, _keyAliases)
for axisletter in ("x", "y")
for arg in wraptuple(get(d, symbol(axisletter * "axis"), ()))
processAxisArg(d, axisletter, arg)
end
end
for arg in wraptuple(get(d, :line, ()))
processLineArg(d, arg)
end
for arg in wraptuple(get(d, :marker, ()))
processMarkerArg(d, arg)
end
end
# -----------------------------------------------------------------------------

View File

@ -24,6 +24,7 @@ supportedArgs(::GadflyPackage) = [
:legend,
:linestyle,
:linetype,
:linewidth,
:marker,
:markercolor,
:markersize,
@ -37,7 +38,6 @@ supportedArgs(::GadflyPackage) = [
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
@ -97,7 +97,7 @@ function getLineGeoms(d::Dict)
lt == :bar && return [Gadfly.Geom.bar]
lt == :steppost && return [Gadfly.Geom.step]
# NOTE: we won't actually show this (we'll set width to 0 later), but we need a geom so that Gadfly doesn't complain
# NOTE: we won't actually show this (we'll set linewidth to 0 later), but we need a geom so that Gadfly doesn't complain
if lt in (:none, :ohlc, :scatter)
return [Gadfly.Geom.path]
end
@ -121,7 +121,7 @@ end
function addGadflyFixedLines!(gplt, d::Dict, theme)
sz = d[:width] * Gadfly.px
sz = d[:linewidth] * Gadfly.px
c = d[:color]
if d[:linetype] == :hline
@ -151,8 +151,8 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
extra_theme_args = []
end
# set theme: color, line width, and point size
line_width = d[:width] * (d[:linetype] in (:none, :ohlc, :scatter) ? 0 : 1) * Gadfly.px # 0 width when we don't show a line
# set theme: color, line linewidth, and point size
line_width = d[:linewidth] * (d[:linetype] in (:none, :ohlc, :scatter) ? 0 : 1) * Gadfly.px # 0 linewidth when we don't show a line
line_color = isa(d[:color], AbstractVector) ? colorant"black" : d[:color]
# fg = initargs[:foreground_color]
theme = Gadfly.Theme(; default_color = line_color,

View File

@ -25,6 +25,7 @@ supportedArgs(::PyPlotPackage) = [
:legend,
:linestyle,
:linetype,
:linewidth,
:marker,
:markercolor,
:markersize,
@ -38,7 +39,6 @@ supportedArgs(::PyPlotPackage) = [
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
@ -208,12 +208,12 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
end
elseif lt in (:hline,:vline)
linewidth = d[:width]
linewidth = d[:linewidth]
linecolor = getPyPlotColor(d[:color])
linestyle = getPyPlotLineStyle(lt, d[:linestyle])
for yi in d[:y]
func = (lt == :hline ? PyPlot.axhline : PyPlot.axvline)
func(yi, linewidth=d[:width], color=linecolor, linestyle=linestyle)
func(yi, linewidth=d[:linewidth], color=linecolor, linestyle=linestyle)
end
end
@ -232,7 +232,7 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
if lt == :hist
extraargs[:bins] = d[:nbins]
else
extraargs[:width] = (lt == :sticks ? 0.1 : 0.9)
extraargs[:linewidth] = (lt == :sticks ? 0.1 : 0.9)
end
elseif lt in (:heatmap, :hexbin)
@ -247,7 +247,7 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
if lt == :scatter
extraargs[:s] = d[:markersize]
extraargs[:c] = getPyPlotColor(d[:markercolor])
extraargs[:linewidths] = d[:width]
extraargs[:linewidths] = d[:linewidth]
if haskey(d, :colorscheme)
extraargs[:cmap] = d[:colorscheme]
end
@ -261,7 +261,7 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
# set these for all types
extraargs[:figure] = plt.o
extraargs[:color] = getPyPlotColor(d[:color])
extraargs[:linewidth] = d[:width]
extraargs[:linewidth] = d[:linewidth]
extraargs[:label] = d[:label]
# do the plot

View File

@ -23,6 +23,7 @@ supportedArgs(::QwtPackage) = [
:legend,
:linestyle,
:linetype,
:linewidth,
:marker,
:markercolor,
:markersize,
@ -36,7 +37,6 @@ supportedArgs(::QwtPackage) = [
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
@ -173,7 +173,7 @@ end
# ----------------------------------------------------------------
# curve.setPen(Qt.QPen(Qt.QColor(color), width, self.getLineStyle(linestyle)))
# curve.setPen(Qt.QPen(Qt.QColor(color), linewidth, self.getLineStyle(linestyle)))
function addLineMarker(plt::Plot{QwtPackage}, d::Dict)
for yi in d[:y]
marker = Qwt.QWT.QwtPlotMarker()
@ -182,7 +182,7 @@ function addLineMarker(plt::Plot{QwtPackage}, d::Dict)
marker[ishorizontal ? :setYValue : :setXValue](yi)
qcolor = Qwt.convertRGBToQColor(d[:color])
linestyle = plt.o.widget[:getLineStyle](string(d[:linestyle]))
marker[:setLinePen](Qwt.QT.QPen(qcolor, d[:width], linestyle))
marker[:setLinePen](Qwt.QT.QPen(qcolor, d[:linewidth], linestyle))
marker[:attach](plt.o.widget)
end

View File

@ -27,6 +27,7 @@ supportedArgs(::[PkgName]Package) = [
:legend,
:linestyle,
:linetype,
:linewidth,
:marker,
:markercolor,
:markersize,
@ -40,7 +41,6 @@ supportedArgs(::[PkgName]Package) = [
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,

View File

@ -25,6 +25,7 @@ supportedArgs(::UnicodePlotsPackage) = [
:legend,
:linestyle,
:linetype,
# :linewidth,
:marker,
# :markercolor,
# :markersize,
@ -38,7 +39,6 @@ supportedArgs(::UnicodePlotsPackage) = [
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,

View File

@ -47,6 +47,7 @@ supportedArgs(::WinstonPackage) = [
:legend,
:linestyle,
:linetype,
:linewidth,
:marker,
:markercolor,
:markersize,
@ -60,7 +61,6 @@ supportedArgs(::WinstonPackage) = [
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
@ -89,15 +89,6 @@ end
# ---------------------------------------------------------------------------
# function createWinstonFigure(d::Dict)
# # println("Creating immerse figure: ", d)
# w,h = d[:size]
# figidx = Winston.figure(; name = d[:windowtitle], width = w, height = h)
# Winston.Figure(figidx)
# end
function plot(pkg::WinstonPackage; kw...)
d = Dict(kw)
wplt = Winston.FramedPlot(title = d[:title], xlabel = d[:xlabel], ylabel = d[:ylabel])
@ -139,7 +130,7 @@ function plot!(::WinstonPackage, plt::Plot; kw...)
e = Dict()
e[:color] = d[:color]
e[:linewidth] = d[:width]
e[:linewidth] = d[:linewidth]
e[:kind] = winston_linestyle[d[:linestyle]]
e[:symbolkind] = winston_marker[d[:marker]]
# markercolor # same choices as `color`, or :match will set the color to be the same as `color`

View File

@ -83,6 +83,14 @@ abstract ColorScheme
getColor(scheme::ColorScheme, idx::Integer) = getColor(scheme, 0.0, idx)
getColor(scheme::ColorScheme, z::AbstractFloat) = getColor(scheme, z, 0)
colorscheme(s::Symbol) = haskey(_gradients, s) ? ColorGradient(s) : ColorWrapper(convertColor(s))
colorscheme{T<:Real}(s::Symbol, vals::AVec{T}) = ColorGradient(s, vals)
colorscheme(cs::AVec, vs::AVec) = ColorGradient(cs, vs)
colorscheme(f::Function) = ColorFunction(f)
colorscheme(v::AVec) = ColorVector(v)
colorscheme(c::Colorant) = ColorWrapper(c)
const _gradients = Dict(
:blues => [colorant"lightblue", colorant"darkblue"],
:reds => [colorant"lightpink", colorant"darkred"],
@ -94,7 +102,7 @@ const _gradients = Dict(
# --------------------------------------------------------------
"Continuous gradient between values. Wraps a list of bounding colors and the values they represent."
type ColorGradient <: ColorScheme
immutable ColorGradient <: ColorScheme
colors::Vector{Colorant}
values::Vector{Float64}
end
@ -151,24 +159,36 @@ end
# --------------------------------------------------------------
"Wraps a function, taking a z-value and index and returning a Colorant"
type ColorFunction <: ColorScheme
immutable ColorFunction <: ColorScheme
f::Function
end
typealias CFun ColorFunction
getColor(grad::ColorFunction, z::Real, idx::Int) = grad.f(z, idx)
getColor(scheme::ColorFunction, z::Real, idx::Int) = scheme.f(z, idx)
# --------------------------------------------------------------
"Wraps a vector of colors... may be Symbol/String or a Colorant"
type ColorVector{V<:AbstractVector} <: ColorScheme
immutable ColorVector{V<:AbstractVector} <: ColorScheme
v::V
end
typealias CVec ColorVector
getColor(grad::ColorVector, z::Real, idx::Int) = convertColor(grad.v[mod1(idx, length(grad.v))])
getColor(scheme::ColorVector, z::Real, idx::Int) = convertColor(scheme.v[mod1(idx, length(scheme.v))])
# --------------------------------------------------------------
"Wraps a single color"
immutable ColorWrapper{C<:Colorant} <: ColorScheme
c::C
end
typealias CWrap ColorWrapper
getColor(scheme::ColorWrapper, z::Real, idx::Int) = scheme.c
# --------------------------------------------------------------

View File

@ -45,7 +45,7 @@ When you pass in matrices, it splits by columns. See the documentation for more
function plot(args...; kw...)
pkg = backend()
d = Dict(kw)
replaceAliases!(d, _keyAliases)
preprocessArgs!(d)
# # ensure we're passing in an RGB
# if haskey(d, :background_color)
@ -80,7 +80,7 @@ end
function plot!(plt::Plot, args...; kw...)
d = Dict(kw)
replaceAliases!(d, _keyAliases)
preprocessArgs!(d)
warnOnUnsupportedArgs(plt.backend, d)

View File

@ -60,7 +60,7 @@ Create a series of plots:
"""
function subplot(args...; kw...)
d = Dict(kw)
replaceAliases!(d, _keyAliases)
preprocessArgs!(d)
# figure out the layout
layoutarg = get(d, :layout, nothing)
@ -119,7 +119,7 @@ function subplot!(subplt::Subplot, args...; kw...)
end
d = Dict(kw)
replaceAliases!(d, _keyAliases)
preprocessArgs!(d)
for k in keys(_plotDefaults)
delete!(d, k)
end