From 73944fc9bf7d9f92cfe4816383b9cbe6291f8bd1 Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Wed, 16 Sep 2015 15:08:50 -0400 Subject: [PATCH] first draft winston --- src/backends/gadfly.jl | 2 +- src/backends/pyplot.jl | 4 +- src/backends/template.jl | 8 +- src/backends/winston.jl | 165 +++++++++++++++++++++++++++++++++++++++ src/utils.jl | 13 +++ 5 files changed, 185 insertions(+), 7 deletions(-) create mode 100644 src/backends/winston.jl diff --git a/src/backends/gadfly.jl b/src/backends/gadfly.jl index 6e98e269..38201fcc 100644 --- a/src/backends/gadfly.jl +++ b/src/backends/gadfly.jl @@ -8,7 +8,7 @@ gadfly!() = plotter!(:gadfly) supportedArgs(::GadflyPackage) = setdiff(ARGS, [:heatmap_c, :fillto, :pos]) supportedAxes(::GadflyPackage) = setdiff(ALL_AXES, [:right]) -supportedTypes(::GadflyPackage) = setdiff(TYPES, [:stepinverted]) +supportedTypes(::GadflyPackage) = setdiff(ALL_TYPES, [:stepinverted]) supportedStyles(::GadflyPackage) = [:auto, :solid] supportedMarkers(::GadflyPackage) = [:none, :auto, :rect, :ellipse, :diamond, :cross] diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index dfa8d441..4dcd67de 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -8,8 +8,8 @@ pyplot!() = plotter!(:pyplot) # ------------------------------- supportedArgs(::PyPlotPackage) = setdiff(ARGS, [:reg, :heatmap_c, :fillto, :pos]) -# supportedAxes(::PyPlotPackage) = [:left] -# supportedTypes(::PyPlotPackage) = setdiff(TYPES, [:stepinverted]) +supportedAxes(::PyPlotPackage) = ALL_AXES +supportedTypes(::PyPlotPackage) = ALL_TYPES supportedStyles(::PyPlotPackage) = setdiff(ALL_STYLES, [:dashdotdot]) supportedMarkers(::PyPlotPackage) = setdiff(ALL_MARKERS, [:star2]) subplotSupported(::PyPlotPackage) = false diff --git a/src/backends/template.jl b/src/backends/template.jl index 5f902dd0..cba73911 100644 --- a/src/backends/template.jl +++ b/src/backends/template.jl @@ -10,10 +10,10 @@ immutable [PkgName]Package <: PlottingPackage end # --------------------------------------------------------------------------- supportedArgs(::[PkgName]Package) = ARGS -supportedAxes(::[PkgName]Package) = AXES -supportedTypes(::[PkgName]Package) = TYPES -supportedStyles(::[PkgName]Package) = STYLES -supportedMarkers(::[PkgName]Package) = MARKERS +supportedAxes(::[PkgName]Package) = ALL_AXES +supportedTypes(::[PkgName]Package) = ALL_TYPES +supportedStyles(::[PkgName]Package) = ALL_STYLES +supportedMarkers(::[PkgName]Package) = ALL_MARKERS subplotSupported(::[PkgName]Package) = false # --------------------------------------------------------------------------- diff --git a/src/backends/winston.jl b/src/backends/winston.jl new file mode 100644 index 00000000..4b540899 --- /dev/null +++ b/src/backends/winston.jl @@ -0,0 +1,165 @@ + +# https://github.com/nolta/Winston.jl + +# credit goes to https://github.com/jverzani for the first draft of this backend implementation + +immutable WinstonPackage <: PlottingPackage end + +winston!() = plotter!(:winston) + +# --------------------------------------------------------------------------- + + +## dictionaries for conversion of Plots.jl names to Winston ones. +const winston_linestyle = Dict(:solid=>"solid", + :dash=>"dash", + :dot=>"dotted", + :dashdot=>"dotdashed", + :dashdotdot=>"dotdashed") + +const winston_marker = Dict(:none=>".", + :ellipse=>"circle", + :rect => "square", + :diamond=>"diamond", + :utriangle=>"triangle", + :dtriangle=>"down-triangle", + :cross => "cross", + :xcross => "cross", + :star1 => "asterisk", + :star2 => "filled circle", + :hexagon => "asterisk" + ) + + +supportedArgs(::WinstonPackage) = ARGS +supportedAxes(::WinstonPackage) = [:auto, :left] +supportedTypes(::WinstonPackage) = [:none, :line, :sticks, :scatter, :hist, :bar] +supportedStyles(::WinstonPackage) = vcat(:auto, keys(winston_linestyle)) +supportedMarkers(::WinstonPackage) = vcat(:auto, collect(keys(winston_marker))) +subplotSupported(::WinstonPackage) = false + +# --------------------------------------------------------------------------- + +function plot(pkg::WinstonPackage; kw...) + d = Dict(kw) + # TODO: create the window/canvas/context that is the plot within the backend (call it `o`) + # TODO: initialize the plot... title, xlabel, bgcolor, etc + + o = Winston.FramedPlot() + + # add the title, axis labels, and theme + Winston.setattr(o, "xlabel", d[:xlabel]) + Winston.setattr(o, "ylabel", d[:ylabel]) + Winston.setattr(o, "title", d[:title]) + + # TODO: add the legend? + + Plot(o, pkg, 0, d, Dict[]) +end + +copy_remove(d::Dict, s::Symbol) = delete!(copy(d), s) + +function addRegressionLineWinston(d::Dict) + xs, ys = regressionXY(d[:x], d[:y]) + Winston.add(plt.o, Winston.Curve(xs, ys, kind="dotted")) +end + +function plot!(::WinstonPackage, plt::Plot; kw...) + d = Dict(kw) + # TODO: add one series to the underlying package + + # until we call it normally, do the hack + if d[:linetype] == :bar + d = barHack(;d...) + end + + + e = Dict() + e[:color] = d[:color] + # label # string or symbol, applies to that line, may go in a legend + e[:linewidth] = d[:width] + 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` + e[:symbolsize] = d[:markersize] / 3 + # fillto # fillto value for area plots + + # size # (Int,Int), resize the enclosing window + # pos # (Int,Int), move the enclosing window to this position + # windowtitle # string or symbol, set the title of the enclosing windowtitle + # screen # Integer, move enclosing window to this screen number (for multiscreen desktops) + + + + ## lintype :line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hexbin, :hist, :bar + if d[:linetype] == :none + Winston.add(plt.o, Winston.Points(d[:x], d[:y]; copy_remove(e, :kind)...)) + + elseif d[:linetype] == :line + Winston.add(plt.o, Winston.Curve(d[:x], d[:y]; e...)) + + # elseif d[:linetype] == :step + # fn = Winston.XXX + + # elseif d[:linetype] == :stepinverted + # fn = Winston.XXX + + elseif d[:linetype] == :sticks + Winston.add(plt.o, Winston.Stems(d[:x], d[:y]; e...)) + + # elseif d[:linetype] == :dots + # fn = Winston.XXX + + # elseif d[:linetype] == :heatmap + # fn = Winston.XXX + + # elseif d[:linetype] == :hexbin + # fn = Winston.XXX + + elseif d[:linetype] == :hist + hst = hist(d[:y], d[:nbins]) + Winston.add(plt.o, Winston.Histogram(hst...; copy_remove(e, :nbins)...)) + + # elseif d[:linetype] == :bar + # # fn = Winston.XXX + + end + + + # marker + if d[:marker] != :none + Winston.add(plt.o, Winston.Points(d[:x], d[:y]; copy_remove(e, :kind)...)) + end + + + # optionally add a regression line + d[:reg] && d[:linetype] != :hist && addRegressionLineWinston(d) + + push!(plt.seriesargs, d) + plt +end + + +function Base.display(::WinstonPackage, plt::Plot) + Winston.display(plt.o) +end + +# ------------------------------- + +function savepng(::WinstonPackage, plt::PlottingObject, fn::String; kw...) + f = open(fn, "w") + writemime(f, "image/png", plt.o) + close(f) +end + + +# ------------------------------- + +function buildSubplotObject!(::WinstonPackage, subplt::Subplot) + # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example +end + + +function Base.display(::WinstonPackage, subplt::Subplot) + # TODO: display/show the Subplot object +end diff --git a/src/utils.jl b/src/utils.jl index ce10dae8..8ec34da2 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -105,6 +105,19 @@ function sticksHack(; kw...) end + + +function regressionXY(x, y) + # regress + β, α = [x ones(length(x))] \ y + + # make a line segment + regx = [minimum(x), maximum(x)] + regy = β * regx + α + regx, regy +end + + # Some conversion functions # note: I borrowed these conversion constants from Compose.jl's Measure const INCH_SCALAR = 25.4