[Tourner] Utilisez matplotlib pour dessiner un curseur en forme de croix

Il est relativement simple de dessiner un curseur en croix dans matplotlib similaire au logiciel de base. Ici, nous examinons plusieurs curseurs intégrés:

1. Le curseur en croix sur la monographie

from matplotlib.widgets import Cursor
import matplotlib.pyplot as plt
import numpy as np
 
fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)
t = np.arange(0.0, 2.0, 0.01)
ax1.plot(t, np.sin(2*np.pi*t))
ax2.plot(t, np.sin(4*np.pi*t))
 
cursor = Cursor(ax1, useblit=True, color='r', lw=0.5)
plt.show()

Voir l'effet

 

2. Un curseur en forme de croix apparaît sur plusieurs sous-graphiques en même temps

from matplotlib.widgets import Cursor,MultiCursor
import matplotlib.pyplot as plt
import numpy as np
 
fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)
t = np.arange(0.0, 2.0, 0.01)
ax1.plot(t, np.sin(2*np.pi*t))
ax2.plot(t, np.sin(4*np.pi*t))
 
# cursor = Cursor(ax1, useblit=True, color='r', lw=0.5)
cursor = MultiCursor(fig.canvas, (ax1, ax2), useblit=True, 
    horizOn=True, vertOn=True, color='r', lw=0.5)
plt.show()

résultat:

3. Curseur étoile croisée simple + multiple

Ceci est très courant dans les logiciels de stock. Par exemple, dans une quinte flush, il n'y a qu'une seule ligne horizontale pour plusieurs indicateurs techniques à la même date, et chaque sous-graphique a une ligne verticale. J'ai constaté qu'il n'y avait pas de mise en œuvre de ce type dans matplotlib, donc je l’ai écrit moi-même Après avoir lu le code, jetons un œil à l’effet.

# from matplotlib.widgets import Cursor,MultiCursor
import matplotlib.pyplot as plt
import numpy as np
 
fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)
t = np.arange(0.0, 2.0, 0.01)
ax1.plot(t, np.sin(2*np.pi*t))
ax2.plot(t, np.sin(4*np.pi*t))
 
# cursor = Cursor(ax1, useblit=True, color='r', lw=0.5)
# cursor = MultiCursor(fig.canvas, (ax1, ax2), useblit=True, horizOn=True, vertOn=True, color='r', lw=0.5)
cursor = SingleMultiCursor(fig.canvas, (ax1, ax2), single=0, color='r', lw=0.5)
plt.show()

Voir l'effet

Si vous organisez les sous-images dans le code à gauche et à droite, et changez le type de single en 1, voyez l'effet

# from matplotlib.widgets import Cursor,MultiCursor
import matplotlib.pyplot as plt
import numpy as np
 
fig, (ax1, ax2) = plt.subplots(ncols=2, sharey=True)
t = np.arange(0.0, 2.0, 0.01)
ax1.plot(t, np.sin(2*np.pi*t))
ax2.plot(t, np.sin(4*np.pi*t))
 
# cursor = Cursor(ax1, useblit=True, color='r', lw=0.5)
# cursor = MultiCursor(fig.canvas, (ax1, ax2), useblit=True, horizOn=True, vertOn=True, color='r', lw=0.5)
cursor = SingleMultiCursor(fig.canvas, (ax1, ax2), single=1, color='r', lw=0.5)
plt.show()

Ci-joint le code d'implémentation de SingleMultiCursor:

class SingleMultiCursor():
    """
    一个用于多个子图(横排或者竖排)的十字星光标,可以在多个子图上同时出现
    single=0表示仅仅一个子图显示水平线,所有子图显示垂直线,用于竖排的子图
    single=1表示仅仅一个子图显示垂直线,所有子图显示水平线,用于横排的子图
    注意:为了能让光标响应事件处理,必须保持对它的引用(比如有个变量保存)
    用法::
        import matplotlib.pyplot as plt
        import numpy as np
        fig, (ax1, ax2) = plt.subplots(nrows=2, sharex=True)
        t = np.arange(0.0, 2.0, 0.01)
        ax1.plot(t, np.sin(2*np.pi*t))
        ax2.plot(t, np.sin(4*np.pi*t))
        cursor = SingleMultiCursor(fig.canvas, (ax1, ax2), single=0, color='w', lw=0.5)
        plt.show()
    """
    def __init__(self, canvas, axes, single=0, **lineprops):
        self.canvas = canvas
        self.axes = axes
        self.single = single
        if single not in [0, 1]:
            raise ValueError('Unrecognized single value: ' + str(single) + ', must be 0 or 1')
 
        xmin, xmax = axes[-1].get_xlim()
        ymin, ymax = axes[-1].get_ylim()
        xmid = 0.5 * (xmin + xmax)
        ymid = 0.5 * (ymin + ymax)
 
        self.background = None
        self.needclear = False
 
        lineprops['animated'] = True # for blt
 
        self.lines = [
            [ax.axhline(ymid, visible=False, **lineprops) for ax in axes],
            [ax.axvline(xmid, visible=False, **lineprops) for ax in axes]
        ]
 
        self.canvas.mpl_connect('motion_notify_event', self.onmove)
        self.canvas.mpl_connect('draw_event', self.clear)
 
    def clear(self, event):
        self.background = (self.canvas.copy_from_bbox(self.canvas.figure.bbox))
        for line in self.lines[0] + self.lines[1]:
            line.set_visible(False)
 
    def onmove(self, event):
        if event.inaxes is None: return
        if not self.canvas.widgetlock.available(self): return
 
        self.needclear = True
 
        for i in range(len(self.axes)):
            if event.inaxes == self.axes[i]:
                if self.single == 0:
                    for line in self.lines[1]:
                        line.set_xdata((event.xdata, event.xdata))
                        line.set_visible(True)
 
                    line = self.lines[0][i]
                    line.set_ydata((event.ydata, event.ydata))
                    line.set_visible(True)
                else:
                    for line in self.lines[0]:
                        line.set_ydata((event.ydata, event.ydata))
                        line.set_visible(True)
 
                    line = self.lines[1][i]
                    line.set_xdata((event.xdata, event.xdata))
                    line.set_visible(True)
            else:
                self.lines[self.single][i].set_visible(False)
 
        if self.background is not None:
            self.canvas.restore_region(self.background)
 
        for lines in self.lines:
            for line in lines:
                if line.get_visible():
                    line.axes.draw_artist(line)
 
        self.canvas.blit()

 

Je suppose que tu aimes

Origine blog.csdn.net/weixin_52071682/article/details/112298659
conseillé
Classement