使用子图放大时间序列或如何在轴边界外绘制线条 [英] Use subplots to zoom into timeseries or how I can draw lines outside of axis borders

查看:74
本文介绍了使用子图放大时间序列或如何在轴边界外绘制线条的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用 matplotlib 生成这样的图

I would like to generate a plot like this with matplotlib

时间尺度 http://www.imagenetz.de/img.php?file = 37d8879009.jpg& pid =

当前,我只用matplotlib进行3个子图绘制,并在inkscape中添加红线.我发现我可以用 Rectangle 创建虚线矩形.

Currently I just do the 3 subplots with matplotlib and add the red lines in inkscape. I found out that I can create the dashed rectangles with Rectangle.

ax.add_patch(Rectangle((25, -1.4), 3, 1.3, edgecolor='red',
                       fill=False, linestyle='dashed'))

我还没有找到任何东西来绘制连接情节的线.有没有可以跨轴边界绘制的函数?

I haven't found anything yet to draw the lines connecting the plots. Is there a function that can draw across axis borders?

推荐答案

简短答案

我们可以利用plt.annotate()在图形坐标中绘制超出轴边界的线.

We can exploit plt.annotate() to draw lines outside axis borders in figure coordinates.

长答案

首先定义一个辅助函数:

First define a helper function:

from matplotlib.patches import Rectangle

def zoomingBox(ax1, roi, ax2, color='red', linewidth=2, roiKwargs={}, arrowKwargs={}):
    '''
    **Notes (for reasons unknown to me)**
    1. Sometimes the zorder of the axes need to be adjusted manually...
    2. The figure fraction is accurate only with qt backend but not inline...
    '''
    roiKwargs = dict([('fill',False), ('linestyle','dashed'), ('color',color), ('linewidth',linewidth)] + roiKwargs.items())
    ax1.add_patch(Rectangle([roi[0],roi[2]], roi[1]-roi[0], roi[3]-roi[2], **roiKwargs))
    arrowKwargs = dict([('arrowstyle','-'), ('color',color), ('linewidth',linewidth)] + arrowKwargs.items())
    srcCorners = [[roi[0],roi[2]], [roi[0],roi[3]], [roi[1],roi[2]], [roi[1],roi[3]]]
    dstCorners = ax2.get_position().corners()
    srcBB = ax1.get_position()
    dstBB = ax2.get_position()
    if (dstBB.min[0]>srcBB.max[0] and dstBB.max[1]<srcBB.min[1]) or (dstBB.max[0]<srcBB.min[0] and dstBB.min[1]>srcBB.max[1]):
        src = [0, 3]; dst = [0, 3]
    elif (dstBB.max[0]<srcBB.min[0] and dstBB.max[1]<srcBB.min[1]) or (dstBB.min[0]>srcBB.max[0] and dstBB.min[1]>srcBB.max[1]):
        src = [1, 2]; dst = [1, 2]
    elif dstBB.max[1] < srcBB.min[1]:
        src = [0, 2]; dst = [1, 3]
    elif dstBB.min[1] > srcBB.max[1]:
        src = [1, 3]; dst = [0, 2]
    elif dstBB.max[0] < srcBB.min[0]:
        src = [0, 1]; dst = [2, 3]
    elif dstBB.min[0] > srcBB.max[0]:
        src = [2, 3]; dst = [0, 1]
    for k in range(2):
        ax1.annotate('', xy=dstCorners[dst[k]], xytext=srcCorners[src[k]], xycoords='figure fraction', textcoords='data', arrowprops=arrowKwargs)

然后我们可以这样做:

import matplotlib.pyplot as plt

axs = plt.subplots(2, 2)[1]
axs[1,1].plot(rand(100))
zoomingBox(axs[1,1], [40,60,0.1,0.9], axs[0,0])
zoomingBox(axs[1,1], [10,30,0.1,0.9], axs[1,0], color='orange')

这篇关于使用子图放大时间序列或如何在轴边界外绘制线条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆