Merge pull request #1378 from apalugniok/dynamic-link-axes
Implement synchronized interactive linked axes for PyPlot and Plotly.
This commit is contained in:
commit
7cee448d68
@ -232,7 +232,7 @@ function plotly_domain(sp::Subplot, letter)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function plotly_axis(axis::Axis, sp::Subplot)
|
function plotly_axis(plt::Plot, axis::Axis, sp::Subplot)
|
||||||
letter = axis[:letter]
|
letter = axis[:letter]
|
||||||
framestyle = sp[:framestyle]
|
framestyle = sp[:framestyle]
|
||||||
ax = KW(
|
ax = KW(
|
||||||
@ -252,7 +252,13 @@ function plotly_axis(axis::Axis, sp::Subplot)
|
|||||||
|
|
||||||
if letter in (:x,:y)
|
if letter in (:x,:y)
|
||||||
ax[:domain] = plotly_domain(sp, letter)
|
ax[:domain] = plotly_domain(sp, letter)
|
||||||
ax[:anchor] = "$(letter==:x ? :y : :x)$(plotly_subplot_index(sp))"
|
if is3d(sp)
|
||||||
|
# don't link 3d axes for synchronized interactivity
|
||||||
|
x_idx = y_idx = sp[:subplot_index]
|
||||||
|
else
|
||||||
|
x_idx, y_idx = plotly_link_indicies(plt, sp)
|
||||||
|
end
|
||||||
|
ax[:anchor] = "$(letter==:x ? "y$(y_idx)" : "x$(x_idx)")"
|
||||||
end
|
end
|
||||||
|
|
||||||
ax[:tickangle] = -axis[:rotation]
|
ax[:tickangle] = -axis[:rotation]
|
||||||
@ -319,9 +325,8 @@ function plotly_layout(plt::Plot)
|
|||||||
d_out[:annotations] = KW[]
|
d_out[:annotations] = KW[]
|
||||||
|
|
||||||
for sp in plt.subplots
|
for sp in plt.subplots
|
||||||
spidx = plotly_subplot_index(sp)
|
spidx = sp[:subplot_index]
|
||||||
|
x_idx, y_idx = plotly_link_indicies(plt, sp)
|
||||||
|
|
||||||
# add an annotation for the title... positioned horizontally relative to plotarea,
|
# add an annotation for the title... positioned horizontally relative to plotarea,
|
||||||
# but vertically just below the top of the subplot bounding box
|
# but vertically just below the top of the subplot bounding box
|
||||||
if sp[:title] != ""
|
if sp[:title] != ""
|
||||||
@ -349,9 +354,9 @@ function plotly_layout(plt::Plot)
|
|||||||
azim = sp[:camera][1] - 90 #convert azimuthal to match GR behaviour
|
azim = sp[:camera][1] - 90 #convert azimuthal to match GR behaviour
|
||||||
theta = 90 - sp[:camera][2] #spherical coordinate angle from z axis
|
theta = 90 - sp[:camera][2] #spherical coordinate angle from z axis
|
||||||
d_out[:scene] = KW(
|
d_out[:scene] = KW(
|
||||||
Symbol("xaxis$spidx") => plotly_axis(sp[:xaxis], sp),
|
Symbol("xaxis$(spidx)") => plotly_axis(plt, sp[:xaxis], sp),
|
||||||
Symbol("yaxis$spidx") => plotly_axis(sp[:yaxis], sp),
|
Symbol("yaxis$(spidx)") => plotly_axis(plt, sp[:yaxis], sp),
|
||||||
Symbol("zaxis$spidx") => plotly_axis(sp[:zaxis], sp),
|
Symbol("zaxis$(spidx)") => plotly_axis(plt, sp[:zaxis], sp),
|
||||||
|
|
||||||
#2.6 multiplier set camera eye such that whole plot can be seen
|
#2.6 multiplier set camera eye such that whole plot can be seen
|
||||||
:camera => KW(
|
:camera => KW(
|
||||||
@ -363,11 +368,12 @@ function plotly_layout(plt::Plot)
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
elseif ispolar(sp)
|
elseif ispolar(sp)
|
||||||
d_out[Symbol("angularaxis$spidx")] = plotly_polaraxis(sp[:xaxis])
|
d_out[Symbol("angularaxis$(spidx)")] = plotly_polaraxis(sp[:xaxis])
|
||||||
d_out[Symbol("radialaxis$spidx")] = plotly_polaraxis(sp[:yaxis])
|
d_out[Symbol("radialaxis$(spidx)")] = plotly_polaraxis(sp[:yaxis])
|
||||||
else
|
else
|
||||||
d_out[Symbol("xaxis$spidx")] = plotly_axis(sp[:xaxis], sp)
|
d_out[Symbol("xaxis$(x_idx)")] = plotly_axis(plt, sp[:xaxis], sp)
|
||||||
d_out[Symbol("yaxis$spidx")] = plotly_axis(sp[:yaxis], sp)
|
# don't allow yaxis to be reupdated/reanchored in a linked subplot
|
||||||
|
spidx == y_idx ? d_out[Symbol("yaxis$(y_idx)")] = plotly_axis(plt, sp[:yaxis], sp) : nothing
|
||||||
end
|
end
|
||||||
|
|
||||||
# legend
|
# legend
|
||||||
@ -385,7 +391,7 @@ function plotly_layout(plt::Plot)
|
|||||||
|
|
||||||
# annotations
|
# annotations
|
||||||
for ann in sp[:annotations]
|
for ann in sp[:annotations]
|
||||||
append!(d_out[:annotations], KW[plotly_annotation_dict(locate_annotation(sp, ann...)...; xref = "x$spidx", yref = "y$spidx")])
|
append!(d_out[:annotations], KW[plotly_annotation_dict(locate_annotation(sp, ann...)...; xref = "x$(x_idx)", yref = "y$(y_idx)")])
|
||||||
end
|
end
|
||||||
# series_annotations
|
# series_annotations
|
||||||
for series in series_list(sp)
|
for series in series_list(sp)
|
||||||
@ -394,7 +400,7 @@ function plotly_layout(plt::Plot)
|
|||||||
push!(d_out[:annotations], plotly_annotation_dict(
|
push!(d_out[:annotations], plotly_annotation_dict(
|
||||||
xi,
|
xi,
|
||||||
yi,
|
yi,
|
||||||
PlotText(str,fnt); xref = "x$spidx", yref = "y$spidx")
|
PlotText(str,fnt); xref = "x$(x_idx)", yref = "y$(y_idx)")
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -455,9 +461,15 @@ const _plotly_markers = KW(
|
|||||||
:hline => "line-ew",
|
:hline => "line-ew",
|
||||||
)
|
)
|
||||||
|
|
||||||
function plotly_subplot_index(sp::Subplot)
|
# find indicies of axes to which the supblot links to
|
||||||
spidx = sp[:subplot_index]
|
function plotly_link_indicies(plt::Plot, sp::Subplot)
|
||||||
spidx == 1 ? "" : spidx
|
if plt[:link] in (:x, :y, :both)
|
||||||
|
x_idx = sp[:xaxis].sps[1][:subplot_index]
|
||||||
|
y_idx = sp[:yaxis].sps[1][:subplot_index]
|
||||||
|
else
|
||||||
|
x_idx = y_idx = sp[:subplot_index]
|
||||||
|
end
|
||||||
|
x_idx, y_idx
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -495,9 +507,9 @@ function plotly_series(plt::Plot, series::Series)
|
|||||||
d_out = KW()
|
d_out = KW()
|
||||||
|
|
||||||
# these are the axes that the series should be mapped to
|
# these are the axes that the series should be mapped to
|
||||||
spidx = plotly_subplot_index(sp)
|
x_idx, y_idx = plotly_link_indicies(plt, sp)
|
||||||
d_out[:xaxis] = "x$spidx"
|
d_out[:xaxis] = "x$(x_idx)"
|
||||||
d_out[:yaxis] = "y$spidx"
|
d_out[:yaxis] = "y$(y_idx)"
|
||||||
d_out[:showlegend] = should_add_to_legend(series)
|
d_out[:showlegend] = should_add_to_legend(series)
|
||||||
|
|
||||||
|
|
||||||
@ -692,10 +704,10 @@ function plotly_series_shapes(plt::Plot, series::Series)
|
|||||||
# x, y = series[:x], series[:y]
|
# x, y = series[:x], series[:y]
|
||||||
|
|
||||||
# these are the axes that the series should be mapped to
|
# these are the axes that the series should be mapped to
|
||||||
spidx = plotly_subplot_index(series[:subplot])
|
x_idx, y_idx = plotly_link_indicies(plt, series[:subplot])
|
||||||
base_d = KW()
|
base_d = KW()
|
||||||
base_d[:xaxis] = "x$spidx"
|
base_d[:xaxis] = "x$(x_idx)"
|
||||||
base_d[:yaxis] = "y$spidx"
|
base_d[:yaxis] = "y$(y_idx)"
|
||||||
base_d[:name] = series[:label]
|
base_d[:name] = series[:label]
|
||||||
# base_d[:legendgroup] = series[:label]
|
# base_d[:legendgroup] = series[:label]
|
||||||
|
|
||||||
|
|||||||
@ -1149,6 +1149,10 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend})
|
|||||||
# this sets the bg color inside the grid
|
# this sets the bg color inside the grid
|
||||||
ax[set_facecolor_sym](py_color(sp[:background_color_inside]))
|
ax[set_facecolor_sym](py_color(sp[:background_color_inside]))
|
||||||
|
|
||||||
|
# link axes
|
||||||
|
x_ax_link, y_ax_link = sp[:xaxis].sps[1].o, sp[:yaxis].sps[1].o
|
||||||
|
ax != x_ax_link && ax[:get_shared_x_axes]()[:join](ax, sp[:xaxis].sps[1].o)
|
||||||
|
ax != y_ax_link && ax[:get_shared_y_axes]()[:join](ax, sp[:yaxis].sps[1].o)
|
||||||
end
|
end
|
||||||
py_drawfig(fig)
|
py_drawfig(fig)
|
||||||
end
|
end
|
||||||
|
|||||||
10
src/plot.jl
10
src/plot.jl
@ -102,8 +102,13 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# create the layout and initialize the subplots
|
# create the layout
|
||||||
plt.layout, plt.subplots, plt.spmap = build_layout(layout, num_sp, copy(plts))
|
plt.layout, plt.subplots, plt.spmap = build_layout(layout, num_sp, copy(plts))
|
||||||
|
|
||||||
|
# do we need to link any axes together?
|
||||||
|
link_axes!(plt.layout, plt[:link])
|
||||||
|
|
||||||
|
# initialize the subplots
|
||||||
cmdidx = 1
|
cmdidx = 1
|
||||||
for (idx, sp) in enumerate(plt.subplots)
|
for (idx, sp) in enumerate(plt.subplots)
|
||||||
_initialize_subplot(plt, sp)
|
_initialize_subplot(plt, sp)
|
||||||
@ -127,9 +132,6 @@ function plot(plt1::Plot, plts_tail::Plot...; kw...)
|
|||||||
_update_subplot_args(plt, sp, d, idx, false)
|
_update_subplot_args(plt, sp, d, idx, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
# do we need to link any axes together?
|
|
||||||
link_axes!(plt.layout, plt[:link])
|
|
||||||
|
|
||||||
# finish up
|
# finish up
|
||||||
current(plt)
|
current(plt)
|
||||||
_do_plot_show(plt, get(d, :show, default(:show)))
|
_do_plot_show(plt, get(d, :show, default(:show)))
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user