简体   繁体   中英

Annotate point on axes with automatic tick formatting in matplotlib?

Consider this example code, derived from Matplotlib Indicate Point on X and Y Axis :

import numpy as np
import matplotlib.pyplot as plt

class PointMarker():
    def __init__(self, ax, point, **kwargs):
        self.ax = ax
        self.point = point
        if "line" in kwargs:
            self.c = kwargs.get("line").get_color()
        else:
            self.c = kwargs.get("color", "b")
        self.ls=kwargs.get("linestyle", ':')
        self.vline, = self.ax.plot([],[],color=self.c,linestyle=self.ls)
        self.hline, = self.ax.plot([],[],color=self.c,linestyle=self.ls)
        self.draw()

    def draw(self):
        xmin = ax.get_xlim()[0]
        ymin = ax.get_ylim()[0]
        self.vline.set_data([self.point[0], self.point[0]], [ymin,self.point[1]])
        self.hline.set_data([xmin, self.point[0]], [self.point[1], self.point[1]])

class PointMarkers():
    pointmarkers = []
    def add(self,ax, point, **kwargs ):
        pm = PointMarker(ax, point, **kwargs)
        self.pointmarkers.append(pm)
    def update(self, event=None):
        for pm in self.pointmarkers:
            pm.draw()

x = np.arange(1,17)
y = np.log(x)
ax = plt.subplot(111)
line = plt.plot(x,y)

# register the markers
p = PointMarkers()
p.add(ax,[x[5],y[5]], line=line[0])
# connect event listener
cid = plt.gcf().canvas.mpl_connect("draw_event", p.update)

plt.grid(True)
plt.show()

What I would like to do, is to keep the automatic tick label formatting on the axis - and insert text labels that would annotate the point; so something like this (where I've manually added the annotating text labels):

matplotlib-annot-axes.png

Basically, if the graph is zoomed in, and the ticks/tick labels change, I would like the annotation labels to also be present (if they are still in view, of course)...

I would be OK with either placing the annotation labels below abscissa/to left of ordinate (as drawn above) - or, with replacing the automatic tick labels with the annotation labels, where they overlap (so in above example, the "6" tick label of the abscissa would be removed and replaced with "my_point_X").

How can an annotation like this be implemented?

We set it up with reference to the official references. The off-axis position was set manually. I have little experience with this task so there may be a better way to do it.

import numpy as np
import matplotlib.pyplot as plt

class PointMarker():
    def __init__(self, ax, point, **kwargs):
        self.ax = ax
        self.point = point
        if "line" in kwargs:
            self.c = kwargs.get("line").get_color()
        else:
            self.c = kwargs.get("color", "b")
        self.ls=kwargs.get("linestyle", ':')
        self.vline, = self.ax.plot([],[],color=self.c,linestyle=self.ls)
        self.hline, = self.ax.plot([],[],color=self.c,linestyle=self.ls)
        self.draw()

    def draw(self):
        xmin = ax.get_xlim()[0]
        ymin = ax.get_ylim()[0]
        self.vline.set_data([self.point[0], self.point[0]], [ymin,self.point[1]])
        self.hline.set_data([xmin, self.point[0]], [self.point[1], self.point[1]])

class PointMarkers():
    pointmarkers = []
    def add(self,ax, point, **kwargs ):
        pm = PointMarker(ax, point, **kwargs)
        self.pointmarkers.append(pm)
    def update(self, event=None):
        for pm in self.pointmarkers:
            pm.draw()

x = np.arange(1,17)
y = np.log(x)
fig = plt.figure(figsize=(4,3),dpi=144) # update
ax = fig.add_subplot(111) # update
# ax = plt.subplot(111)
line = plt.plot(x,y)

# register the markers
p = PointMarkers()
p.add(ax,[x[5],y[5]], line=line[0])
# update start
# x_points = x[5]/x.max()
# y_points = y[5]/y.max()
ax.annotate('my_point_Y', xy=(0.3, 1.75), xycoords='data', color='r', fontsize=9)
ax.annotate('my_point_X', xy=(5.0, -0.1), xycoords='data', color='r', fontsize=9)
# update end

# connect event listener
cid = plt.gcf().canvas.mpl_connect("draw_event", p.update)

plt.grid(True)
plt.show()

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM