Skip to content

Instantly share code, notes, and snippets.

@krshrimali
Forked from fasiha/README.md
Created December 20, 2017 12:19
Show Gist options
  • Save krshrimali/80bbe8419bff6e7064d7dafa5162ce4d to your computer and use it in GitHub Desktop.
Save krshrimali/80bbe8419bff6e7064d7dafa5162ce4d to your computer and use it in GitHub Desktop.
How to visualize 2D arrays in Matplotlib/Python (like imagesc in Matlab)

Visualizing rectangular 2D arrays in Python and Matplotlib the way you do with Matlab’s imagesc

Say you have a very rectangular 2D array arr, whose columns and rows correspond to very specific sampling locations x and y. That is, the arr[i, j] entry corresponds to some measurement taken at x[j] and y[i].

Matlab’s imagesc shows you this quite meaningfully:

x = linspace(-100, -10, 10);
y = [-8 -3];
data = randn(numel(y), numel(x));

figure()
imagesc(x, y, data)
export_fig('matlab.png')

Matlab imagesc

The two left-most matrix elements’ y-positions are indeed at -8 and -3, as specified in y (although the effect is obscured because of all the extra tick marks). Each matrix element’s horizontal position falls exactly on a multiple of -10, as in the x vector.

Furthermore, the matrix is stretched to cover the figure window, causing non-square matrix elements—very valuable when you want to observe the behavior of the full dataset. A given rectangular matrix element (‘matel’?) has the same flat color over its extent.

In Python and Matplotlib, an image like this is a little harder to obtain, because by default, Matplotlib’s imshow forces square pixels. If you ask for rectangular pixels via aspect='auto', it interpolates the underlying array, so each matrix element has a blend of colors. Finally, if you specify extent=[xmin, xmax, ymin, ymax], it takes these limits to mean the farthest edges of the image shown, rather than to the center of the edge matrix elements—so matrix elements do not line up with the sampling locations in x and y.

Here’s how to fix all these issues:

import numpy as np
import matplotlib.pyplot as plt

def extents(f):
  delta = f[1] - f[0]
  return [f[0] - delta/2, f[-1] + delta/2]

x = np.linspace(-100, -10, 10)
y = np.array([-8, -3.0])
data = np.random.randn(y.size,x.size)

plt.imshow(data, aspect='auto', interpolation='none',
           extent=extents(x) + extents(y), origin='lower')
plt.savefig('py.png')

Matplotlib imshow

We write a custom extents function that takes a vector containing sampling locations, and converts it into a 2-tuple suitable for being used in imshow’s extent keyword argument. We call this extents function on both x and y before giving their combination to imshow. We also specify that no interpolation should happen, and request automatic aspect ratios for rectangular matrix elements. Finally, we request that the image be flipped vertically via origin='lower' (in Matlab, axis ij instead of axis xy).

With these tweaks, we get a visualization that with the same useful properties as imagesc:

  1. rectangular pixels,
  2. flat color over a single matrix element,
  3. x and y axes that correspond to specified sampling locations, and last but definitely not least,
  4. origin that matches these axes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment