Художник Matplotlib останется того же размера, когда увеличено, но также двигаться с панорамированием? - PullRequest
6 голосов
/ 22 марта 2012

Это очень прямое продолжение по этому вопросу .

Используя matplotlib , я хотел бы иметь возможность разместить своего рода "подсветку"бар "над диапазоном маркеров данных, которые, как я знаю, все будут находиться в прямой горизонтальной линии.

Эта полоса / прямоугольник должна быть немного выше маркеров и содержать их, что-то вроде этого для трех нижеприведенных маркеров:

enter image description here

Чтобы бытьРазумная подсвечивающая полоса должна иметь следующие две черты:

  • Если график панорамируется, полоса перемещается с маркерами (поэтому она всегда покрывает их).
  • ЕслиГрафик увеличен, высота полосы не изменяется (поэтому она всегда немного выше маркеров).

Если полезно знать, эти маркеры не имеютзначимые значения y (они все представлены при y = -1), только значимые значения x.Поэтому высота столбца не имеет смысла в координатах данных;он просто должен быть всегда достаточно высоким, чтобы поместить маркеры.

1 Ответ

6 голосов
/ 15 июня 2012

Отличный вопрос!Это была сложная задача, и для ее достижения требовалось несколько комбинаций.

Во-первых, нам нужно изобрести преобразование, которое будет возвращать координаты устройства заранее определенного значения плюс смещение на основе заданной точки.Например, если мы знаем, что хотим, чтобы столбец находился в x_pt, y_pt, то преобразование должно представлять (в псевдокоде):

def transform(x, y):
    return x_pt_in_device + x, y_pt_in_device + y

Как только мы это сделаем, мы могли бы использовать это преобразование для рисованияпрямоугольник из 20 пикселей вокруг фиксированной точки данных.Однако вы хотите нарисовать только прямоугольник с фиксированной высотой в направлении у, но в направлении х вы хотите стандартное масштабирование данных.

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

import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import matplotlib.path as mpath
import matplotlib.transforms as mtrans

import numpy as np


class FixedPointOffsetTransform(mtrans.Transform):
    """
    Always returns the same transformed point plus
    the given point in device coordinates as an offset.
    """
    def __init__(self, trans, fixed_point):
        mtrans.Transform.__init__(self)
        self.input_dims = self.output_dims = 2
        self.trans = trans
        self.fixed_point = np.array(fixed_point).reshape(1, 2)

    def transform(self, values):
        fp = self.trans.transform(self.fixed_point)
        values = np.array(values)
        if values.ndim == 1:
            return fp.flatten() + values
        else:
            return fp + values


plt.scatter([3.1, 3.2, 3.4, 5], [2, 2, 2, 6])

ax = plt.gca()
fixed_pt_trans = FixedPointOffsetTransform(ax.transData, (0, 2))

xdata_yfixed = mtrans.blended_transform_factory(ax.transData, fixed_pt_trans)


x = [3.075, 3.425] # x range of box (in data coords)
height = 20 # of box in device coords (pixels)
path = mpath.Path([[x[0], -height], [x[1], -height],
                   [x[1], height],  [x[0], height],
                   [x[0], -height]])
patch = mpatches.PathPatch(path, transform=xdata_yfixed,
                           facecolor='red', edgecolor='black',
                           alpha=0.4, zorder=0)
ax.add_patch(patch)

plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...