Неправильное расположение прямоугольника в matplotlib

Я делаю сюжет с барами, и я пытаюсь найти их абсолютное местоположение (в пикселях) на графике для дальнейшей обработки позже. Мне кажется, что это должно быть понято из информации трансформации matplotlib о экземпляре осей. В частности, я использую ax.transData для перехода от координат данных (где я знаю позиции ящиков) для отображения координат. Вот какой код:

 import matplotlib.pyplot as plt x = range(10) y = range(1, 11) fig = plt.figure() ax = fig.add_subplot(111) bars = ax.bar(x, y, width=.5, label="foo") ax.monkey_rectangles = bars ax.legend() def get_useful_info(fig): for ax in fig.get_axes(): for rect in ax.monkey_rectangles: corners = rect.get_bbox().corners()[::3] pos = ax.transData.transform(corners) left = pos[0,0] width = pos[1,0] - pos[0,0] bottom = pos[0,1] height = pos[1,1] - pos[0,1] yield left, width, bottom, height fig.savefig('foo.png') for l, w, b, h in get_useful_info(fig): print l, w, b, h 

Это отображает следующее:

 80.0 24.8 48.0 38.4 129.6 24.8 48.0 76.8 179.2 24.8 48.0 115.2 228.8 24.8 48.0 153.6 278.4 24.8 48.0 192.0 328.0 24.8 48.0 230.4 377.6 24.8 48.0 268.8 427.2 24.8 48.0 307.2 476.8 24.8 48.0 345.6 526.4 24.8 48.0 384.0 

Итак, matplotlib думает, что мои ящики составляют 24,8 единицы (пиксели, которые, как я предполагаю), широкие. Это прекрасно, если только я не стал измерять ширину окна, я получаю нечто большее, чем 32 пикселя в ширину. Какое здесь расхождение?

2 Solutions collect form web for “Неправильное расположение прямоугольника в matplotlib”

Как обычно, откровение возникает при публикации вопроса … Проблема в том, что единицы не пиксели , они точки. Когда эта цифра инициализируется, она настроена с использованием точек по умолчанию на дюйм ( fig.set_dpi() и fig.get_dpi() позволяют вам изменять / запрашивать разрешение текущей фигуры). Конечно, все не так просто: при сохранении рисунка dpi изменяется в зависимости от ваших настроек rc для конкретного бэкэнд. Для меня с бэкэндом по умолчанию и выходом png это составляет 100 dpi. Однако одна вещь, которая здесь является инвариантной, – это размер фигуры fig.get_size_inches() . Итак, если я масштабирую свои результаты, похоже, похоже, что мы немного поочередно …

 def get_useful_info(fig): dpi = fig.get_dpi() pngdpi = 100 scale_x = pngdpi / dpi scale_y = pngdpi / dpi for ax in fig.get_axes(): for rect in ax.monkey_rectangles: corners = rect.get_bbox().corners()[::3] pos = ax.transData.transform(corners) left = pos[0,0] * scale_x width = (pos[1,0] - pos[0,0]) * scale_x bottom = pos[0,1] * scale_y height = (pos[1,1] - pos[0,1]) * scale_y yield left, width, bottom, height 

У меня есть ощущение, что это не полное решение. В конце концов, мы все еще работаем в точках. Я не совсем уверен, как точка преобразуется в пиксель для изображений png … Я надеюсь, что движок отображения (в моем конкретном случае, веб-браузер) отображает каждую точку в одном пикселе и не заботится о размер изображения. Я полагаю, что только некоторые эксперименты будут сортировать этот …

Поскольку вы имеете в виду веб-браузеры, я предполагаю, что вы строите карты изображений?

 import matplotlib.pyplot as plt x = range(10) y = range(1, 11) fig = plt.figure() ax = fig.add_subplot(111) bars = ax.bar(x, y, width=.5, label="foo") ax.monkey_rectangles = bars ax.legend() def fig_fraction_info(fig): for ax in fig.get_axes(): inv = fig.transFigure.inverted() # transformations are applied left to right my_trans = ax.transData + inv for rect in ax.monkey_rectangles: corners = rect.get_bbox().corners()[::3] pos = my_trans.transform(corners) left = pos[0,0] width = pos[1,0] - pos[0,0] bottom = pos[0,1] height = pos[1,1] - pos[0,1] yield left, width, bottom, height 

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

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

С другой стороны:

 dpi = 300 ... fig.set_dpi(dpi) ... fig.savefig(..., dpi=dpi) на dpi = 300 ... fig.set_dpi(dpi) ... fig.savefig(..., dpi=dpi) 
Python - лучший язык программирования в мире.