user3821012
user3821012

Reputation: 1331

Issues with matshow

I am trying to show a matrix and a related vector data together using matplotlib matshow.

vec_data = np.array([[ 0.,  1.,  1.,  1.,  0.,  1.,  1.,  0.,  0.,  0.]])

mat_data = np.array([
       [ 0. ,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0. ],
       [ 0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  1. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  0. ,  0.5,  0. ,  0.5,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0. ,  1. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 0.1,  0.1,  0.1,  0.1,  0. ,  0.1,  0.1,  0.1,  0. ,  0.1],
       [ 0. ,  0. ,  1. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  1. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ,  0. ],
       [ 0. ,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0. ,  0.1,  0.1],
       [ 0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0.1,  0. ,  0. ],
       [ 0.1,  0.1,  0.1,  0.1,  0. ,  0.1,  0.1,  0.1,  0.1,  0. ]])

fig, axes = plt.subplots(2,1,figsize=(4,4),sharey=False,sharex=True,gridspec_kw = {'height_ratios':[25,1]})
axes[0].matshow(mat_data)
axes[1].matshow(vec_data)
axes[1].tick_params(direction='out', length=6, width=0)
axes[1].set_yticklabels([''])
axes[1].set_xlabel('vector')

The resulting image would be as follows:

enter image description here

The issue here is that when putting these two matshow images together mess up the ylim of the first image: it is supposed to show the values from 0 to 9, but it only shows a range 0.5 to 8.5. If I plot the image alone with the command

plt.matshow(mat_data)

I get the desired image with correct ylim.

enter image description here

Anybody knows what causes the issue and how I can fix it? I tried to use

axes[0].set_ylim([-0.5,9.5])

but it does not work.

P.S.: I have used the keyword gridspec_kw = {'height_ratios':[25,1]} so that the vector is shown as a vector--otherwise it will be shown as a matrix with blank values like the following.

enter image description here

The argument sharex = True is used for plt.subplots in order for the vector and the matrix to be aligned. Without the argument, the graph will be like the following

enter image description here

but note there that the issue with the ylim is gone--so it is possible that the argument is the main cause of this issue. I guess if I can find another way to align the two images without using "sharex = True" can solve this issue.

Upvotes: 1

Views: 925

Answers (1)

ImportanceOfBeingErnest
ImportanceOfBeingErnest

Reputation: 339340

Using sharex=True for the subplots overconstrains the system. Matplotlib will hence free the plot limits to be able to show the plot with the given specifications.

The solution would be to use sharex=False (the default). Then the height-ratios need to match the dimensions of the images, i.e.

fig, axes = plt.subplots(2,1,figsize=(4,4),sharey=False,sharex=False,
                    gridspec_kw = {'height_ratios':[mat_data.shape[0],vec_data.shape[0]]})

Complete example:

import numpy as np
import matplotlib.pyplot as plt

vec_data = np.array([[ 0.,  1.,  1.,  1.,  0.,  1.,  1.,  0.,  0.,  0.]])
mat_data = np.random.choice([0,.1,.5,1], size=(10,10))

fig, axes = plt.subplots(2,1,figsize=(4,4),sharey=False,sharex=False,
                    gridspec_kw = {'height_ratios':[mat_data.shape[0],vec_data.shape[0]]})
axes[0].matshow(mat_data)
axes[1].matshow(vec_data)
axes[1].tick_params(direction='out', length=6, width=0)
axes[1].set_yticklabels([''])
axes[1].set_xlabel('vector')

plt.show()

enter image description here

Upvotes: 2

Related Questions