Центрирование аннотации на шкале журнала с помощью matplotlib - PullRequest
0 голосов
/ 07 мая 2020

У меня следующая ситуация, не требующая пояснений; см. рисунок и рабочий пример, вставленные ниже.

Интересно, как центрировать текст в середине размерной линии.

import numpy as np
import matplotlib.pyplot as plt

# Dimension line
def annotation_line(ax, xmin, xmax, y, text, ytext=0, linecolor='black', linewidth=1, fontsize=12):
    ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data', arrowprops={'arrowstyle': '|-|', 'color':linecolor, 'linewidth':linewidth})
    ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data', arrowprops={'arrowstyle': '<->', 'color':linecolor, 'linewidth':linewidth})
    xcenter = xmin + (xmax - xmin) / 2
    if ytext==0:
        ytext = y + ( ax.get_ylim()[1] - ax.get_ylim()[0] ) / 20
    ax.annotate(text, xy=(xcenter, ytext), ha='center', va='bottom', fontsize=fontsize)

# Toy data
N = 8
y = np.zeros(N)
x1 = np.linspace(1, 1000, N, endpoint=True)

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x1, y, 'o')
annotation_line(ax=ax, text='TEXT 1', xmin=1, xmax=100, y=0.01, ytext=0, linewidth=1, linecolor='gray', fontsize=12)
ax.set_xscale('log')

enter image description here

1 Ответ

1 голос
/ 07 мая 2020

Простое решение - сделать так, как предлагает @ Johan C, и вычислить среднюю точку в логарифмических координатах.

Другое решение - использовать координаты стрелки, чтобы найти ее среднюю точку. Однако у этого метода есть недостатки. Во-первых, вам нужно явно нарисовать фигуру на промежуточном этапе, поскольку координаты будут действительны только во время рисования, а во-вторых, вам необходимо установить логарифмический масштаб перед рисованием аннотации. С другой стороны, код работает независимо от масштабирования осей

import numpy as np
import matplotlib.pyplot as plt

# Dimension line
def annotation_line(ax, xmin, xmax, y, text, ytext=0, linecolor='black', linewidth=1, fontsize=12):
    an = ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data', arrowprops={'arrowstyle': '|-|', 'color':linecolor, 'linewidth':linewidth})
    ax.annotate('', xy=(xmin, y), xytext=(xmax, y), xycoords='data', textcoords='data', arrowprops={'arrowstyle': '<->', 'color':linecolor, 'linewidth':linewidth})
    ax.figure.canvas.draw() # draw to get actual coordinates
    p = an.arrow_patch.get_path().transformed(ax.transAxes.inverted())
    xmin, xmax = np.min(p.vertices[:,0]),np.max(p.vertices[:,0])
    xcenter = xmin+(xmax-xmin)/2
    if ytext==0:
        ytext = y + ( ax.get_ylim()[1] - ax.get_ylim()[0] ) / 20
    ax.annotate(text, xy=(xcenter, ytext), xycoords=('axes fraction','data'), ha='center', va='bottom', fontsize=fontsize)
    return an

# Toy data
N = 8
y = np.zeros(N)
x1 = np.linspace(1, 1000, N, endpoint=True)

fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x1, y, 'o')
ax.set_xscale('log') # must do before the call to annotation_line
an = annotation_line(ax=ax, text='TEXT 1', xmin=1, xmax=100, y=0.01, ytext=0, linewidth=1, linecolor='gray', fontsize=12)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...