Connector patch between subplots with animation no

2019-09-11 16:13发布

I am using an artist animation method with 5 subplots. There is one static plot on the left, with 3 smaller animated imshow plots to the right (the colorbar is the 5th). I have successfully used ConnectionPatch to connect subplots to show where the data is coming from, but only on static plots. No matter what I try, I can't seem to get the patches to show up on the animation. I've tried to include the patch in the image artist list, tried to update the figure with the artist instead of the axis (which I guess doesn't make much sense), among other things. It will be very difficult to extract a working example due to the complexity of the plot, but maybe someone has a tip.

Could setting the facecolor to 'white' with the animation savefig_kwargs be covering up the connector lines? If so, how do I change the z order of the patch/facecolor?

1条回答
太酷不给撩
2楼-- · 2019-09-11 16:20

Without a minimal working example, I can only tell you that it is possible to use a ConnectionPatch in an animation. However, as seen below, one has to recreate it for every frame.

enter image description here

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(0)
import matplotlib.gridspec as gridspec
from matplotlib.patches import ConnectionPatch
import matplotlib.animation
plt.rcParams["figure.figsize"] = np.array([6,3.6])*0.7

x = np.linspace(-3,3)
X,Y = np.meshgrid(x,x)
f = lambda x,y: (1 - x / 2. + x ** 5 + y ** 3) * np.exp(-x ** 2 - y ** 2)+1.5
Z = f(X,Y)

bins=np.linspace(Z.min(), Z.max(), 16)
cols = plt.cm.PuOr((bins[:-1]-Z.min())/(Z.max()-Z.min()))

gs = gridspec.GridSpec(2, 2, height_ratios=[34,53], width_ratios=[102,53])
fig = plt.figure()
ax=fig.add_subplot(gs[:,0])
ax2=fig.add_subplot(gs[0,1])
ax3=fig.add_subplot(gs[1,1])

ax.imshow(Z, cmap="PuOr")
rec = plt.Rectangle([-.5,-.5], width=9, height=9, edgecolor="crimson", fill=False, lw=2)
conp = ConnectionPatch(xyA=[-0.5,0.5], xyB=[9.5,4], coordsA="data", coordsB="data",
                      axesA=ax3, axesB=ax, arrowstyle="-|>", zorder=25, shrinkA=0, shrinkB=1,
                      mutation_scale=20, fc="w", ec="crimson", lw=2)
ax3.add_artist(conp)
ax.add_artist(rec)
im = ax3.imshow(Z[:9,:9], cmap="PuOr", vmin=Z.min(), vmax=Z.max())
ticks = np.array([0,4,8])
ax3.set_yticks(ticks); ax3.set_xticks(ticks)
ax2.hist(Z[:9,:9].flatten(), bins=bins)

def ins(px,py):
    global rec, conp, histpatches
    ll = [px-.5,py-.5]
    rec.set_xy(ll)
    conp.remove()
    conp = ConnectionPatch(xyA=[-0.5,0.5], xyB=[px+9.5,py+4], coordsA="data", coordsB="data",
                      axesA=ax3, axesB=ax, arrowstyle="-|>", zorder=25, shrinkA=0, shrinkB=1,
                      mutation_scale=20, fc="w", ec="crimson", lw=2)
    ax3.add_patch(conp)
    data = Z[px:px+9,py:py+9]
    im.set_data(data)
    ax3.set_xticklabels(ticks+px)
    ax3.set_yticklabels(ticks+py)
    ax2.clear()
    ax2.set_ylim(0,60)
    h, b_, patches = ax2.hist(data.flatten(), bins=bins, ec="k", fc="#f1a142")
    [pat.set_color(cols[i]) for i, pat in enumerate(patches)]

def func(p):
    px,py = p
    ins(px, py)

phi = np.linspace(0.,2*np.pi)
r = np.sin(2*phi)*20+np.pi/2
xr = (r*np.cos(phi)).astype(np.int8)
yr = (r*np.sin(phi)).astype(np.int8)

plt.subplots_adjust(top=0.93,bottom=0.11,left=0.04,right=0.96,hspace=0.26,wspace=0.15)
frames = np.c_[xr+20, yr+20]
ani = matplotlib.animation.FuncAnimation(fig, func, frames=frames, interval=300, repeat=True)

plt.show()
查看更多
登录 后发表回答