首页 > 其他分享 >Matplotlib 中文用户指南 3.7 变换教程

Matplotlib 中文用户指南 3.7 变换教程

时间:2023-05-02 15:02:54浏览次数:51  
标签:教程 transData 变换 transform Matplotlib 3.7 matplotlib ax 坐标系


变换教程

原文:Transformations Tutorial

译者:飞龙

协议:CC BY-NC-SA 4.0

像任何图形包一样,matplotlib 建立在变换框架之上,以便在坐标系,用户数据坐标系,轴域坐标系,图形坐标系和显示坐标系之间轻易变换。 在 95 %的绘图中,你不需要考虑这一点,因为它发生在背后,但随着你接近自定义图形生成的极限,它有助于理解这些对象,以便可以重用 matplotlib 提供给你的现有变换,或者创建自己的变换(见matplotlib.transforms)。 下表总结了现有的坐标系,你应该在该坐标系中使用的变换对象,以及该系统的描述。 在『变换对象』一列中,axAxes实例,fig是一个图形实例。

坐标系

变换对象

描述

数据

ax.transData

用户数据坐标系,由xlimylim控制

轴域

ax.transAxes

轴域坐标系;(0,0)是轴域左下角,(1,1)是轴域右上角

图形

fig.transFigure

图形坐标系;(0,0)是图形左下角,(1,1)是图形右上角

显示

None

这是显示器的像素坐标系; (0,0)是显示器的左下角,(width, height)是显示器的右上角,以像素为单位。 或者,可以使用恒等变换(matplotlib.transforms.IdentityTransform())来代替None

上表中的所有变换对象都接受以其坐标系为单位的输入,并将输入变换到显示坐标系。 这就是为什么显示坐标系没有『变换对象』的原因 - 它已经以显示坐标为单位了。 变换也知道如何反转自身,从显示返回自身的坐标系。 这在处理来自用户界面的事件(通常发生在显示空间中),并且你想知道数据坐标系中鼠标点击或按键按下的位置时特别有用。

数据坐标

让我们从最常用的坐标,数据坐标系开始。 每当向轴域添加数据时,matplotlib 会更新数据对象,set_xlim()set_ylim()方法最常用于更新。 例如,在下图中,数据的范围在x轴上为从 0 到 10,在y轴上为从 -1 到 1。

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 10, 0.005)
y = np.exp(-x/2.) * np.sin(2*np.pi*x)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y)
ax.set_xlim(0, 10)
ax.set_ylim(-1, 1)

plt.show()

Matplotlib 中文用户指南 3.7 变换教程_坐标变换

你可以使用ax.transData实例将数据变换为显示坐标系,无论是单个点或是一系列点,如下所示:

In [14]: type(ax.transData)
Out[14]: <class 'matplotlib.transforms.CompositeGenericTransform'>

In [15]: ax.transData.transform((5, 0))
Out[15]: array([ 335.175,  247.   ])

In [16]: ax.transData.transform([(5, 0), (1,2)])
Out[16]:
array([[ 335.175,  247.   ],
       [ 132.435,  642.2  ]])

你可以使用inverted()方法创建一个变换,从显示坐标变换为数据坐标:

In [41]: inv = ax.transData.inverted()

In [42]: type(inv)
Out[42]: <class 'matplotlib.transforms.CompositeGenericTransform'>

In [43]: inv.transform((335.175,  247.))
Out[43]: array([ 5.,  0.])

如果你一直关注本教程,如果你的窗口大小或 dpi 设置不同,显示坐标的确切值可能会有所不同。 同样,在下面的图形中,在 ipython 会话中,由显示标记的点可能并不相同,因为文档图形大小默认值是不同的。

Matplotlib 中文用户指南 3.7 变换教程_数据_02

注意

如果在 GUI 后端中运行上述示例中的源代码,你还可能发现数据和显示标注的两个箭头不会指向完全相同的点。 这是因为显示点是在显示图形之前计算的,并且 GUI 后端可以在创建图形时稍微调整图形大小。 如果你自己调整图的大小,效果更明显。 这是你很少想要处理显示空间的一个很好的原因,但是你可以连接到'on_draw'事件来更新图上的图坐标;请参阅事件处理和选择

当你更改轴的xy的范围时,将更新数据范围,以便变换生成新的显示点。 注意,当我们只是改变ylim,只有y显示坐标改变,当我们改变xlim也同理。 我们在谈论 Bbox 时会深入。

In [54]: ax.transData.transform((5, 0))
Out[54]: array([ 335.175,  247.   ])

In [55]: ax.set_ylim(-1,2)
Out[55]: (-1, 2)

In [56]: ax.transData.transform((5, 0))
Out[56]: array([ 335.175     ,  181.13333333])

In [57]: ax.set_xlim(10,20)
Out[57]: (10, 20)

In [58]: ax.transData.transform((5, 0))
Out[58]: array([-171.675     ,  181.13333333])

轴域坐标

在数据坐标系之后,轴域可能是第二有用的坐标系。 这里,点(0,0)是轴域或子图的左下角,(0.5,0.5)是中心,(1.0,1.0)是右上角。 你还可以引用范围之外的点,因此(-0.1,1.1)位于轴的左上方。 此坐标系在将文本放置在轴中时非常有用,因为你通常需要在固定的位置(例如,轴域窗格的左上角)放置文本气泡,并且在平移或缩放时保持该位置固定。 这里是一个简单的例子,创建四个面板,并将他们标记为'A''B''C''D',你经常在期刊上看到它们。

Matplotlib 中文用户指南 3.7 变换教程_缩放_03

你也可以在轴坐标系中创建线条或者补丁,但是以我的经验,这比使用ax.transAxes放置文本更不实用。 尽管如此,这里是一个愚蠢的例子,它在数据空间中绘制了一些随机点,并且覆盖在一个半透明的圆上面,这个圆以轴域的中心为圆心,半径为轴域的四分之一。 - 如果你的轴域不保留高宽比(见set_aspect ()),它将看起来像一个椭圆。 使用平移/缩放工具移动,或手动更改数据的xlimylim,你将看到数据移动,但圆将保持固定,因为它不在数据坐标中,并且将始终保持在轴域的中心 。

Matplotlib 中文用户指南 3.7 变换教程_缩放_04

混合变换

在数据与轴域坐标混合的混合坐标空间中绘制是非常实用的,例如创建一个水平跨度,突出y数据的一些区域但横跨x轴,而无论数据限制,平移或缩放级别等。实际上这些混合线条和跨度非常有用,我们已经内置了一些函数来使它们容易绘制(参见axhline()axvline()axhspan()axvspan()),但是为了教学目的,我们使用混合变换实现这里的水平跨度。 这个技巧只适用于可分离的变换,就像你在正常的笛卡尔坐标系中看到的,但不能为不可分离的变换,如PolarTransform(极坐标变换)。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.transforms as transforms

fig = plt.figure()
ax = fig.add_subplot(111)

x = np.random.randn(1000)

ax.hist(x, 30)
ax.set_title(r'$\sigma=1 \/ \dots \/ \sigma=2$', fontsize=16)

# the x coords of this transformation are data, and the
# y coord are axes
trans = transforms.blended_transform_factory(
    ax.transData, ax.transAxes)

# highlight the 1..2 stddev region with a span.
# We want x to be in data coordinates and y to
# span from 0..1 in axes coords
rect = patches.Rectangle((1,0), width=1, height=1,
                         transform=trans, color='yellow',
                         alpha=0.5)

ax.add_patch(rect)

plt.show()

Matplotlib 中文用户指南 3.7 变换教程_数据_05

混合变换非常有用,其中x为数据坐标而y为轴域坐标,我们拥有辅助方法来返回内部使用的版本 mpl ,用于绘制ticksticklabels以及其他。方法是matplotlib.axes.Axes.get_xaxis_transform()matplotlib.axes.Axes.get_yaxis_transform()。 因此,在上面的示例中,blended_transform_factory()的调用可以替换为get_xaxis_transform

trans = ax.get_xaxis_transform()

使用偏移变换来创建阴影效果

变换的一个用法,是创建偏离另一变换的新变换,例如,放置一个对象,相对于另一对象有一些偏移。 通常,你希望物理尺寸上有一些移位,例如以点或英寸,而不是数据坐标为单位,以便移位效果在不同的缩放级别和 dpi 设置下保持不变。

偏移的一个用途是创建一个阴影效果,其中你绘制一个与第一个相同的对象,刚好在它的右边和下面,调整zorder来确保首先绘制阴影,然后绘制对象,阴影在它之上。 变换模块具有辅助变换ScaledTranslation。 它可以这样来实例化:

trans = ScaledTranslation(xt, yt, scale_trans)

其中xtyt是变换的偏移,scale_trans是变换,在应用偏移之前的变换期间缩放xtyt。 一个典型的用例是,将图形的fig.dpi_scale_trans变换用于scale_trans参数,来在实现最终的偏移之前,首先将以点为单位的xtyt缩放到显示空间。
DPI 和英寸偏移是常见的用例,我们拥有一个特殊的辅助函数,来在matplotlib.transforms.offset_copy()中创建它,它返回一个带有附加偏移的新变换。 但在下面的示例中,我们将自己创建偏移变换。 注意使用加法运算符:

offset = transforms.ScaledTranslation(dx, dy,
         fig.dpi_scale_trans)
shadow_transform = ax.transData + offset

这里显示了,可以使用加法运算符将变换链起来。 该代码表示:首先应用数据变换ax.transData,然后由dxdy点翻译数据。 在排版中,一个点是 1/72 英寸,通过以点为单位指定偏移,你的图形看起来是一样的,无论所保存的 dpi 分辨率。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.transforms as transforms

fig = plt.figure()
ax = fig.add_subplot(111)

# make a simple sine wave
x = np.arange(0., 2., 0.01)
y = np.sin(2*np.pi*x)
line, = ax.plot(x, y, lw=3, color='blue')

# shift the object over 2 points, and down 2 points
dx, dy = 2/72., -2/72.
offset = transforms.ScaledTranslation(dx, dy,
  fig.dpi_scale_trans)
shadow_transform = ax.transData + offset

# now plot the same data with our offset transform;
# use the zorder to make sure we are below the line
ax.plot(x, y, lw=3, color='gray',
  transform=shadow_transform,
  zorder=0.5*line.get_zorder())

ax.set_title('creating a shadow effect with an offset transform')
plt.show()

Matplotlib 中文用户指南 3.7 变换教程_缩放_06

变换流水线

我们在本教程中一直使用的ax.transData变换是三种不同变换的组合,它们构成从数据到显示坐标的变换流水线。 Michael Droettboom 实现了变换框架,提供了一个干净的 API,它隔离了在极坐标和对数坐标图中发生的非线性投影和尺度,以及在平移和缩放时发生的线性仿射变换。 这里有一个效率问题,因为你可以平移和放大你的轴域,它会影响仿射变换,但你可能不需要计算潜在的昂贵的非线性比例或简单的导航事件的投影。 也可以将仿射变换矩阵相乘在一起,然后在一步之中将它们应用于坐标。 这对所有可能的变换不都是有效的。

这里是在ax.transData实例在基本可分离的Axes类中的定义方式。

self.transData = self.transScale + (self.transLimits + self.transAxes)

我们已经在Axes坐标中引入了上面的transAxes实例,它将轴或子图边界框的(0,0)(1,1)角映射到显示空间,所以让我们看看这两个部分。

self.transLimits是从数据到轴域坐标的变换; 也就是说,它将你的视图xlimylim映射到轴域单位空间(然后transAxes将该单位空间用于显示空间)。 我们可以在这里看到这一点:

In [80]: ax = subplot(111)

In [81]: ax.set_xlim(0, 10)
Out[81]: (0, 10)

In [82]: ax.set_ylim(-1,1)
Out[82]: (-1, 1)

In [84]: ax.transLimits.transform((0,-1))
Out[84]: array([ 0.,  0.])

In [85]: ax.transLimits.transform((10,-1))
Out[85]: array([ 1.,  0.])

In [86]: ax.transLimits.transform((10,1))
Out[86]: array([ 1.,  1.])

In [87]: ax.transLimits.transform((5,0))
Out[87]: array([ 0.5,  0.5])

而且我们可以使用相同的反转变换,从轴域单位坐标变换回数据坐标。

In [90]: inv.transform((0.25, 0.25))
Out[90]: array([ 2.5, -0.5])

最后一个是self.transScale属性,它负责数据的可选非线性缩放,例如对数轴域。 当Axes初始化时,这只是设置为恒等变换,因为基本的 matplotlib 轴域具有线性缩放,但是当你调用对数缩放函数如semilogx()或使用set_xscale显式设置为对数时,ax.transScale属性为处理非线性投影而设置。 缩放变换是相应xaxisyaxisAxis实例的属性。 例如,当调用ax.set_xscale('log')时,xaxis会将其缩放更新为matplotlib.scale.LogScale实例。

对于不可分离的轴域,PolarAxes,还有一个要考虑的部分,投影变换。 matplotlib.projections.polar.PolarAxestransData类似于典型的可分离 matplotlib 轴域,带有一个额外的部分,transProjection

self.transData = self.transScale + self.transProjection + \
    (self.transProjectionAffine + self.transAxes)

transProjection将来自空间的投影,例如,地图数据的纬度和经度,或极坐标数据的半径和极角,处理为可分离的笛卡尔坐标系。 在matplotlib.projections包中有几个投影示例,深入了解的最好方法是打开这些包的源代码,看看如何自己制作它,因为 matplotlib 支持可扩展的轴域和投影。 Michael Droettboom 提供了一个创建一个锤投影轴域的很好的教程示例;请参阅 api 示例代码:custom_projection_example.py


标签:教程,transData,变换,transform,Matplotlib,3.7,matplotlib,ax,坐标系
From: https://blog.51cto.com/wizardforcel/6239965

相关文章

  • 安卓逆向系列教程(二)APK 和 DEX
    安卓逆向系列教程(二)APK和DEX作者:飞龙APKAPK是Android软件包的分发格式,它本身是个Zip压缩包。APK根目录下可能出现的目录和文件有:名称用途META-INF存放元数据AndroidManifest.xml编译后的全局配置文件assets存放资源文件,不会编译classes.dex编译并打包后的源代码lib存放二进......
  • Theano 中文文档 0.9 - 7. 教程
    7.教程译者:Python文档协作翻译小组,原文:Tutorial。本文以CCBY-NC-SA4.0协议发布,转载请保留作者署名和文章出处。Python文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。交流群:467338606。让我们开始一个交互式会话(例如使用python或ipython)并导入Theano。>>>......
  • Python安装教程
    首先在浏览器上搜索网址www.python.org或者搜索python官网点进去。(1)(2)(3)有不同版本的安装包,根据自己的需求下载(4)(5)(6)(7)(8)这里可以自定义安装目录,建议不是c盘都可以(9)(10)(11)之后我们在命令行里看一下安装的python,在命令行里输入python或者是pyt......
  • Django教程
    1.前言复习该课程的时候已经2023年初了,2021年底发布了4.0,由于是复习,所以这里还是使用django3.X版本来进行练习。下面看一下django的版本演变过程。Django是基于Python的Web框架,依赖Python环境,所以需要提前安装好Python解释器。建议安装长期支持 LTS 版......
  • CentOS 7的下载安装配置教程
    CentOS7的下载安装配置教程  CentOS主流版本有7和8,我们这里选择CentOS7进行安装,因为现在8已经不更新了,CentOS8是一个介于实验性版本和稳定商业版本之间的产物,是最后一个版本,一般情况下,我们更追求稳定性,所以我们选择CentOS7。相关下载:  CentOS7镜像:http://mirrors.......
  • 一键部署VSCode_c环境脚本使用教程
       ......
  • Java教程:Springboot项目如何使用Test单元测试
    今天早上来公司领导突然分配了任务,就是简单的测试一下实体的添加修改功能,要使用到Juntil单元测试,目前使用springboot项目,jpa,maven管理,回忆起曾经用到过@Test注解,于是开始唰唰唰的写起了测试咧,然鹅,一顿报错,依赖无法注入,空指针,乱七八糟的一大通,无奈开始借助百度,终于实现了单元测试,......
  • 绘图库Matplotlib的一些使用总结
      Matplotlib是Python语言的绘图库,可视化一些实验输出用起来很方便。简单总结下使用时的一些要点。1、线条(1)线条颜色,可以用关键字参数color(或c)来设置可以用颜色全名或缩写,如‘green’,‘g’16进制,如0000FF(r,g,b)或(r,g,b,a)方式,其中r,g,b,a的取值在[0,1]之间......
  • 【wireshark 抓包】入门教程
    之前对wireshark一直一无所知,除了知道这个工具是拿来抓包,这个信息之后,其它全然不懂,比如:(1)为什么要抓包(它的使用场景)(2)怎样抓包(3)抓到的报文怎样分析(4)抓包后能干嘛?(5)都说报文可以被篡改,那这个可以篡改报文吗?以上的问题,我一个都答不上。我是写不出相关的文章了,这篇文章写得......
  • 【pytorch】土堆pytorch教程学习(三)TensorBoard的使用
    TensorBoard是TensorFlow的可视化工具包,提供机器学习实验所需的可视化功能和工具:跟踪和可视化损失及准确率等指标可视化模型图(操作和层)查看权重、偏差或其他张量随时间变化的直方图将嵌入投射到较低的维度空间显示图片、文字和音频数据剖析TensorFlow程序安装Tenso......