Matplotlib艺术家在放大时可以保持相同大小,但是还可以平移吗? [英] Matplotlib artist to stay same size when zoomed in but ALSO move with panning?

查看:31
本文介绍了Matplotlib艺术家在放大时可以保持相同大小,但是还可以平移吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是对这个问题.

使用 matplotlib ,我希望能够在一系列数据标记上放置一种突出显示的条",这些数据标记全部位于一条直线上.

Using matplotlib, I'd like to be able to place a sort of "highlighting bar" over a range of data markers that I know will all be in a straight horizontal line.

此条形图/矩形应比标记稍高并包含标记,以下三个标记的含义如下:

This bar/rectangle should be slightly taller than the markers and contain them, something like this for the three markers below:

要成为一个明智的突出显示栏,它必须具有以下两个特征:

In order to be a sensible highlighting bar, it needs to have the following two traits:

  • 如果绘图被平移,则条形会随标记移动(因此它始终覆盖它们).
  • 如果图被放大,条形的显示高度不会改变(所以它总是比标记略高).
  • If the plot is panned, the bar moves with the markers (so it always covers them).
  • If the plot is zoomed, the bar's display height doesn't change (so it always is slightly taller than the markers).

如果有帮助的话,这些标记将没有有意义的y值(它们全部绘制在y = -1处),只有有意义的x值.因此,条形的高度在数据坐标中是没有意义的.它只需要总是足够高以包含标记.

If it is helpful to know, these markers have no meaningful y values (they are plotted all at y=-1), only meaningful x values. Therefore, the height of the bar is meaningless in data coordinates; it merely needs to be always just tall enough to enclose the markers.

推荐答案

好问题!这是一个很好的挑战,需要综合考虑.

Great question! This was a good challenge and requires a combination of things to achieve.

首先,我们需要发明一种变换,该变换将返回预定义值的设备坐标以及基于给定点的偏移量.例如,如果我们知道我们希望柱线位于 x_pt, y_pt,那么变换应该表示(在伪代码中):

Firstly, we need to invent a transform which will return the device coordinates of a pre-defined value plus an offset based on the given point. For instance, if we know we want the bar to be at x_pt, y_pt, then the transform should represent (in pseudo code):

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

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

Once we have done this, we could use this transform to draw a box of 20 pixels around a fixed data point. However, you only want to draw a box of fixed pixel height in the y direction, but in the x direction you would like standard data scaling.

因此,我们需要创建一个可以独立变换 x 和 y 坐标的混合变换.整个代码可以完成您要问的事情:

Therefore, we need to create a blended transform which can transform the x and y coordinates independently. The whole code to do what you are asking:

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

这篇关于Matplotlib艺术家在放大时可以保持相同大小,但是还可以平移吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆