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
|
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)
|
for (i,guide) in enumerate(gplt.guides)
|
||||||
if isa(guide, t)
|
if isa(guide, t)
|
||||||
gplt.guides[i] = t(s)
|
gplt.guides[i] = t(args...; kw...)
|
||||||
# guide.label = s
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function updateGadflyGuides(gplt, d::Dict)
|
function updateGadflyGuides(gplt, d::Dict)
|
||||||
haskey(d, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, d[:title])
|
haskey(d, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, d[:title])
|
||||||
haskey(d, :xlabel) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, d[:xlabel])
|
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
|
function subplotlayout(rowcounts::AVec{Int})
|
||||||
SubplotLayout(rowcounts::AbstractVector{Int}) = SubplotLayout(sum(rowcounts), rowcounts)
|
# 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
|
# figure out how many rows/columns we need
|
||||||
if nr == -1
|
if nr == -1
|
||||||
@ -18,6 +24,11 @@ function SubplotLayout(numplts::Int, nr::Int, nc::Int)
|
|||||||
nc = ceil(Int, numplts / nr)
|
nc = ceil(Int, numplts / nr)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# if it's a perfect rectangle, just create a grid
|
||||||
|
if numplts == nr * nc
|
||||||
|
return GridLayout(nr, nc)
|
||||||
|
end
|
||||||
|
|
||||||
# create the rowcounts vector
|
# create the rowcounts vector
|
||||||
i = 0
|
i = 0
|
||||||
rowcounts = Int[]
|
rowcounts = Int[]
|
||||||
@ -30,8 +41,68 @@ function SubplotLayout(numplts::Int, nr::Int, nc::Int)
|
|||||||
SubplotLayout(numplts, rowcounts)
|
SubplotLayout(numplts, rowcounts)
|
||||||
end
|
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
|
# figure out the layout
|
||||||
layoutarg = get(d, :layout, nothing)
|
layoutarg = get(d, :layout, nothing)
|
||||||
# if haskey(d, :layout)
|
|
||||||
if layoutarg != nothing
|
if layoutarg != nothing
|
||||||
layout = SubplotLayout(layoutarg)
|
layout = subplotlayout(layoutarg)
|
||||||
else
|
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)
|
error("You must specify either layout or n when creating a subplot: ", d)
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
# initialize the individual plots
|
# initialize the individual plots
|
||||||
@ -128,9 +199,10 @@ function subplot!(subplt::Subplot, args...; kw...)
|
|||||||
|
|
||||||
d = Dict(kw)
|
d = Dict(kw)
|
||||||
preprocessArgs!(d)
|
preprocessArgs!(d)
|
||||||
for k in keys(_plotDefaults)
|
# for k in keys(_plotDefaults)
|
||||||
delete!(d, k)
|
# delete!(d, k)
|
||||||
end
|
# end
|
||||||
|
dumpdict(d, "After subplot! preprocessing")
|
||||||
|
|
||||||
kwList, xmeta, ymeta = createKWargsList(subplt, args...; d...)
|
kwList, xmeta, ymeta = createKWargsList(subplt, args...; d...)
|
||||||
|
|
||||||
@ -140,6 +212,7 @@ function subplot!(subplt::Subplot, args...; kw...)
|
|||||||
subplt.n += 1
|
subplt.n += 1
|
||||||
plt = getplot(subplt) # get the Plot object where this series will be drawn
|
plt = getplot(subplt) # get the Plot object where this series will be drawn
|
||||||
di[:show] = false
|
di[:show] = false
|
||||||
|
dumpdict(di, "subplot! kwList $i")
|
||||||
plot!(plt; di...)
|
plot!(plt; di...)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -149,6 +222,19 @@ function subplot!(subplt::Subplot, args...; kw...)
|
|||||||
subplt.initialized = true
|
subplt.initialized = true
|
||||||
end
|
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
|
# set this to be current
|
||||||
current(subplt)
|
current(subplt)
|
||||||
|
|
||||||
|
|||||||
@ -18,7 +18,14 @@ type Plot{T<:PlottingPackage} <: PlottingObject{T}
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
type SubplotLayout
|
abstract SubplotLayout
|
||||||
|
|
||||||
|
immutable GridLayout <: SubplotLayout
|
||||||
|
nr::Int
|
||||||
|
nc::Int
|
||||||
|
end
|
||||||
|
|
||||||
|
immutable FlexLayout <: SubplotLayout
|
||||||
numplts::Int
|
numplts::Int
|
||||||
rowcounts::AbstractVector{Int}
|
rowcounts::AbstractVector{Int}
|
||||||
end
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user