working on linked subplots
This commit is contained in:
parent
1115ff83bb
commit
f4b716b255
239
examples/facets.ipynb
Normal file
239
examples/facets.ipynb
Normal file
@ -0,0 +1,239 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"INFO: Recompiling stale cache file /home/tom/.julia/lib/v0.4/Plots.ji for module Plots.\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"[Plots.jl] Default backend: immerse\n",
|
||||
"[Plots.jl] Switched to backend: gadfly"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"using Plots\n",
|
||||
"gadfly()\n",
|
||||
"default(leg=false);\n",
|
||||
"#Plots._debugMode.on=true;"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "LoadError",
|
||||
"evalue": "LoadError: UndefVarError: GadflyPackage not defined\nwhile loading In[2], in expression starting on line 2",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"LoadError: UndefVarError: GadflyPackage not defined\nwhile loading In[2], in expression starting on line 2",
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# link the subplots together to share axes... useful for facet plots, cross-scatters, etc\n",
|
||||
"function linkPlots(subplt::Plots.Subplot{GadflyPackage})\n",
|
||||
"end"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"\n",
|
||||
"[Plots.jl] Initializing backend: gadfly"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"y = linspace(0,1,100)\n",
|
||||
"p = subplot(repmat(y,1,4),n=4);"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"ename": "ErrorException",
|
||||
"evalue": "type GridLayout has no field rowcounts",
|
||||
"output_type": "error",
|
||||
"traceback": [
|
||||
"type GridLayout has no field rowcounts",
|
||||
"",
|
||||
" in buildGadflySubplotContext at /home/tom/.julia/v0.4/Plots/src/backends/gadfly.jl:497",
|
||||
" in writemime at /home/tom/.julia/v0.4/Plots/src/backends/gadfly.jl:523",
|
||||
" in base64encode at base64.jl:160",
|
||||
" in display_dict at /home/tom/.julia/v0.4/IJulia/src/execute_request.jl:32"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"i = 1\n",
|
||||
"subplot!(ylabel=[\"y1\",\"y1\",\"y2\",\"y2\"], xlabel=[\"x1\",\"x2\",\"x1\",\"x2\"])\n",
|
||||
"# findGuideAndSet(gplt, t::DataType, s::@compat(AbstractString))\n",
|
||||
"for (i,(r,c)) in enumerate(p.layout)\n",
|
||||
"# for (r,nc) in enumerate(p.layout.rowcounts)\n",
|
||||
"# for c in 1:nc\n",
|
||||
" gplt = p.plts[i].o\n",
|
||||
" if r < Plots.nrows(p.layout)\n",
|
||||
" push!(gplt.guides, Gadfly.Guide.xticks(label=false))\n",
|
||||
" Plots.findGuideAndSet(gplt, Gadfly.Guide.xlabel, \"\")\n",
|
||||
" end\n",
|
||||
" if c > 1\n",
|
||||
" push!(gplt.guides, Gadfly.Guide.yticks(label=false))\n",
|
||||
" Plots.findGuideAndSet(gplt, Gadfly.Guide.ylabel, \"\")\n",
|
||||
" end\n",
|
||||
"end\n",
|
||||
"#p1 = p.plts[1].o\n",
|
||||
"#push!(p1.guides, Gadfly.Guide.xticks(label=false,ticks=nothing))\n",
|
||||
"p"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"p.layout.rowcounts"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"immutable FlexLayout \n",
|
||||
" numplts::Int\n",
|
||||
" rowcounts::AbstractVector{Int}\n",
|
||||
"end\n",
|
||||
"\n",
|
||||
"immutable GridLayout \n",
|
||||
" nr::Int\n",
|
||||
" nc::Int\n",
|
||||
"end"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"\n",
|
||||
"Base.length(layout::FlexLayout) = layout.numplts\n",
|
||||
"Base.start(layout::FlexLayout) = 1\n",
|
||||
"Base.done(layout::FlexLayout, state) = state > length(layout)\n",
|
||||
"function Base.next(layout::FlexLayout, state)\n",
|
||||
" r = 1\n",
|
||||
" c = 0\n",
|
||||
" for i = 1:state\n",
|
||||
" c += 1\n",
|
||||
" if c > layout.rowcounts[r]\n",
|
||||
" r += 1\n",
|
||||
" c = 1\n",
|
||||
" end\n",
|
||||
" end\n",
|
||||
" (r,c), state + 1\n",
|
||||
"end\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"Base.length(layout::GridLayout) = layout.nr * layout.nc\n",
|
||||
"Base.start(layout::GridLayout) = 1\n",
|
||||
"Base.done(layout::GridLayout, state) = state > length(layout)\n",
|
||||
"function Base.next(layout::GridLayout, state)\n",
|
||||
" r = div(state, layout.nc)\n",
|
||||
" c = mod1(state, layout.nc)\n",
|
||||
" (r,c), state + 1\n",
|
||||
"end"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"fl = FlexLayout(5, [2,1,2])\n",
|
||||
"gl = GridLayout(3,2)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": false
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for (r,c) in gl\n",
|
||||
" @show r,c\n",
|
||||
"end\n",
|
||||
"length(gl)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Julia 0.4.0-rc4",
|
||||
"language": "julia",
|
||||
"name": "julia-0.4"
|
||||
},
|
||||
"language_info": {
|
||||
"file_extension": ".jl",
|
||||
"mimetype": "application/julia",
|
||||
"name": "julia",
|
||||
"version": "0.4.0"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@ -431,15 +431,17 @@ function plot!(::GadflyPackage, plt::Plot; kw...)
|
||||
end
|
||||
|
||||
|
||||
function findGuideAndSet(gplt, t::DataType, s::@compat(AbstractString))
|
||||
|
||||
function findGuideAndSet(gplt, t::DataType, args...; kw...) #s::@compat(AbstractString))
|
||||
for (i,guide) in enumerate(gplt.guides)
|
||||
if isa(guide, t)
|
||||
gplt.guides[i] = t(s)
|
||||
# guide.label = s
|
||||
gplt.guides[i] = t(args...; kw...)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
function updateGadflyGuides(gplt, d::Dict)
|
||||
haskey(d, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, d[:title])
|
||||
haskey(d, :xlabel) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, d[:xlabel])
|
||||
|
||||
110
src/subplot.jl
110
src/subplot.jl
@ -1,10 +1,16 @@
|
||||
|
||||
function subplotlayout(sz::@compat(Tuple{Int,Int}))
|
||||
# create a GridLayout
|
||||
GridLayout(sz...)
|
||||
end
|
||||
|
||||
# create a layout directly
|
||||
SubplotLayout(rowcounts::AbstractVector{Int}) = SubplotLayout(sum(rowcounts), rowcounts)
|
||||
function subplotlayout(rowcounts::AVec{Int})
|
||||
# create a FlexLayout
|
||||
FlexLayout(sum(rowcounts), rowcounts)
|
||||
end
|
||||
|
||||
function subplotlayout(numplts::Int, nr::Int, nc::Int)
|
||||
|
||||
# create a layout given counts... nr/nc == -1 implies we figure out a good number automatically
|
||||
function SubplotLayout(numplts::Int, nr::Int, nc::Int)
|
||||
|
||||
# figure out how many rows/columns we need
|
||||
if nr == -1
|
||||
@ -18,6 +24,11 @@ function SubplotLayout(numplts::Int, nr::Int, nc::Int)
|
||||
nc = ceil(Int, numplts / nr)
|
||||
end
|
||||
|
||||
# if it's a perfect rectangle, just create a grid
|
||||
if numplts == nr * nc
|
||||
return GridLayout(nr, nc)
|
||||
end
|
||||
|
||||
# create the rowcounts vector
|
||||
i = 0
|
||||
rowcounts = Int[]
|
||||
@ -30,8 +41,68 @@ function SubplotLayout(numplts::Int, nr::Int, nc::Int)
|
||||
SubplotLayout(numplts, rowcounts)
|
||||
end
|
||||
|
||||
# # create a layout directly
|
||||
# SubplotLayout(rowcounts::AbstractVector{Int}) = SubplotLayout(sum(rowcounts), rowcounts)
|
||||
|
||||
# # create a layout given counts... nr/nc == -1 implies we figure out a good number automatically
|
||||
# function SubplotLayout(numplts::Int, nr::Int, nc::Int)
|
||||
|
||||
# # figure out how many rows/columns we need
|
||||
# if nr == -1
|
||||
# if nc == -1
|
||||
# nr = round(Int, sqrt(numplts))
|
||||
# nc = ceil(Int, numplts / nr)
|
||||
# else
|
||||
# nr = ceil(Int, numplts / nc)
|
||||
# end
|
||||
# else
|
||||
# nc = ceil(Int, numplts / nr)
|
||||
# end
|
||||
|
||||
# # create the rowcounts vector
|
||||
# i = 0
|
||||
# rowcounts = Int[]
|
||||
# for r in 1:nr
|
||||
# cnt = min(nc, numplts - i)
|
||||
# push!(rowcounts, cnt)
|
||||
# i += cnt
|
||||
# end
|
||||
|
||||
# SubplotLayout(numplts, rowcounts)
|
||||
# end
|
||||
|
||||
|
||||
Base.length(layout::FlexLayout) = layout.numplts
|
||||
Base.start(layout::FlexLayout) = 1
|
||||
Base.done(layout::FlexLayout, state) = state > length(layout)
|
||||
function Base.next(layout::FlexLayout, state)
|
||||
r = 1
|
||||
c = 0
|
||||
for i = 1:state
|
||||
c += 1
|
||||
if c > layout.rowcounts[r]
|
||||
r += 1
|
||||
c = 1
|
||||
end
|
||||
end
|
||||
(r,c), state + 1
|
||||
end
|
||||
|
||||
nrows(layout::FlexLayout) = length(layout.rowcounts)
|
||||
ncols(layout::FlexLayout, row::Int) = row < 1 ? 0 : (row > nrows(layout) ? 0 : layout.rowcounts[row])
|
||||
|
||||
Base.length(layout::GridLayout) = layout.nr * layout.nc
|
||||
Base.start(layout::GridLayout) = 1
|
||||
Base.done(layout::GridLayout, state) = state > length(layout)
|
||||
function Base.next(layout::GridLayout, state)
|
||||
r = div(state, layout.nc)
|
||||
c = mod1(state, layout.nc)
|
||||
(r,c), state + 1
|
||||
end
|
||||
|
||||
nrows(layout::GridLayout) = layout.nr
|
||||
ncols(layout::GridLayout) = layout.nc
|
||||
|
||||
Base.length(layout::SubplotLayout) = layout.numplts
|
||||
|
||||
|
||||
# ------------------------------------------------------------
|
||||
@ -70,14 +141,14 @@ function subplot(args...; kw...)
|
||||
|
||||
# figure out the layout
|
||||
layoutarg = get(d, :layout, nothing)
|
||||
# if haskey(d, :layout)
|
||||
if layoutarg != nothing
|
||||
layout = SubplotLayout(layoutarg)
|
||||
layout = subplotlayout(layoutarg)
|
||||
else
|
||||
if !haskey(d, :n) || d[:n] < 0
|
||||
n = get(d, :n, -1)
|
||||
if n < 0
|
||||
error("You must specify either layout or n when creating a subplot: ", d)
|
||||
end
|
||||
layout = SubplotLayout(d[:n], get(d, :nr, -1), get(d, :nc, -1))
|
||||
layout = subplotlayout(n, get(d, :nr, -1), get(d, :nc, -1))
|
||||
end
|
||||
|
||||
# initialize the individual plots
|
||||
@ -128,9 +199,10 @@ function subplot!(subplt::Subplot, args...; kw...)
|
||||
|
||||
d = Dict(kw)
|
||||
preprocessArgs!(d)
|
||||
for k in keys(_plotDefaults)
|
||||
delete!(d, k)
|
||||
end
|
||||
# for k in keys(_plotDefaults)
|
||||
# delete!(d, k)
|
||||
# end
|
||||
dumpdict(d, "After subplot! preprocessing")
|
||||
|
||||
kwList, xmeta, ymeta = createKWargsList(subplt, args...; d...)
|
||||
|
||||
@ -140,6 +212,7 @@ function subplot!(subplt::Subplot, args...; kw...)
|
||||
subplt.n += 1
|
||||
plt = getplot(subplt) # get the Plot object where this series will be drawn
|
||||
di[:show] = false
|
||||
dumpdict(di, "subplot! kwList $i")
|
||||
plot!(plt; di...)
|
||||
end
|
||||
|
||||
@ -149,6 +222,19 @@ function subplot!(subplt::Subplot, args...; kw...)
|
||||
subplt.initialized = true
|
||||
end
|
||||
|
||||
|
||||
# add title, axis labels, ticks, etc
|
||||
for (i,plt) in enumerate(subplt.plts)
|
||||
di = copy(d)
|
||||
for (k,v) in di
|
||||
if typeof(v) <: AVec
|
||||
di[k] = v[mod1(i, length(v))]
|
||||
end
|
||||
end
|
||||
dumpdict(di, "Updating sp $i")
|
||||
updatePlotItems(plt, di)
|
||||
end
|
||||
|
||||
# set this to be current
|
||||
current(subplt)
|
||||
|
||||
|
||||
@ -18,7 +18,14 @@ type Plot{T<:PlottingPackage} <: PlottingObject{T}
|
||||
end
|
||||
|
||||
|
||||
type SubplotLayout
|
||||
abstract SubplotLayout
|
||||
|
||||
immutable GridLayout <: SubplotLayout
|
||||
nr::Int
|
||||
nc::Int
|
||||
end
|
||||
|
||||
immutable FlexLayout <: SubplotLayout
|
||||
numplts::Int
|
||||
rowcounts::AbstractVector{Int}
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user