Matplotlib:Figure.add_axes从x,y转换为相对坐标 [英] Matplotlib: figure.add_axes convert from x,y to relative coordinates
问题描述
我正在制作一个自组织地图,我想将其显示为六边形点阵,其中蜘蛛图表示相应单元格中的权重向量/神经元,并且能够通过以下方式创建六边形网格:
def hex_plot(ws,a=1):"""绘制具有偏移行的m(行)x n(cols)六边形网格,其中a为六边形的边长和 m 和 n 由前两个决定权重向量的维数ws"""m,n,_ =形状偏移量 = .75 * 2*aoffsetx = numpy.sqrt(3)* a奇数行 = numpy.sqrt(3)/2 * ax,y = 0,0fig,ax = plt.subplots(figsize=(7.5,7.5))ax.set_aspect('相等')ax.set_zorder(1)cs = {}对于我在范围(m)中的:对于范围(n)中的j:如果i%2!= 0则offsetr =奇数行,否则0cp =(j * offsetx + offsetr,-i * offsety)cs[(i,j)] = cphexg = RegularPolygon(cp,numVertices = 6,radius = a,facecolor ='white',edgecolor ='k')ax.add_patch(hexg)ax.text(cp [0],cp [1],"{},{} \ n {:.2f},{:. 2f}".format(i,j,cp [0],cp [1]), ha='center', va='center', size=10)xy = [cs [(i,j)]对于范围(i)中的i对于范围(n)中的jax.scatter([x for x,_ in xy],[y for _,y in xy],c ='white',alpha = 0.5)ax.set_xticks([])ax.set_yticks([])plt.show()
这给了我以下内容:
使用inset_axes
如果您确实需要轴,例如要显示网格,您可以将 inset_axes
定位在相应的位置.
将 numpy 导入为 np导入matplotlib.pyplot作为plt从 matplotlib.patches 导入 RegularPolygon从 mpl_toolkits.axes_grid1.inset_locator 导入 inset_axes从matplotlib.projections导入get_projection_classdef hex_plot(ws,a=1):"""绘制具有偏移行的m(行)x n(cols)六边形网格,其中a为六边形的边长和 m 和 n 由前两个决定权重向量 ws 的维度"""m,n,l =形状偏移量 = .75 * 2*aoffsetx = np.sqrt(3) * a奇数行 = np.sqrt(3)/2 * atheta = np.linspace(0, 2*np.pi, l+1)无花果,ax = plt.subplots(figsize =(7.5,7.5))ax.set_aspect('相等')ax.set_zorder(1)cs = {}axcs = {}对于我在范围(m)中的:对于范围(n)中的j:offsetr = 奇数行 if i % 2 != 0 else 0cp =(j * offsetx + offsetr,-i * offsety)cs[(i,j)] = cphexg = RegularPolygon(cp,numVertices=6,radius=a,facecolor='white',edgecolor='k')ax.add_patch(hexg)ax.text(cp[0], cp[1], "{},{}\n{:.2f},{:.2f}".format(i,j,cp[0],cp[1]),ha='center', va='center', size=10)axins=inset_axes(ax, width="100%", height="100%",bbox_to_anchor =(cp [0] -offsetx/2,cp [1] -offsety/2,offsetx,offsety),bbox_transform=ax.transData,borderpad=0,axis_class=get_projection_class("polar"),)axins.set_zorder(4)axcs [(i,j)] =毒素r = ws [i,j ,:]r = np.concatenate((r, [r[0]]))axins.fill(theta,r)axins.set_yticklabels([])axins.set_xticklabels([])ax.autoscale()ax.set_xticks([])ax.set_yticks([])plt.show()hex_plot(np.random.rand(5,4,6),a=1)
I am working on a self-organizing map that I want to show as a hexagonal lattice with spider charts representing the weight vector/neuron in the corresponding cells and have been able to create a hexagonal grid via the following:
def hex_plot(ws,a=1):
"""
plots a m (rows) x n (cols) hexagonal grid with offset rows where a is
the hexagon's side length and m and n are determined by the first two
dimensions of the weight vectors ws
"""
m,n,_ = ws.shape
offsety = .75 * 2*a
offsetx = numpy.sqrt(3) * a
oddrow = numpy.sqrt(3)/2 * a
x,y = 0,0
fig,ax = plt.subplots(figsize=(7.5,7.5))
ax.set_aspect('equal')
ax.set_zorder(1)
cs = {}
for i in range(m):
for j in range(n):
offsetr = oddrow if i % 2 != 0 else 0
cp = (j*offsetx+offsetr,-i*offsety)
cs[(i,j)] = cp
hexg = RegularPolygon(cp,numVertices=6,radius=a,facecolor='white',edgecolor='k')
ax.add_patch(hexg)
ax.text(cp[0], cp[1], "{},{}\n{:.2f},{:.2f}".format(i,j,cp[0],cp[1]), ha='center', va='center', size=10)
xy = [cs[(i,j)] for i in range(m) for j in range(n)]
ax.scatter([x for x,_ in xy],[y for _,y in xy],c='white',alpha=0.5)
ax.set_xticks([])
ax.set_yticks([])
plt.show()
This gives me the following:
5x4 blank hexagon grid
With that I am trying to place spider charts of the neurons 5x4 trained SOM representing each weight vector such that the spider chart at 0,0 (top left) is inside the hexagonal cell at 0,0 (top left). I tried using sub plots but the difficulty arises in the spider charts having a polar projections whereas the grids do not. My second attempt involves using "add_axes". By adding the following immediately prior to plt.show() in the code above:
w = ws[0][0] # current weight vector
a = numpy.linspace(0,2*numpy.pi,len(w),endpoint=False)
a = numpy.concatenate((a,[a[0]]))
w = numpy.concatenate((w,[w[0]]))
ax1 = fig.add_axes([0.0,0.0,0.1,0.1],polar=True,zorder=2)
ax1.set_thetagrids([])
ax1.fill(a,w,alpha=1.0)
ax1.set_yticklabels([])
ax1.set_rticks([])
I can place a spider chart in the lower left canvas: Spider chart over hex, But since the rectangle specified in add_axes is in coordinates relative to the figure, I cannot figure out to determine what coordinate 0,0 in the orginal axes (hexagon 0,0) would map to in relative coordinates. I looked at transformations but it wasn't helpful.
Has anyone ran into this and come up with a solution? Thanks
I see two options here:
Plot all shapes in a single axes
Since it does not look like there is a need for a special polar axes you could just plot the fills all in the same axes at the respective positions of the hexagons.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import RegularPolygon
def hex_plot(ws,a=1):
"""
plots a m (rows) x n (cols) hexagonal grid with offset rows where a is
the hexagon's side length and m and n are determined by the first two
dimensions of the weight vectors ws
"""
m,n,l = ws.shape
offsety = .75 * 2*a
offsetx = np.sqrt(3) * a
oddrow = np.sqrt(3)/2 * a
theta = np.linspace(0, 2*np.pi, l+1)
fig,ax = plt.subplots(figsize=(7.5,7.5))
ax.set_aspect('equal')
ax.set_zorder(1)
cs = {}
for i in range(m):
for j in range(n):
offsetr = oddrow if i % 2 != 0 else 0
cp = (j*offsetx+offsetr,-i*offsety)
cs[(i,j)] = cp
hexg = RegularPolygon(cp,numVertices=6,radius=a,
facecolor='white',edgecolor='k')
ax.add_patch(hexg)
ax.text(cp[0], cp[1], "{},{}\n{:.2f},{:.2f}".format(i,j,cp[0],cp[1]),
ha='center', va='center', size=10)
r = ws[i,j,:]
r = np.concatenate((r, [r[0]]))
x,y = (np.c_[r*np.sin(theta), r*np.cos(theta)] + cp).T
ax.fill(x,y, color="C0")
ax.autoscale()
ax.set_xticks([])
ax.set_yticks([])
plt.show()
hex_plot(np.random.rand(5,4,6),a=1)
Use inset_axes
If you really need the axes, e.g. to show the grids, you may position inset_axes
at the respective positions.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import RegularPolygon
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
from matplotlib.projections import get_projection_class
def hex_plot(ws,a=1):
"""
plots a m (rows) x n (cols) hexagonal grid with offset rows where a is
the hexagon's side length and m and n are determined by the first two
dimensions of the weight vectors ws
"""
m,n,l = ws.shape
offsety = .75 * 2*a
offsetx = np.sqrt(3) * a
oddrow = np.sqrt(3)/2 * a
theta = np.linspace(0, 2*np.pi, l+1)
fig,ax = plt.subplots(figsize=(7.5,7.5))
ax.set_aspect('equal')
ax.set_zorder(1)
cs = {}
axcs = {}
for i in range(m):
for j in range(n):
offsetr = oddrow if i % 2 != 0 else 0
cp = (j*offsetx+offsetr,-i*offsety)
cs[(i,j)] = cp
hexg = RegularPolygon(cp,numVertices=6,radius=a,
facecolor='white',edgecolor='k')
ax.add_patch(hexg)
ax.text(cp[0], cp[1], "{},{}\n{:.2f},{:.2f}".format(i,j,cp[0],cp[1]),
ha='center', va='center', size=10)
axins=inset_axes(ax, width="100%", height="100%",
bbox_to_anchor=(cp[0]-offsetx/2, cp[1]-offsety/2, offsetx, offsety),
bbox_transform=ax.transData, borderpad=0,
axes_class=get_projection_class("polar"),
)
axins.set_zorder(4)
axcs[(i,j)] = axins
r = ws[i,j,:]
r = np.concatenate((r, [r[0]]))
axins.fill(theta,r)
axins.set_yticklabels([])
axins.set_xticklabels([])
ax.autoscale()
ax.set_xticks([])
ax.set_yticks([])
plt.show()
hex_plot(np.random.rand(5,4,6),a=1)
这篇关于Matplotlib:Figure.add_axes从x,y转换为相对坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!