3

Basically, I'd like to make something like the following (triangles not squares as is typically used with plt.matshow). enter image description here

One could start with four 2D arrays, each representing the values for the colours of a set of triangles: right, left, bottom, top:

import numpy as np
right=np.random.randn(8, 8)
left=np.random.randn(8, 8)
bottom=np.random.randn(8, 8)
top=np.random.randn(8, 8)

But I have no idea about the plotting...

Oliver Angelil
  • 1,099
  • 15
  • 31
  • You're looking for plt.triplot, I think: https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.triplot. See also https://stackoverflow.com/questions/29512046/how-to-create-ternary-contour-plot-in-python for a more worked out example that's kinda similar to your plot. – ngoldbaum Jun 21 '17 at 05:26
  • You may also look at [this question](https://stackoverflow.com/questions/44291155/plotting-two-distance-matrices-together-on-same-plot), which plots 2 triangles per pixel, but could easily be extended. – ImportanceOfBeingErnest Jun 21 '17 at 17:03

3 Answers3

3

You may indeed use tripcolor to plot a set of triangles. In the code below the function quatromatrix takes 4 2D arrays of values to colormap as input, creates the triangles and rearanges the colors to fit to the respective positions. It is thus very similar to plotting 4 imshow plots.

enter image description here

import matplotlib.pyplot as plt
import numpy as np

def quatromatrix(left, bottom, right, top, ax=None, triplotkw={},tripcolorkw={}):
    if not ax: ax=plt.gca()
    n = left.shape[0]; m=left.shape[1]

    a = np.array([[0,0],[0,1],[.5,.5],[1,0],[1,1]])
    tr = np.array([[0,1,2], [0,2,3],[2,3,4],[1,2,4]])

    A = np.zeros((n*m*5,2))
    Tr = np.zeros((n*m*4,3))

    for i in range(n):
        for j in range(m):
            k = i*m+j
            A[k*5:(k+1)*5,:] = np.c_[a[:,0]+j, a[:,1]+i]
            Tr[k*4:(k+1)*4,:] = tr + k*5

    C = np.c_[ left.flatten(), bottom.flatten(), 
              right.flatten(), top.flatten()   ].flatten()

    triplot = ax.triplot(A[:,0], A[:,1], Tr, **triplotkw)
    tripcolor = ax.tripcolor(A[:,0], A[:,1], Tr, facecolors=C, **tripcolorkw)
    return tripcolor


right=np.random.randn(8, 8)
left=np.random.randn(8, 8)
bottom=np.random.randn(8, 8)
top=np.random.randn(8, 8)

fig, ax=plt.subplots()

quatromatrix(left, bottom, right, top, ax=ax,
             triplotkw={"color":"k", "lw":1},
             tripcolorkw={"cmap": "plasma"}) 

ax.margins(0)
ax.set_aspect("equal")
ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
0

See the example matplotlib.pyplot.tripcolor(*args, **kwargs) in the matplotlib documentation here. Here is a simplyfied version of want you need:

import matplotlib.pyplot as plt
import numpy as np

xy = np.asarray([
    [-0.01, 0.872], [-0.080, 0.883], [-0.069, 0.888], [-0.054, 0.890]])

x = xy[:, 0]*180/3.14159
y = xy[:, 1]*180/3.14159

triangles = np.asarray([[3, 2,  0]  , [3,  1, 2],   [ 0, 2,  1] , 
                        [0,  1, 2]])

xmid = x[triangles].mean(axis=1)
ymid = y[triangles].mean(axis=1)
x0 = -5
y0 = 52
zfaces = np.exp(-0.01*((xmid - x0)*(xmid - x0) + 
                (ymid - y0)*(ymid - y0)))


plt.figure()
plt.gca().set_aspect('equal')
plt.tripcolor(x, y, triangles, facecolors=zfaces, edgecolors='k')
plt.colorbar()
plt.title('tripcolor of user-specified triangulation')
plt.xlabel('Longitude (degrees)')
plt.ylabel('Latitude (degrees)')

plt.show()

You should get the following picture: enter image description here

jonie83
  • 1,136
  • 2
  • 17
  • 28
-1

I used ImportanceOfBeingErnest's code to plot the Q-table for a reinforcement learning project- I wanted to understand it so I went through and made it a bit clearer. Just replace the data (up, down, left, right) with your own.

def showQVals(self):
    fig, ax = plt.subplots()

    rows = self.level.NUM_ROWS
    cols = self.level.NUM_COLUMNS

    up = self.q[:,Action.UP].reshape(rows, cols)
    down = self.q[:,Action.DOWN].reshape(rows, cols)
    right = self.q[:,Action.RIGHT].reshape(rows, cols)
    left = self.q[:,Action.LEFT].reshape(rows, cols)

    vertDims = np.array([[0,0],[0,1],[.5,.5],[1,0],[1,1]])
    UP = [1,2,4]
    DOWN = [0,2,3]
    RIGHT = [2,3,4]
    LEFT = [0,1,2]
    triDims = np.array([DOWN, UP, RIGHT, LEFT])

    verts = np.zeros((rows*cols*5,2))
    tris = np.zeros((rows*cols*4,3))

    for row in range(rows): #i
        for col in range(cols): #j
            cell = row*cols+col

            #assign slices to the newly constructed verts and tris
            verts[cell*5:(cell+1)*5,:] = np.c_[vertDims[:,0]+col, vertDims[:,1]+row]
            tris[cell*4:(cell+1)*4,:] = triDims + cell*5

    C = np.c_[ up.flatten(), down.flatten(), 
            right.flatten(), left.flatten()   ].flatten()

    ax.invert_yaxis()
    ax.set_title('Q Values')

    triplot = ax.triplot(verts[:,0], verts[:,1], tris)
    tripcolor = ax.tripcolor(verts[:,0], verts[:,1], tris, facecolors=C)

    fig.colorbar(tripcolor)
    plt.show()

q table figure based off of grid map