Matplotlib: figure.add_axes конвертировать из x, y в относительные координаты - PullRequest
0 голосов
/ 08 ноября 2018

Я работаю над самоорганизующейся картой, которую хочу показать в виде гексагональной решетки с паутинными диаграммами, представляющими вектор веса / нейрон в соответствующих ячейках, и смог создать гексагональную сетку с помощью следующего:

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

Это дает мне следующее:
5x4 пустая шестигранная сетка

При этом я пытаюсь разместить паутинные диаграммы нейронов 5x4 обученных СДЛ , представляющих каждый весовой вектор, так что паутинная диаграмма в 0,0 (вверху слева) находится внутри гексагональной ячейки в 0,0 (верхний левый). Я попытался использовать вспомогательные графики, но трудности возникают в диаграммах пауков, имеющих полярные проекции, тогда как сетки не имеют. Моя вторая попытка связана с использованием "add_axes". Добавив следующее непосредственно перед plt.show () в коде выше:

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

Я могу поместить диаграмму паука в нижнем левом холсте: Диаграмма паука над гексом , но так как прямоугольник, указанный в add_axes, находится в координатах относительно фигуры, я не могу определить, какая координата 0 0 в исходных осях (шестиугольник 0,0) будет отображаться в относительных координатах. Я посмотрел на преобразования, но это не помогло.

Кто-нибудь сталкивался с этим и придумал решение? Спасибо

1 Ответ

0 голосов
/ 08 ноября 2018

Здесь я вижу два варианта:

Построить все фигуры по одной оси

Поскольку это не похоже на необходимость в специальных полярных осях, вы можете просто нанести заливки на все одинаковые оси в соответствующих положениях шестиугольников.

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)

enter image description here

Использование inset_axes

Если вам действительно нужны оси, например, чтобы показать сетки, вы можете расположить inset_axes в соответствующих позициях.

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)

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...