Home > Enterprise >  Imshow heatmap with array of arrays - problem with final plot/image
Imshow heatmap with array of arrays - problem with final plot/image

Time:12-01

I'd like to plot imshow heatmap but the final image looks very small and disproportional. My data represent a distance measured between atoms (cca 10 atoms of one molecule to cca 30 atoms of other molecule) - the result is array of arrays. I prepared similar output for illustration, however my original dataset is bigger:

import numpy as np
array1 = np.random.randint(20, size=30)
array2 = np.random.randint(20, size=30)
array3 = np.random.randint(20, size=30)
array4 = np.random.randint(20, size=30)
array5 = np.random.randint(20, size=30)
array6 = np.random.randint(20, size=30)
array7 = np.random.randint(20, size=30)
array8 = np.random.randint(20, size=30)
array9 = np.random.randint(20, size=30)
arrayOfArrays = np.array([array1, array2, array3, array4, array5, array6, array7, array8, array9])

Then I wanted to make heatmap to see distances between the atoms, so this is my code:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
im = ax.imshow(arrayOfArrays, origin='upper')

#this is here because I use this approach to define xticks and yticks in my original plot  - here I modified the code with "len(range(0,30))" but in my original plot there is number of atoms for which I measured the distances (something like n_atoms=len(dataset1))
n_1=len(range(0,30))
n_2=len(range(0,9))
tick_interval = 1
ax.set_yticks(np.arange(n_2)[::tick_interval])
ax.set_xticks(np.arange(n_1)[::tick_interval])

# colorbar
cbar = fig.colorbar(im)

The final image created with this particular plot looks already small but the image with my original data is even smaller and I can't see the colors inside at all.

For illustration:this is how it looks with original measured data

I'd really appreciate any suggestions where the problem is or which part of the code should be edited? I tried to edit size of picture, add "interpolation", "ascpect"...

CodePudding user response:

First of all, there is no need to create your arrays like that. Instead, you can use list comprehension to get everything in one line:

arrayOfArrays = np.array([np.random.randint(20, size=30) for _ in range(9)])

I know that you are probably using a dataset, however, this is useful to know for creating the data randomly :3

Also there are some other redundancies in your code, you can use

np.arange(30)

Instead of using

n_1 = len(range(0,30))
np.arange(n_1)

to create a list of integers from 0 to 30

Matplotlib figure resizing: You can adjust the size of the figure, everything that is plotted with

fig.size_in_inches(10, 10)

When I insert this line in your code and run it in google colab, the output is as follows: plot with size adjusting

If you want to adjust the size of the color bar use the shrink argument in the fig.colorbar, a value of 0.3 outputs:

plot adjusting figure size and color bar size

CodePudding user response:

I like the answer from TomiOck, but I believe that JohanC is right is you have a dataset for which you have many more columns than rows. This can be fixed by adding aspect='auto' to the imshow command.

Here is my attempt:

import numpy as np
nrows = 9
ncols = 30
minv = 0 # inclusive
maxv = 20 # exclusive
arrayofArrays = np.random.randint(low=minv, high=maxv, size=(nrows,ncols))

You can generate the random data in one numpy line.

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(14,8)) # width and height in inches
im = ax.imshow(arrayOfArrays, origin='upper', aspect='auto', interpolation='None')

n_1 = np.arange(ncols)
n_2 = np.arange(nrows)
tick_interval = 1
ax.set_yticks(n_2[::tick_interval])
ax.set_xticks(n_1[::tick_interval])

# colourbar
cbar = fig.colorbar(im)

The aspect='auto' stretches your image such that it fill the figure. I also recommend using interpolation='None' to be absolutely sure that matplotlib does not change the colours much (outcome

  • Related