难点:添加一个旋转的浮动轴。
本文利用matplotlib 的仿射变换来做实际的旋转,从而创建一个旋转的浮动轴。 这里需要了解戳👇。 Matplotlib 可视化之图表坐标系统 Matplotlib 图像可视化之 imshow 函数详解
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D
from matplotlib.ticker import MultipleLocator
import mpl_toolkits.axisartist.floating_axes as floating_axes
fig = plt.figure(figsize=(8,8))
ax1 = plt.subplot(1,1,1, aspect=1, xlim=[0,10], ylim=[0,10])
假设我们想要有一个浮动的轴,其中心在数据坐标中为(5,5)
,大小在数据坐标中为(5,3)
,方向为‐30度
:
# Floating axis
center = np.array([5, 5]) # data coordinates
size = np.array([5, 3]) # data coordinates
orientation = -30 # degrees
T = size / 2 * [(-1, -1), (+1, -1), (+1, +1), (-1, +1), (-1, -1)]
# 初始T
T = rotation.transform(T) # 旋转后的T
rotation = Affine2D().rotate_deg(orientation)
P = center + T # 旋转后的T + center
在上面的代码中,我们定义了四个点来确定新轴的范围,并利用matplotlib的仿射变换来进行实际的旋转。此处定义四个点在数据坐标中描述轴的边界,并且需要将它们转换为figure规范化坐标,这是因为浮动轴需要法线化的图形坐标。
DC_to_FC = ax1.transData.transform
FC_to_NFC = fig.transFigure.inverted().transform DC_to_NFC = lambda x: FC_to_NFC(DC_to_FC(x))
另外还有个难点,浮动轴的位置需要根据非旋转的包围框来定义:
xmin, ymin = DC_to_NFC((xmin0,ymin0))
# (0.28658257801676496, 0.31004762302141226)
xmax, ymax = DC_to_NFC((xmax0,ymax0))
# (0.738417421983235, 0.6949523769785877)
T2 = np.array([[xmin, ymin], [xmin, ymax],
[xmax, ymax], [xmax, ymin],
[xmin, ymin]])
plt.plot(T2[:,0],T2[:,1],
color='red',
transform=fig.transFigure)
现在我们有了添加新轴的所有信息:
# 确定旋转配置
transform = Affine2D().rotate_deg(orientation)
# 添加浮动旋转轴
helper = floating.GridHelperCurveLinear(transform, (0, size[0], 0, size[1]))
ax2 = floating.FloatingSubplot(fig, 111, grid_helper=helper, zorder=0)
# 设置浮动旋转轴的位置
ax2.set_position((xmin, ymin, xmax-xmin, ymax-xmin))
# 添加旋转轴到画布中
fig.add_subplot(ax2)
还可以添加云朵君头像
。分别添加到两个不同的画布上。
import imageio
I = imageio.imread("../data/云朵君-01.png")
def do_plot(ax, I, transform):
im = ax.imshow(I, interpolation='none',
origin='lower',
extent=[0, 10, 0, 10], clip_on=True)
# 0.5, 4, 0.5, 2
trans_data = transform + ax.transData
im.set_transform(trans_data)
# display intended extent of the image
x1, x2, y1, y2 = im.get_extent()
ax.plot([x1, x2, x2, x1, x1], [y1, y1, y2, y2, y1], "y--",
transform=trans_data, zorder=10)
在浮动轴画布上添加图像:
do_plot(ax2, I, transform=Affine2D())
在固定轴画布上添加图像:
do_plot(ax1, I, transform=Affine2D())
[1]
Scientific Visualisation-Python & Matplotlib