E. AMARAL
E. AMARAL

Reputation: 1019

Organizing axes with Matplotlib

I'm working with Matplotlib and Python in the plotting of 2D skeletons made of joints connected by lines (that data comes from a text file of coordinates, representing the (x,y) joints), side by side with a distance matrix of each joint to all the others, for each skeleton plotted, generated by some calculations with the same text file data.

By now, I've plotted the skeletons, connected to a key press event, what means that by each text file read, a number of skeletons is plotted, generating a movement, and the movement is perceptible since the user must press the right arrow key to plot the sequence of skeletons, one by one, and the movement is visible ever since.

Also, I've built the matrices, and each matrix is plotted in a blue scale with a color bar aside, after some calculation in the code. I've tested the plotting of each matrix, and it's working fine. Notice that if I have 43 skeletons in a text file, there must be 43 matrices, one for each skeleton.

The problem is: I've used thescatter method to plot the skeletons, with one figure and one axis only. I must plot each matrix aside the skeleton, and I'm using imshow to plot the matrices from an array into a graph, in the format of an image, like an image. But I can't figure out how to organize prorperly the axis and plot the matrix aside de skeleton, without having to add another axis, like fig, (ax1,ax) = plt.subplots(ncols=2), for example. Since I'm a beginner in Matplotlib, I'm a bit confused about how to plot the matrix side by side the skeletons, without having to rebuilt the method for plotting the skeletons.

The code:

from matplotlib import gridspec
import matplotlib.pyplot as plt
import numpy as np

movement = np.loadtxt("file01.txt")

bone_list = [[1, 3], [2, 3], [3, 4], [4, 7], [5, 7], [6, 7], [1, 8], [2, 9], 
[8, 10], [9, 11], [10, 12], [11, 13], [5, 14], [6, 15], [14, 16], [15, 17], 
[16, 18], [17, 19], [3, 20]]

bone_list = np.array(bone_list) - 1
number_of_postures = int(len(movement)/20)
list_for_matrix = []


for i in range(number_of_postures):

    list_for_matrix.append(movement[(i*20):((i+1)*20),:3]) 
    matrixCoord = np.array(list_for_matrix)
    matrixDistance= np.zeros((number_of_postures,20,20))


for k in range(number_of_postures): 
    for i in range(len(matrixDistance[0])): 
        for j in range(len(matrixDistance[0])):     
            matrixDistance[k,i,j] = np.linalg.norm(matrixCoord[k,i,:] - 
            matrixCoord[k,j,:])


fig, ax = plt.subplots()

i = 1 #this variable is for plotting from the second skeleton on with the function call.

def press(event):
global i

if event.key == 'right':        
    fig.canvas.draw_idle()  
    plt.cla()   
    plt.xlim(100, 190)  
    plt.ylim(-250, 0)   
    skeleton = movement[i*20:(i+1)*20]      
    x = skeleton[:, 0]      
    y = -skeleton[:, 1]     
    sc = ax.scatter(x, y, s=40) 
    for bone in bone_list:      
        ax.plot([x[bone[0]], x[bone[1]]], [y[bone[0]], y[bone[1]]], 'r')

    plt.subplots_adjust(left=0.12, bottom=0.11, right=0.49, top=0.93,wspace=0.20, hspace=0.20)

    if i < number_of_postures:  
        i+=1

    else:           
        return


    #plot of the first skeleton, outside the function call.
    plt.xlim(100, 190)
    plt.ylim(-250, 0)
    skeleton = movement[0*20:(0+1)*20]
    x = skeleton[:, 0]
    y = -skeleton[:, 1]
    sc = ax.scatter(x, y, s=40)
    for bone in bone_list   
        ax.plot([x[bone[0]], x[bone[1]]], [y[bone[0]], y[bone[1]]], 'r')
    plt.subplots_adjust(left=0.12, bottom=0.11, right=0.49,top=0.93,wspace=0.20, hspace=0.20)


    fig.canvas.mpl_connect("key_press_event", press)
    plt.show()


    #that's the plotting for the matrices, outside the plt.show(), since it's not working properly.
    '''
    img = matrixDistance[i]
    imgplot = plt.imshow(img)
    plt.title('Distance Matrix')
    imgplot.set_cmap('PuBu')
    plt.colorbar()

    '''

Below, there are two pictures, the result generated by the code, and an idea of what I need to achieve yet.

Result generated by the code:

Result generated by the code

What I need to achieve yet:

What I need to achieve yet

Upvotes: 0

Views: 539

Answers (1)

user2699
user2699

Reputation: 3147

Most commands affecting subplots replace any axis existing in the same area. You've created a single axes for the figure with the line

fig, ax = plt.subplots()

Subsequent calls to subplots or subplot will remove this axis and create a new one. You need to setup both axes at the same time. You can execute

fig, (ax1, ax2) = figure(ncol=2)

Then use

sca(ax1) 

before your current code. That will make ax1 the axis matplotlib draws on. After the current code and before the code to draw matrices use the command again to set ax2 (i.e. sca(ax2)).

Upvotes: 1

Related Questions