From 8120c340647fc0bf73925b1c2eaaee968f559bcb Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Wed, 28 Oct 2015 12:14:58 -0400 Subject: [PATCH] added smooth and opacity args for pyplot; fixes in regressionXY, replaceAliases --- src/args.jl | 2 +- src/backends/pyplot.jl | 54 +++++++++++++++++++++-------- src/backends/supported.jl | 8 ++--- src/backends/unicodeplots.jl | 67 ------------------------------------ src/backends/winston.jl | 65 ---------------------------------- src/colors.jl | 2 +- src/recipes.jl | 16 ++++----- src/utils.jl | 8 +++-- 8 files changed, 56 insertions(+), 166 deletions(-) diff --git a/src/args.jl b/src/args.jl index f0efbc70..487b7d1e 100644 --- a/src/args.jl +++ b/src/args.jl @@ -121,7 +121,7 @@ _seriesDefaults[:fillcolor] = :match _seriesDefaults[:fillopacity] = nothing # _seriesDefaults[:ribbon] = nothing # _seriesDefaults[:ribboncolor] = :match -_seriesDefaults[:nbins] = 100 # number of bins for heatmaps and hists +_seriesDefaults[:nbins] = 30 # number of bins for heatmaps and hists # _seriesDefaults[:heatmap_c] = (0.15, 0.5) # TODO: this should be replaced with a ColorGradient # _seriesDefaults[:fill] = nothing # fills in the area _seriesDefaults[:smooth] = false # regression line? diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index c7c31b89..ac6fca49 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -4,14 +4,20 @@ # ------------------------------- # convert colorant to 4-tuple RGBA -getPyPlotColor(c::Colorant) = map(f->float(f(c)), (red, green, blue, alpha)) -getPyPlotColor(scheme::ColorScheme) = getPyPlotColor(getColor(scheme)) -getPyPlotColor(c) = getPyPlotColor(convertColor(c)) +getPyPlotColor(c::Colorant, α=nothing) = map(f->float(f(convertColor(c,α))), (red, green, blue, alpha)) +getPyPlotColor(scheme::ColorScheme, α=nothing) = getPyPlotColor(convertColor(getColor(scheme), α)) +getPyPlotColor(c, α=nothing) = getPyPlotColor(convertColor(c, α)) +# getPyPlotColor(c, alpha) = getPyPlotColor(colorscheme(c, alpha)) -function getPyPlotColorMap(c::ColorGradient) - pycolors.pymember("LinearSegmentedColormap")[:from_list]("tmp", map(getPyPlotColor, getColorVector(c))) +function getPyPlotColorMap(c::ColorGradient, α=nothing) + # c = ColorGradient(c.colors, c.values, alpha=α) + # pycolors.pymember("LinearSegmentedColormap")[:from_list]("tmp", map(getPyPlotColor, getColorVector(c))) + pyvals = [(c.values[i], getPyPlotColor(c.colors[i], α)) for i in 1:length(c.colors)] + pycolors.pymember("LinearSegmentedColormap")[:from_list]("tmp", pyvals) end -getPyPlotColorMap(c) = getPyPlotColorMap(ColorGradient(:redsblues)) + +# anything else just gets a redsblue gradient +getPyPlotColorMap(c, α=nothing) = getPyPlotColorMap(ColorGradient(:redsblues), α) # get the style (solid, dashed, etc) function getPyPlotLineStyle(linetype::Symbol, linestyle::Symbol) @@ -62,7 +68,7 @@ function getPyPlotMarker(marker::@compat(AbstractString)) marker end -function getPyPlotDrawStyle(linetype::Symbol) +function getPyPlotStepStyle(linetype::Symbol) linetype == :steppost && return "steps-post" linetype == :steppre && return "steps-pre" return "default" @@ -127,6 +133,19 @@ function updateAxisColors(ax, fgcolor) end +function handleSmooth(plt::Plot{PyPlotPackage}, ax, d::Dict, smooth::Bool) + if smooth + xs, ys = regressionXY(d[:x], d[:y]) + ax[:plot](xs, ys, + # linestyle = getPyPlotLineStyle(:path, :dashdot), + color = getPyPlotColor(d[:color]), + linewidth = 2 + ) + end +end +handleSmooth(plt::Plot{PyPlotPackage}, ax, d::Dict, smooth::Real) = handleSmooth(plt, ax, d, true) + + nop() = nothing @@ -177,6 +196,9 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...) error("linetype $(lt) is unsupported in PyPlot. Choose from: $(supportedTypes(pkg))") end + color = getPyPlotColor(d[:color], d[:lineopacity]) + + if lt == :sticks d,_ = sticksHack(;d...) @@ -187,7 +209,7 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...) elseif lt in (:hline,:vline) linewidth = d[:linewidth] - linecolor = getPyPlotColor(d[:color]) + linecolor = color linestyle = getPyPlotLineStyle(lt, d[:linestyle]) for yi in d[:y] func = ax[lt == :hline ? :axhline : axvline] @@ -233,22 +255,22 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...) c = d[:markercolor] if isa(c, ColorGradient) && d[:z] != nothing extra_kwargs[:c] = convert(Vector{Float64}, d[:z]) - extra_kwargs[:cmap] = getPyPlotColorMap(c) + extra_kwargs[:cmap] = getPyPlotColorMap(c, d[:markeropacity]) else - extra_kwargs[:c] = getPyPlotColor(c) + extra_kwargs[:c] = getPyPlotColor(c, d[:markeropacity]) end else extra_kwargs[:markersize] = d[:markersize] - extra_kwargs[:markerfacecolor] = getPyPlotColor(d[:markercolor]) + extra_kwargs[:markerfacecolor] = getPyPlotColor(d[:markercolor], d[:markeropacity]) extra_kwargs[:markeredgecolor] = getPyPlotColor(plt.initargs[:foreground_color]) extra_kwargs[:markeredgewidth] = d[:linewidth] - extra_kwargs[:drawstyle] = getPyPlotDrawStyle(lt) + extra_kwargs[:drawstyle] = getPyPlotStepStyle(lt) end end # set these for all types if lt != :contour - extra_kwargs[:color] = getPyPlotColor(d[:color]) + extra_kwargs[:color] = color extra_kwargs[:linewidth] = d[:linewidth] extra_kwargs[:label] = d[:label] end @@ -263,7 +285,7 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...) surf = d[:surface]' handle = plotfunc(x, y, surf, d[:nlevels]; extra_kwargs...) if d[:fillrange] != nothing - handle = ax[:contourf](x, y, surf, d[:nlevels]; cmap = getPyPlotColorMap(d[:fillcolor])) + handle = ax[:contourf](x, y, surf, d[:nlevels]; cmap = getPyPlotColorMap(d[:fillcolor], d[:fillopacity])) end handle elseif lt in (:scatter, :heatmap, :hexbin) @@ -272,6 +294,8 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...) plotfunc(d[:x], d[:y]; extra_kwargs...)[1] end + handleSmooth(plt, ax, d, d[:smooth]) + # add the colorbar legend if plt.initargs[:legend] && haskey(extra_kwargs, :cmap) PyPlot.colorbar(d[:serieshandle]) @@ -282,7 +306,7 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...) fillrange = d[:fillrange] if fillrange != nothing && lt != :contour - fillcolor = getPyPlotColor(d[:fillcolor]) + fillcolor = getPyPlotColor(d[:fillcolor], d[:fillopacity]) if typeof(fillrange) <: @compat(Union{Real, AVec}) ax[:fill_between](d[:x], fillrange, d[:y], facecolor = fillcolor) else diff --git a/src/backends/supported.jl b/src/backends/supported.jl index 901d1913..f32eb34c 100644 --- a/src/backends/supported.jl +++ b/src/backends/supported.jl @@ -75,7 +75,6 @@ supportedScales(::ImmersePackage) = supportedScales(GadflyPackage()) supportedArgs(::PyPlotPackage) = [ :annotation, - # :args, :axis, :background_color, :color, @@ -84,8 +83,6 @@ supportedArgs(::PyPlotPackage) = [ :fillcolor, :foreground_color, :group, - # :heatmap_c, - # :kwargs, :label, :layout, :legend, @@ -100,7 +97,7 @@ supportedArgs(::PyPlotPackage) = [ :nc, :nr, # :pos, - # :smooth, + :smooth, # :ribbon, :show, :size, @@ -126,6 +123,9 @@ supportedArgs(::PyPlotPackage) = [ :grid, :surface, :nlevels, + :fillopacity, + :lineopacity, + :markeropacity, ] supportedAxes(::PyPlotPackage) = _allAxes supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour] diff --git a/src/backends/unicodeplots.jl b/src/backends/unicodeplots.jl index b21a5ba8..cdb3e9a8 100644 --- a/src/backends/unicodeplots.jl +++ b/src/backends/unicodeplots.jl @@ -1,67 +1,8 @@ # https://github.com/Evizero/UnicodePlots.jl -# immutable UnicodePlotsPackage <: PlottingPackage end - -# export unicodeplots -# unicodeplots() = backend(:unicodeplots) - # ------------------------------- -# # supportedArgs(::UnicodePlotsPackage) = setdiff(_allArgs, [:reg, :heatmap_c, :fill, :pos, :xlims, :ylims, :xticks, :yticks]) -# supportedArgs(::UnicodePlotsPackage) = [ -# # :annotation, -# # :args, -# # :axis, -# # :background_color, -# # :color, -# # :fill, -# # :foreground_color, -# :group, -# # :heatmap_c, -# # :kwargs, -# :label, -# # :layout, -# :legend, -# :linestyle, -# :linetype, -# # :linewidth, -# :markershape, -# # :markercolor, -# # :markersize, -# # :n, -# :nbins, -# # :nc, -# # :nr, -# # :pos, -# # :reg, -# # :ribbon, -# :show, -# :size, -# :title, -# :windowtitle, -# :x, -# :xlabel, -# :xlims, -# # :xticks, -# :y, -# :ylabel, -# :ylims, -# # :yrightlabel, -# # :yticks, -# # :xscale, -# # :yscale, -# # :xflip, -# # :yflip, -# # :z, -# ] -# supportedAxes(::UnicodePlotsPackage) = [:auto, :left] -# supportedTypes(::UnicodePlotsPackage) = [:none, :line, :path, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline] -# supportedStyles(::UnicodePlotsPackage) = [:auto, :solid] -# supportedMarkers(::UnicodePlotsPackage) = [:none, :auto, :ellipse] -# supportedScales(::UnicodePlotsPackage) = [:identity] - - # do all the magic here... build it all at once, since we need to know about all the series at the very beginning function rebuildUnicodePlot!(plt::Plot) @@ -205,9 +146,6 @@ end # ------------------------------- -# function savepng(::UnicodePlotsPackage, plt::PlottingObject, fn::@compat(AbstractString), args...) -# function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{UnicodePlotsPackage}) - # since this is such a hack, it's only callable using `png`... should error during normal `writemime` function png(plt::PlottingObject{UnicodePlotsPackage}, fn::@compat(AbstractString)) fn = addExtension(fn, "png") @@ -226,11 +164,6 @@ function png(plt::PlottingObject{UnicodePlotsPackage}, fn::@compat(AbstractStrin # TODO: compute size of plot to adjust these numbers (or maybe implement something good??) run(`screencapture -R50,600,700,420 $fn`) - # # some other attempts: - # run(`screencapture -w $fn`) - # using PyCall - # @pyimport pyscreenshot as pss - # END HACK (phew) return end diff --git a/src/backends/winston.jl b/src/backends/winston.jl index 2624d4f4..05e51c3a 100644 --- a/src/backends/winston.jl +++ b/src/backends/winston.jl @@ -3,10 +3,6 @@ # credit goes to https://github.com/jverzani for contributing to the first draft of this backend implementation -# immutable WinstonPackage <: PlottingPackage end - -# export winston -# winston() = backend(:winston) # --------------------------------------------------------------------------- @@ -29,63 +25,6 @@ :star5 => "asterisk" ) - -# supportedArgs(::WinstonPackage) = [ -# :annotation, -# # :args, -# # :axis, -# # :background_color, -# :color, -# :color_palette, -# :fillrange, -# :fillcolor, -# # :foreground_color, -# :group, -# # :heatmap_c, -# # :kwargs, -# :label, -# # :layout, -# :legend, -# :linestyle, -# :linetype, -# :linewidth, -# :markershape, -# :markercolor, -# :markersize, -# # :n, -# :nbins, -# # :nc, -# # :nr, -# # :pos, -# :smooth, -# # :ribbon, -# :show, -# :size, -# :title, -# :windowtitle, -# :x, -# :xlabel, -# :xlims, -# # :xticks, -# :y, -# :ylabel, -# :ylims, -# # :yrightlabel, -# # :yticks, -# :xscale, -# :yscale, -# # :xflip, -# # :yflip, -# # :z, -# ] -# supportedAxes(::WinstonPackage) = [:auto, :left] -# supportedTypes(::WinstonPackage) = [:none, :line, :path, :sticks, :scatter, :hist, :bar] -# supportedStyles(::WinstonPackage) = [:auto, :solid, :dash, :dot, :dashdot] -# supportedMarkers(::WinstonPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] -# supportedScales(::WinstonPackage) = [:identity, :log10] -# subplotSupported(::WinstonPackage) = false - - function preparePlotUpdate(plt::Plot{WinstonPackage}) Winston.ghf(plt.o) end @@ -119,10 +58,6 @@ end function plot!(::WinstonPackage, plt::Plot; kw...) d = Dict(kw) - - # # make this figure current - # fig, figidx = plt.o - # Winston.switchfig(Winston._display, figidx) window, canvas, wplt = getWinstonItems(plt) diff --git a/src/colors.jl b/src/colors.jl index e943932f..9c2fd3d5 100644 --- a/src/colors.jl +++ b/src/colors.jl @@ -109,7 +109,7 @@ convertColor(c::ColorScheme) = c function convertColor(c, α::Real) c = convertColor(c) - RGBA(c, α) + RGBA(RGB(c), α) end convertColor(cs::AVec, α::Real) = map(c -> convertColor(c, α), cs) convertColor(c, α::Void) = convertColor(c) diff --git a/src/recipes.jl b/src/recipes.jl index 3aa26a0c..5468a619 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -75,7 +75,7 @@ function corrplot{T<:Real,S<:Real}(mat::AMat{T}, corrmat::AMat{S} = cor(mat); @assert size(corrmat) == (m,m) # create a subplot grid, and a gradient from -1 to 1 - p = subplot(rand(0,m^2); n=m^2, leg=false, kw...) + p = subplot(rand(0,m^2); n=m^2, leg=false, grid=false, kw...) cgrad = ColorGradient(colors, [-1,1]) # make all the plots @@ -85,28 +85,24 @@ function corrplot{T<:Real,S<:Real}(mat::AMat{T}, corrmat::AMat{S} = cor(mat); plt = p.plts[idx] if i==j # histogram on diagonal - histogram!(plt, mat[:,i], c=:black, leg=false) + histogram!(plt, mat[:,i], c=:black) i > 1 && plot!(plt, yticks = :none) elseif i < j - # plot!(plt, mat[:,j], mat[:,i], l=:hexbin, leg=false) - # plot!(plt, [0], [0], ann=(0, 0, "Corr:\n$(corrmat[i,j])"), leg=false) + # annotate correlation value in upper triangle mi, mj = centers[i], centers[j] plot!(plt, [mj], [mi], ann = (mj, mi, text(@sprintf("Corr:\n%0.3f", corrmat[i,j]), 15)), - yticks=:none, grid=false) + yticks=:none) else - # scatter plots off-diagonal, color determined by correlation + # scatter plots in lower triangle; color determined by correlation c = RGBA(RGB(getColorZ(cgrad, corrmat[i,j])), 0.3) - scatter!(plt, mat[:,j], mat[:,i], w=0, ms=3, c=c, leg=false) + scatter!(plt, mat[:,j], mat[:,i], w=0, ms=3, c=c, smooth=true) end if labels != nothing && length(labels) >= m i == m && xlabel!(plt, string(labels[j])) j == 1 && ylabel!(plt, string(labels[i])) end - - # # replace the plt - # p.plts[idx] = plt end end diff --git a/src/utils.jl b/src/utils.jl index 7a22f290..828046cc 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -106,7 +106,7 @@ end function regressionXY(x, y) # regress - β, α = [x ones(length(x))] \ y + β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y) # make a line segment regx = [minimum(x), maximum(x)] @@ -161,9 +161,11 @@ function replaceType(vec, val) end function replaceAliases!(d::Dict, aliases::Dict) - for (k,v) in d + ks = collect(keys(d)) + # for (k,v) in d + for k in ks if haskey(aliases, k) - d[aliases[k]] = v + d[aliases[k]] = d[k] delete!(d, k) end end