Gap when using contourf and nan's

Bror,

The key to understanding this behaviour is to realise that your fld and mask values are defined at grid points, whereas contour deals with the quads that connect these grid points. If a single grid point is masked out, all 4 quads that the point is a corner of are masked out as far as contour is concerned as you cannot contour a quad that doesn’t have all 4 points defined.

You could solve your problem using contour but you would have to expand the mask so that each masked point [j,i] was expanded to [j-1:j+1, i-1:i+1]. I cannot think of a cunning numpy way of doing this whilst handling all the edge cases and would have to resort to explicit looping over the indices.

There is a better way. From the point mask create a quad mask which is one smaller in each direction. Then use pcolor rather than contour as pcolor takes a quad-centric view of the world. Also, when dealing with masks I use numpy.ma rather than having to handle NaNs.

Here is the simplest modification of your code that I can come up with to do what you want:

import numpy as np

import pylab as pl

#Generate a matrix populated with 1’s

fld = np.ones((4,4))

#Set one corner of the matrix to NaN

fld[:2,:2] = np.nan

#Create a mask.

mask = np.isnan(fld)

#Expand mask so that it is a quad mask.

mask = 1 - (mask[:-1,:-1] | mask[:-1,1:] | mask[1:,:-1] | mask[1:,1:])

#Create masked array.

maskedArray = np.ma.array(np.zeros_like(mask), mask=mask)

#Note mask is one smaller than fld in each direction.

print ‘fld.shape’, fld.shape, ‘mask.shape’, mask.shape

pl.contourf(np.arange(4), np.arange(4), fld, colors=‘b’)

#pcolor does what you want. Any colormap is chosen that has red as its first color.

pl.pcolor(np.arange(4), np.arange(4), maskedArray, cmap=‘autumn’)

pl.show()

Ian

···

On 16 November 2012 15:38, Bror Jonsson <brorlist@…287…> wrote:

Oh, I left out a line in the code, very sorry for that. Here is a full example:

import numpy as np

import pylab as pl

#Generate a matrix populated with 1’s

fld = np.ones((4,4))

#Set one corner of the matrix to NaN

fld[:2,:2] = np.nan

#Plot the contourf plot of the matrix

pl.contourf(arange(4),arange(4),fld,colors=‘b’)

#Create a mask where the NaN’s are reversed.

mask = np.isnan(fld).astype(np.float)

mask[mask==0] = np.nan

#Plot the contourf of the mask

contourf(arange(4),arange(4),mask,colors=‘r’)

The cells with values in mask covers the cells with nan’s in fld exactly:

In [102]: print fld

Out[102]:

array([[ nan, nan, 1., 1.],

   [ nan,  nan,   1.,   1.],
   [  1.,   1.,   1.,   1.],
   [  1.,   1.,   1.,   1.]])

In [101]: print mask

Out[101]:

array([[ 1., 1., nan, nan],

   [  1.,   1.,  nan,  nan],
   [ nan,  nan,  nan,  nan],
   [ nan,  nan,  nan,  nan]])

There are, however, a gap between the red and the blue areas in the figure. Is there a way to make contourf plot mask so that the red patch extends to 2,2 and covers all cells with 1’s in mask?

Many thanks!

:-)Bror