Pcolormesh with masked invalid values

I am trying to build a one-dimensional array like pcolormesh (so the color changes along the x axis, but constant along the y axis for each x). But my data has some bad values, so I use a masked array and a customized color palette with masked values ​​set to blue:

import numpy as np import matplotlib.pyplot as plt import matplotlib.cm as cm import copy a = np.array([3, 5, 10, np.inf, 5, 8]) a = np.ma.masked_where(np.isinf(a), a) imdata = np.vstack((a, a)) myhot = copy.copy(cm.hot) myhot.set_bad('b', 1) fig, ax = plt.subplots() im = ax.pcolormesh(imdata, cmap=myhot) plt.colorbar(im) plt.show() 

It works fine if I don't have np.inf value, but I just get an empty plot if I do this. I seem to misunderstood something about how set_bad works, because I get an extra warning:

 RuntimeWarning: invalid value encountered in true_divide resdat /= (vmax - vmin) 

What should I do to get the effect I want?

+5
source share
1 answer

You need to mask imdata , optionally a :

 import numpy as np import matplotlib.pyplot as plt a = np.array([3, 5, 10, np.inf, 5, 8]) imdata = np.ma.masked_invalid(np.atleast_2d(a)) cmap = plt.cm.hot cmap.set_bad('b', 1) fig, ax = plt.subplots() im = ax.pcolormesh(imdata, cmap=cmap) plt.colorbar(im) plt.show() 

enter image description here


If you look at imdata in an interactive session, you will see

 In [185]: imdata Out[185]: masked_array(data = [[ 3. 5. 10. inf 5. 8.] [ 3. 5. 10. inf 5. 8.]], mask = False, fill_value = 1e+20) 

Above, mask=False means nothing is masked. If you wrap this with np.ma.masked_invalid , then:

 In [186]: np.ma.masked_invalid(imdata) Out[186]: masked_array(data = [[3.0 5.0 10.0 -- 5.0 8.0] [3.0 5.0 10.0 -- 5.0 8.0]], mask = [[False False False True False False] [False False False True False False]], fill_value = 1e+20) 

The problem with masking a is that np.vstack does not account for the mask. Alternatively, you could use np.ma.vstack . Generally speaking, only functions in the np.ma namespace are masked.

However, in fact, you do not need to use vstack here; np.atleast_2d will do. vstack creates an array of form (2, N) , and np.atleast_2d creates an array of form (1, N) .


Another alternative is to use set_over instead of set_bad . This would allow you to avoid having to mask the array:

 import numpy as np import matplotlib.pyplot as plt a = np.array([3, 5, 10, np.inf, 5, 8]) imdata = np.atleast_2d(a) cmap = plt.cm.hot cmap.set_over('b') cmap.set_under('g') fig, ax = plt.subplots() b = a[np.isfinite(a)] im = ax.pcolormesh(imdata, cmap=cmap, vmin=b.min(), vmax=b.max()) plt.colorbar(im, extend='both') plt.show() 

enter image description here

extend='both' in combination with set_over and set_under give small colored arrows in the color bar that indicate the color used for values ​​that are outside the range of the color scale.

+9
source

Source: https://habr.com/ru/post/1208464/


All Articles