简体   繁体   中英

Transformation from axis to absolute figure coordinates using display coordinates does not work in matplotlib

I need to plot point markers at the edge along the y-axes in Matplotlib. I want the location of the markers in x-direction to be constant (independent of the size of the axes) while y-direction should be in data coordinates. I've tried to create blended transformation according to Transformations tutorial but it did not work according to my expectations. Can anyone explain where I'm making a mistake? And how to fix it?

import matplotlib
print(matplotlib.__version__) # 3.3.1

import matplotlib.transforms as transforms
fig, ax = plt.subplots(figsize=(2, 3.5))
ax.set_xlim((0,2))
ax.set_ylim((0,2))
ax.plot([0,2], [0,2])
ax.grid(True)
fig.set_facecolor('lightgray')
point = [1,0]

# Ok, let's use the y-axis transform to plot in axis coordinates in the x-direction
t_yaxis = ax.get_yaxis_transform()
ax.scatter([1, 1.1], [2, 2], transform=t_yaxis, clip_on=False, label='p1')
# This works but the distance between points depends on the size of the axes. 
# We want to set it in absolute units.

# Here we create blended transformation which actually works exactly the same as the previous one.
t_own_yaxis = transforms.blended_transform_factory(ax.transAxes, ax.transData)
ax.scatter([1, 1.1], [1.5, 1.5], transform=t_own_yaxis, clip_on=False, label='p2')

# Let's try to blend physical coordinates of the figure in x-direction 
# with data coordinates in y-direction.
t_blended = transforms.blended_transform_factory(fig.dpi_scale_trans, ax.transData)
ax.scatter([1, 1.1], [1, 1], transform=t_blended, clip_on=False, label='p3')
# This works for distance between points but we want to offset the points at the edge of the axes
# asi in previous cases.

# Let's calculate the location of the edge and plot using that.
t_yaxis2blended = t_yaxis + t_blended.inverted()
p4 = t_yaxis2blended.transform([1, 0.5])
print(p4)
ax.scatter([p4[0], p4[0]+0.1], [0.5, 0.5], transform=t_blended, clip_on=False, label='p4')
# Why the left 'p4' point is not at the edge?

plt.legend()

在此处输入图片说明

[Edit] The blue, orange and green dots are where I expected them. I expected the left red dot at [2.0, 0.5].

Interestingly, if I use interactive backend %matplotlib notebook for rendering of the plots the result is as expected:

在此处输入图片说明

[Edit] The reason I need this is to annotate dendrograms like this: 在此处输入图片说明

It is possible to use axes scale and calculate the absolute distance between points from axes size:

import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
fig, ax = plt.subplots(figsize=(2, 3.5))
ax.set_xlim((0,2))
ax.set_ylim((0,2))
ax.plot([0,2], [0,2])
ax.grid(True)
fig.set_facecolor('lightgray')

t_yaxis = ax.get_yaxis_transform()
ax.scatter([1, 1.1], [2, 2], transform=t_yaxis, clip_on=False, label='p1')

bbox = ax.get_window_extent().transformed(fig.dpi_scale_trans.inverted())
shift = 0.1 / bbox.width
ax.scatter([1, 1 + shift], [0, 0], transform=t_yaxis, clip_on=False, label='p5')

plt.legend()

在此处输入图片说明

If you want to offset something, you can use a ScaledTransform :

import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
fig, ax = plt.subplots(figsize=(2, 3.5))
ax.set_xlim((0,2))
ax.set_ylim((0,2))
ax.plot([0,2], [0,2])

t_yaxis = ax.get_yaxis_transform()
ax.scatter([1], [2], transform=t_yaxis, clip_on=False, label='p1')

# offset -0.25 inch horizontally
trans = t_yaxis + transforms.ScaledTranslation(-0.25, 0, fig.dpi_scale_trans)
ax.scatter([1], [2], transform=trans, clip_on=False, label='p1')

plt.show()

在此处输入图片说明

This will make the second (orange) point always offset from the blue by -0.25 inches, regardless of window resizing (note the figure above has been resized manually)

More details at https://matplotlib.org/tutorials/advanced/transforms_tutorial.html#plotting-in-physical-coordinates

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