Matplotlib:Figure.add_axes从x,y转换为相对坐标 [英] Matplotlib: figure.add_axes convert from x,y to relative coordinates

查看:66
本文介绍了Matplotlib:Figure.add_axes从x,y转换为相对坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个自组织地图,我想将其显示为六边形点阵,其中蜘蛛图表示相应单元格中的权重向量/神经元,并且能够通过以下方式创建六边形网格:

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屋!

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