【问题标题】:Matplotlib artist to stay same size when zoomed in but ALSO move with panning?Matplotlib 艺术家在放大时保持相同大小但也随着平移移动?
【发布时间】:2012-03-21 20:39:07
【问题描述】:

这是对this question的非常直接的跟进。

使用 ma​​tplotlib,我希望能够在一系列数据标记上放置一种“高亮条”,我知道这些标记都将位于一条水平直线上。

这个条形/矩形应该比标记稍高并包含它们,对于下面的三个标记是这样的:

为了成为一个明智的高亮条,它需要具有以下两个特征:

  • 如果绘图被平移,条形图会随着标记移动(因此它总是覆盖它们)。
  • 如果放大绘图,条形的显示高度不会改变(因此它总是比标记略高)。

如果知道有帮助,这些标记没有有意义的 y 值(它们都在 y=-1 处绘制),只有有意义的 x 值。因此,柱的高度在数据坐标中是没有意义的;它只需要总是足够高以包围标记。

【问题讨论】:

  • 我没有时间完全整理出来,但看起来它会是某种形式的混合变换。希望这会有所帮助:matplotlib.sourceforge.net/users/… 或至少让某人走上正轨。

标签: python matplotlib


【解决方案1】:

好问题!这是一个很好的挑战,需要综合考虑才能实现。

首先,我们需要发明一个转换,它将返回一个预定义值的设备坐标加上基于给定点的偏移量。例如,如果我们知道我们希望条形图位于 x_pt、y_pt,那么变换应该表示(在伪代码中):

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

完成此操作后,我们可以使用此变换在固定数据点周围绘制一个 20 像素的框。但是,您只想在 y 方向上绘制一个固定像素高度的框,但在 x 方向上您需要标准数据缩放。

因此,我们需要创建一个可以独立变换 x 和 y 坐标的混合变换。完成您所要求的全部代码:

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()

【讨论】:

  • 真的很棒,非常感谢。我积压了其他错误,只是开始实施这个——多么好的改进!我认为这种突出显示栏也是对 mpl 的一个很好的补充。伟大的工作,如果可以的话,我会给超过+1。 :D
  • 谢谢@Chelonian。我很可能忽略了一个更简单的答案,因为创建一种新型艺术家可能更容易(matplotlib.sourceforge.net/users/artists.html)。如果其他人有兴趣使用艺术家产生与我的答案完全相同的结果,我会非常渴望看到它。
猜你喜欢
  • 1970-01-01
  • 2015-08-16
  • 1970-01-01
  • 2019-12-28
  • 2012-07-10
  • 1970-01-01
  • 2014-08-19
  • 2013-05-04
  • 2017-02-19
相关资源
最近更新 更多