diff --git a/examples/colors.ipynb b/examples/colors.ipynb index 8166b6b8..203ed8ac 100644 --- a/examples/colors.ipynb +++ b/examples/colors.ipynb @@ -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", diff --git a/src/args.jl b/src/args.jl index 5c8624f6..f773ec38 100644 --- a/src/args.jl +++ b/src/args.jl @@ -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 # ----------------------------------------------------------------------------- diff --git a/src/backends/gadfly.jl b/src/backends/gadfly.jl index b889a808..57aa17cf 100644 --- a/src/backends/gadfly.jl +++ b/src/backends/gadfly.jl @@ -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, diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index b699a04b..52b9815b 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -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 diff --git a/src/backends/qwt.jl b/src/backends/qwt.jl index daadcb24..8a1fc5cc 100644 --- a/src/backends/qwt.jl +++ b/src/backends/qwt.jl @@ -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 diff --git a/src/backends/template.jl b/src/backends/template.jl index 81dc2c7d..3fd401bb 100644 --- a/src/backends/template.jl +++ b/src/backends/template.jl @@ -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, diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index 11b2bf0b..dc632470 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -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, diff --git a/src/backends/winston.jl b/src/backends/winston.jl index dea2be6f..5a558ed3 100644 --- a/src/backends/winston.jl +++ b/src/backends/winston.jl @@ -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` diff --git a/src/colors.jl b/src/colors.jl index 32a1529f..5ebae5fb 100644 --- a/src/colors.jl +++ b/src/colors.jl @@ -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 # -------------------------------------------------------------- diff --git a/src/plot.jl b/src/plot.jl index 174ee078..16c70645 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -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) diff --git a/src/subplot.jl b/src/subplot.jl index 73c15e9f..dc7ae2a9 100644 --- a/src/subplot.jl +++ b/src/subplot.jl @@ -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