8

I'm plotting a surface using matplotlib 1.1.0.

The plot Z axis is masked like so:

Zm = ma.masked_where((abs(z_grid) < 1.09) & (abs(z_grid) > 0.91), (z_surface))
surf = ax.plot_surface(X, Y,Zm, rstride=2, cstride=2, cmap=colors,linewidth=0, antialiased=False)

But I'm not seeing the mask applied on the plot. I plotted the mask itself as a subplot

surf = ax.plot_surface(X, Y,ma.getmask(Zm), rstride=2, cstride=2, cmap=colors,linewidth=0, antialiased=False)

Which worked, so I know my mask does actually contain True values.

Full code:

from pylab import *
import matplotlib.pyplot as plt
from matplotlib.widgets import Button
import numpy
from mpl_toolkits.mplot3d.axes3d import Axes3D
from  matplotlib import patches
from matplotlib.figure import Figure
from matplotlib import rcParams


fig = plt.figure(figsize=plt.figaspect(0.5))
ax = fig.add_subplot(1, 2, 1,projection='3d')

pole_positions_orig = [-0.6+0.73j];
zero_positions_orig = [0.29-0.41j];

surface_limit = 1.7;
min_val = -surface_limit;
max_val = surface_limit;

surface_resolution = 0.0333;

X = numpy.arange(min_val,max_val,surface_resolution)
Y = numpy.arange(min_val,max_val,surface_resolution)
X, Y = numpy.meshgrid(X, Y)

z_grid = X + Y*1j;
z_surface = z_grid*0;

pole_positions = numpy.round(pole_positions_orig,1) + surface_resolution/2+(surface_resolution/2)*1j;
zero_positions = numpy.round(zero_positions_orig,1) + surface_resolution/2 +(surface_resolution/2)*1j;

for k in range(0, len(zero_positions)):
    z_surface = z_surface + 20*log10((z_grid - zero_positions[k].real - zero_positions[k].imag*1j));
    z_surface = z_surface + 20*log10((z_grid - zero_positions[k].real + zero_positions[k].imag*1j));

for k in range(0, len(pole_positions)):
    z_surface = z_surface - 20*log10((z_grid - pole_positions[k].real - pole_positions[k].imag*1j));
    z_surface = z_surface - 20*log10((z_grid - pole_positions[k].real + pole_positions[k].imag*1j));    


colors = cm.jet;
colors.set_bad('k');


Zm = ma.masked_where((abs(z_grid) < 1.09) & (abs(z_grid) > 0.91), (z_surface))

z_surface = Zm;

surf = ax.plot_surface(X, Y,z_surface, rstride=2, cstride=2, cmap=colors,linewidth=0, antialiased=False)


ticks = [-1, 1]; 
z_ticks = [-30,-20,-10,0,10,20,30]; 
ax.set_xticks(ticks);
ax.set_yticks(ticks);   
ax.set_zticks(z_ticks);

ax.set_xlabel('Re')
ax.set_ylabel('Im')
ax.set_zlabel('Mag(db)',ha='left')
plt.setp(ax.get_zticklabels(), fontsize=7)
plt.setp(ax.get_xticklabels(), fontsize=7)  
plt.setp(ax.get_yticklabels(), fontsize=7)

ax = fig.add_subplot(1, 2, 2,projection='3d')
surf = ax.plot_surface(X, Y,ma.getmask(z_surface), rstride=2, cstride=2, cmap=colors,linewidth=0, antialiased=False)

ax.grid(b=None);
show();

This is what I have:

python plot

This is what I want (from matlab):

matlab plot

What am I missing?

4
  • So the masked data should still be drawn, but in a solid color? Commented Jun 13, 2012 at 19:03
  • yes, is this possible? ... If not, then just not drawing the mask is a good compromise. I played around with "colors.set_bad('k',alpha=0.5)" to give that a try, but it didn't change the plot at all. Commented Jun 13, 2012 at 19:31
  • Don't think its going to be possible with masking, looks like plot_surface() doesn't respect masks. Probably is possible through a clever workaround, but its beating me at the moment :( Commented Jun 14, 2012 at 7:54
  • I've added an answer to the question explaining how I got around the problem :) It's not ideal, but it worked for my purposes. Commented Jun 14, 2012 at 18:15

2 Answers 2

13

Fraxel mentioned that surface_plot doesn't support masking. In order to get around the issue, this is what I did:

I basically manually masked the z axis data by setting every masked value to numpy.nan like so:

Zm = ma.masked_where((abs(z_grid) < 1.02) & (abs(z_grid) > 0.98), (z_surface))
z_surface[where(ma.getmask(Zm)==True)] = numpy.nan

Cmap Broken

However, it messed up my colormap scaling. To fix that, I did this:

cmap = cm.jet
lev = numpy.arange(-30,30,1);
norml = colors.BoundaryNorm(lev, 256)

surf = ax.plot_surface(X, Y, z_surface,...,norm = norml)

Fixed

Not 100% what I wanted, but a good compromise nonetheless.

1

You can do it, but you need to do it by manually colouring the surface faces yourself;

the cmap function takes a nubmer between 0 and 1, so we just need to normalise the values before calling the cmap function on them.

z_surface = numpy.real(z_surface)
min_z, max_z = z_surface.min(), z_surface.max()
colours = numpy.zeros_like(z_surface, dtype=object)

for i in range(len(z_surface)):
  for j in range(len(z_surface[0])):
    if 0.91 < numpy.sqrt(X[i,j]**2 + Y[i,j]**2) < 1.09:
      colours[i,j] = "red"  
    else:
      colours[i,j] = plt.get_cmap("jet")((z_surface[i,j]-min_z) / (max_z - min_z))


surf = ax.plot_surface(X, Y, z_surface, rstride=2, cstride=2, facecolors=colours, linewidth=0, antialiased=False)

enter image description here

I should also point out that matplotlib is casting your z array to real - whether or not you are taking advantage of this on purpose though i don't know.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.