Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recipes #42

Closed
tbreloff opened this issue Oct 9, 2015 · 11 comments
Closed

Recipes #42

tbreloff opened this issue Oct 9, 2015 · 11 comments

Comments

@tbreloff
Copy link
Member

tbreloff commented Oct 9, 2015

I added the abstract type PlotRecipe, which will hopefully give a straightforward framework to create complex plots, and also give package authors nice ways to visualize parts of their packages.

An example, which could be the basis of an overlay of PCA results, among other things:

tmp

and the recipe is defined like:

type EllipseRecipe <: PlotRecipe
    w::Float64
    h::Float64
    x::Float64
    y::Float64
    θ::Float64
end
EllipseRecipe(w,h,x,y) = EllipseRecipe(w,h,x,y,0)

# return x,y coords of a rotated ellipse
function rotatedEllipse(w, h, x, y, θ, rotθ)
    # # coord before rotation
    xpre = w * cos(θ)
    ypre = h * sin(θ)

    # rotate and translate
    r = rotate(xpre, ypre, rotθ)
    x + r[1], y + r[2]
end

# implement this, and return whatever should be passed in as x/y for the plot command
function getRecipeXY(ep::EllipseRecipe)
    x, y = unzip([rotatedEllipse(ep.w, ep.h, ep.x, ep.y, u, ep.θ) for u in linspace(0,2π,100)])
    top = rotate(0, ep.h, ep.θ)
    right = rotate(ep.w, 0, ep.θ)
    linex = Float64[top[1], 0, right[1]] + ep.x
    liney = Float64[top[2], 0, right[2]] + ep.y
    Any[x, linex], Any[y, liney]
end

# implement this, and return a Dict or list of pairs that will be splatted as keyword args
function getRecipeArgs(ep::EllipseRecipe)
    [(:line, (3, [:dot :solid], [:red :blue], :path))]
end

If anyone has ideas for cool recipes that should be included, please comment. I'm thinking that it might make sense to have a separate repo PlotRecipes.jl which compiles a library of them...

@tbreloff
Copy link
Member Author

tbreloff commented Oct 9, 2015

Here's another good one that should probably be a recipe:

tmp

@joshday
Copy link
Contributor

joshday commented Oct 9, 2015

👍 This is great. Colors based on correlations are a nice touch! Could Plots just have this as a function scatterplotmatrix(x)?

@tbreloff
Copy link
Member Author

tbreloff commented Oct 9, 2015

Yeah that's probably reasonable too... although it would be really cool to implement it as a recipe attached to the OnlineStats.CovarianceMatrix. We could do things like add an update! function to the recipe which could add data points to the scatters and adjust the colors on the fly as new data is added to the model. That's harder if it's just sitting as a standalone (static) method within Plots. Just brainstorming here...

@joshday
Copy link
Contributor

joshday commented Oct 9, 2015

I like the updating idea. Maybe OnlineStats could have an update_plot! function similar to update_get!?

@tbreloff
Copy link
Member Author

tbreloff commented Oct 9, 2015

I tightened up the layout and removed the inner tick labels... much nicer I think:

tmp

@tbreloff
Copy link
Member Author

tbreloff commented Oct 9, 2015

This works on dev now:

using Plots, OnlineStats
gadfly()
default(size=(800,800),leg=false)

n = 1000
x = randn(n)
y = 2randn(n) + 0.5x
z = 0.2randn(n) + 0.5x - 0.1y
v = -x

M = [x y z v]
C = cor(CovarianceMatrix(M))

corrplot(M, C, colors=[colorant"red", colorant"black", colorant"green"])

@Evizero
Copy link
Member

Evizero commented Oct 12, 2015

This is really cool! If you allow me a remark then it would be to reduce the overplotting a bit. The circles seem to be suboptimal for this type of plot.

@tbreloff
Copy link
Member Author

See: JuliaML/MLPlots.jl#2

@tbreloff
Copy link
Member Author

See: JuliaML/MLPlots.jl#5

I'm experimenting with a method Plots._apply_recipe which would get called within plot! and subplot!, and allow for implementing arbitrary recipes which can be called like:

plot(mycustomtype, otherargs...; kwargs...)

This may make PlotRecipes obsolete...

@Evizero
Copy link
Member

Evizero commented Nov 24, 2015

The purpose of recipes always appeared to me to be reusable small building blocks for things that you don't usually plot on their own. The ellipse seems like a good example. One rarely wants to plot just an ellipse, but there may be reasons (such as PCA) to include one in the plot

@tbreloff
Copy link
Member Author

I agree... had the same thought after I posted. However, it probably makes more sense to bypass the PlotRecipe type and just create a new standalone type:

type EllipseRecipe
  ...
end

function Plots._apply_recipe(d::Dict, ellipse::EllipseRecipe; kw...)
  # update d
  # return (x,y)
end

I could keep PlotRecipe around just for informational purposes, but no real dispatch use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants