On 16 November 2012 15:38, Bror Jonsson <brorl...@gmail.com> 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
>

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
------------------------------------------------------------------------------
Monitor your physical, virtual and cloud infrastructure from a single
web console. Get in-depth insight into apps, servers, databases, vmware,
SAP, cloud infrastructure, etc. Download 30-day Free Trial.
Pricing starts from $795 for 25 servers or applications!
http://p.sf.net/sfu/zoho_dev2dev_nov
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

Reply via email to