Как получить пиксельные координаты для matplotlib-генерируемого scatterplot?

Я использую Matplotlib для создания PNG-файлов диаграмм рассеяния. Теперь, для каждого scatterplot, в дополнение к файлу PNG, я бы и как генерировать список пиксельных координат различных точек в диаграмме рассеяния.

код, который я использую для создания PNG-файлов для диаграмм рассеяния, в основном выглядит так:

from matplotlib.figure import Figure
from matplotlib.pyplot import setp
from matplotlib.backends.backend_agg import FigureCanvasAgg

...

fig = Figure(figsize=(3, 3), dpi=100)
ax = fig.gca()
for (x, y), m, c in zip(points, markers, colors):
    ax.scatter(x, y, marker=m, c=c, s=SIZE, vmin=VMIN, vmax=VMAX)

# several assorted tweaks like ax.spines['top'].set_color('none'), etc.

setp(fig, 'facecolor', 'none')

# FigureCanvasAgg(fig).print_png(FILEPATH)

...(где переменные в верхнем регистре обозначают устанавливаемые параметры).

как я могу также создать список (px, py) пары координат пикселей в результирующем PNG, соответствующие точкам в points?

[EDIT: удалены некоторые глупости о imshow.]

[EDIT:

хорошо, вот что я, наконец, придумал, основываясь на предложениях Джо Кингтона.

# continued from above...

cnvs = FigureCanvasAgg(fig)
fig.set_canvas(cnvs)
_, ht = cnvs.get_width_height()
pcoords = [(int(round(t[0])), int(round(ht - t[1]))) for t in
           ax.transData.transform(points)]
fig.savefig(FILEPATH, dpi=fig.dpi)

результирующие пиксельные координаты (в pcoords) довольно близки к правильным значениям. На самом деле, y coords совершенно правы. Координаты x-1 или 2 пикселя, что достаточно хорошо для моего цели.

]

2 ответов


сделать это довольно просто, но чтобы понять, что происходит, вам нужно будет немного прочитать о преобразованиях matplotlib. The преобразований учебник - это хорошее место для начала.

во всяком случае, вот пример:

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
points, = ax.plot(range(10), 'ro')
ax.axis([-1, 10, -1, 10])

# Get the x and y data and transform it into pixel coordinates
x, y = points.get_data()
xy_pixels = ax.transData.transform(np.vstack([x,y]).T)
xpix, ypix = xy_pixels.T

# In matplotlib, 0,0 is the lower left corner, whereas it's usually the upper 
# right for most image software, so we'll flip the y-coords...
width, height = fig.canvas.get_width_height()
ypix = height - ypix

print 'Coordinates of the points in pixel coordinates...'
for xp, yp in zip(xpix, ypix):
    print '{x:0.2f}\t{y:0.2f}'.format(x=xp, y=yp)

# We have to be sure to save the figure with it's current DPI
# (savfig overrides the DPI of the figure, by default)
fig.savefig('test.png', dpi=fig.dpi)

это дает:

Coordinates of the points in pixel coordinates...
125.09  397.09
170.18  362.18
215.27  327.27
260.36  292.36
305.45  257.45
350.55  222.55
395.64  187.64
440.73  152.73
485.82  117.82
530.91  82.91

enter image description here


попробуйте поле аннотации:http://matplotlib.org/examples/pylab_examples/demo_annotation_box.html

import matplotlib.pyplot as plt
from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, \
     AnnotationBbox

for (x, y), m, c in zip(points, markers, colors):
    ax.scatter(x, y, marker=m, c=c, s=SIZE, vmin=VMIN, vmax=VMAX)

    for px, py in zip(x,y):
        offsetbox = TextArea( " %s, %s" (px, py ) , minimumdescent=False)
        ab = AnnotationBbox(offsetbox,(px, py ),
                        xybox=(-20, 40),
                        xycoords='data',
                        boxcoords="offset points",
                        arrowprops=dict(arrowstyle="->"))
        ax.add_artist(ab)

У меня нет matplotlib, установленного на моем текущем компьютере, поэтому мой код может не работать.