Create a Label, bbox or axes.text border flush with Graph spikes in python matplotlib

for a particular manuscript, I need to place my Earl mark exactly in the upper right or left corner. The label requires a border with the same thickness as the spikes of the graph. I am currently doing it like this:

import matplotlib.pyplot as plt
import numpy as np
my_dpi=96
xposr_box=0.975 
ypos_box=0.94
nrows=3
Mytext="label"
GLOBAL_LINEWIDTH=2
fig, axes = plt.subplots(nrows=nrows, sharex=True, sharey=True, figsize=
               (380/my_dpi, 400/my_dpi), dpi=my_dpi)
fig.subplots_adjust(hspace=0.0001)
colors = ('k', 'r', 'b')
for ax, color in zip(axes, colors):
    data = np.random.random(1) * np.random.random(10)
    ax.plot(data, marker='o', linestyle='none', color=color)

for ax in ['top','bottom','left','right']:
    for idata in range(0,nrows):
        axes[idata].spines[ax].set_linewidth(GLOBAL_LINEWIDTH)


axes[0].text(xposr_box, ypos_box , Mytext, color='black',fontsize=8,
             horizontalalignment='right',verticalalignment='top', transform=axes[0].transAxes,
             bbox=dict(facecolor='white', edgecolor='black',linewidth=GLOBAL_LINEWIDTH)) 

plt.savefig("Label_test.png",format='png', dpi=600,transparent=True)

Image1

So, I control the position of the window with the parameters:

xposr_box=0.975 
ypos_box=0.94

If I change the width of my plot, the position of my box also changes, but it should always have an upper and right (or left) spine directly above the vertices of the graphs:

import matplotlib.pyplot as plt
import numpy as np
my_dpi=96
xposr_box=0.975 
ypos_box=0.94
nrows=3
Mytext="label"
GLOBAL_LINEWIDTH=2
fig, axes = plt.subplots(nrows=nrows, sharex=True, sharey=True, figsize=
               (500/my_dpi, 400/my_dpi), dpi=my_dpi)
fig.subplots_adjust(hspace=0.0001)
colors = ('k', 'r', 'b')
for ax, color in zip(axes, colors):
    data = np.random.random(1) * np.random.random(10)
    ax.plot(data, marker='o', linestyle='none', color=color)

for ax in ['top','bottom','left','right']:
    for idata in range(0,nrows):
        axes[idata].spines[ax].set_linewidth(GLOBAL_LINEWIDTH)


axes[0].text(xposr_box, ypos_box , Mytext, color='black',fontsize=8,
             horizontalalignment='right',verticalalignment='top',transform=axes[0].transAxes,
             bbox=dict(facecolor='white', edgecolor='black',linewidth=GLOBAL_LINEWIDTH)) 

plt.savefig("Label_test.png",format='png', dpi=600,transparent=True)

Image2

It should also be if the image is narrower, not wider, as in this example. I would like to avoid this manually. Is there a way to always position it where it should? Regardless of the width and height of the plot and the number of stacked graphs?

+4
2

, text , . , (1,1)-borderpadding, , (1,1) .

, matplotlib.offsetbox.AnchoredText. , , , , . loc="upper right". .

from matplotlib.offsetbox import AnchoredText
txt = AnchoredText("text", loc="upper right", pad=0.4, borderpad=0, )
ax.add_artist(txt)

:

import matplotlib.pyplot as plt
from matplotlib.offsetbox import AnchoredText
import numpy as np

my_dpi=96
nrows=3
Mytext="label"
plt.rcParams["axes.linewidth"] = 2
plt.rcParams["patch.linewidth"] = 2

fig, axes = plt.subplots(nrows=nrows, sharex=True, sharey=True, figsize=
               (500./my_dpi, 400./my_dpi), dpi=my_dpi)
fig.subplots_adjust(hspace=0.0001)
colors = ('k', 'r', 'b')
for ax, color in zip(axes, colors):
    data = np.random.random(1) * np.random.random(10)
    ax.plot(data, marker='o', linestyle='none', color=color)

txt = AnchoredText(Mytext, loc="upper right", 
                   pad=0.4, borderpad=0, prop={"fontsize":8})
axes[0].add_artist(txt)

plt.show()

enter image description here

+2

Annotations (x y 0 1) xycoords = 'axes fraction. , bbox, bbox .

ax.text a ScaledTransformation, , , Axes . pad bbox, , bbox figure points (1 - 72 ), . , :

from matplotlib import pyplot as plt
import numpy as np
import matplotlib.transforms as transforms

GLOBAL_LINEWIDTH=2
pad = 10

fig,ax = plt.subplots()
x = np.linspace(0,1,20)

ax.plot(x,x**2, 'ro')

offset_bl = transforms.ScaledTranslation(
    pad/72, pad/72, fig.dpi_scale_trans,
)
offset_br = transforms.ScaledTranslation(
    -pad/72, pad/72, fig.dpi_scale_trans,
)
offset_tl = transforms.ScaledTranslation(
    pad/72, -pad/72, fig.dpi_scale_trans,
)
offset_tr = transforms.ScaledTranslation(
    -pad/72, -pad/72, fig.dpi_scale_trans,
)

for pos in ['top','bottom','left','right']:
    ax.spines[pos].set_linewidth(GLOBAL_LINEWIDTH)

ax.text(
    0,0, 'bottom left', 
    fontsize = 16, fontweight='bold', va='bottom', ha='left',
    bbox=dict(
        facecolor = 'white', edgecolor='black', lw = GLOBAL_LINEWIDTH,
        pad = pad
    ),
    transform=ax.transAxes + offset_bl,
)    

ax.text(
    1,0, 'bottom right', 
    fontsize = 16, fontweight='bold', va='bottom', ha='right',
    bbox=dict(
        facecolor = 'white', edgecolor='black', lw = GLOBAL_LINEWIDTH,
        pad = pad
    ),
    transform=ax.transAxes + offset_br,
)    

ax.text(
    0,1, 'top left', 
    fontsize = 16, fontweight='bold', va='top', ha='left',
    bbox=dict(
        facecolor = 'white', edgecolor='black', lw = GLOBAL_LINEWIDTH,
        pad = pad
    ),
    transform=ax.transAxes + offset_tl,
)    

ax.text(
    1,1, 'top right', 
    fontsize = 16, fontweight='bold', va='top', ha='right',
    bbox=dict(
        facecolor = 'white', edgecolor='black', lw = GLOBAL_LINEWIDTH,
        pad = pad
    ),
    transform=ax.transAxes + offset_tr,
)    

plt.show()

:

result of above code

+1

Source: https://habr.com/ru/post/1693314/


All Articles