matplotlib bar3d clipping problems
Question: I am trying to create a 3D bar graph with Matplotlib 1.2.0 and Python 2.7.3. I
followed the advice in <http://www.mail-archive.com/matplotlib-
users@lists.sourceforge.net/msg19740.html> and plotted the bar one by one, but
I am still getting rendering problems (i.e., bars on top of each other).

Moreover, I get the following when I invoke my code:

/usr/apps/python/lib/python2.7/site-
packages/mpl_toolkits/mplot3d/axes3d.py:1476: RuntimeWarning: divide by zero
encountered in divide for n in normals])

/usr/apps/python/lib/python2.7/site-
packages/mpl_toolkits/mplot3d/axes3d.py:1476: RuntimeWarning: invalid value
encountered in divide for n in normals])

My questions:

  1. Are these serious warnings? Do I need to look into them and try to eliminate them? How do I eliminate them?
  2. What is the difference between zsort='max' and zsort='average'?
  3. What else can I do to eliminate rendering problems?

Thanks in advance!

Here is my code:

    
    
    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    import matplotlib.colors as colors
    import matplotlib.cm as cmx
    
    # my data
    dat = [2.31778665482167e-310, 0.006232785101850947, 0.0285075971030949, 0.0010248181570355695, 0.0048776795767614825, 0.02877090365176044, 0.002459331469834533, 0.0008594610645495889, 0.002919824084878003, 0.000968081117692596, 0.0, 0.0, 0.0319623949119874, 0.00568752311279771, 0.009994801469036968, 0.03248018520506219, 0.006686905726805326, 0.005987863156039365, 0.0072955095915350045, 0.005568911905473998, 0.0, 0.0, 0.0, 0.028483143996551524, 0.031030793902192794, 0.06125216053962635, 0.02935971973938871, 0.028507530280092265, 0.030112963748812088, 0.028293406731749605, 0.0, 0.0, 0.0, 0.0, 0.004510645022825792, 0.028998119822468988, 0.0013993630391143715, 0.0010726572949244424, 0.002288215944285159, 0.0006513973584945584, 0.0, 1.1625e-320, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.03148966953869102, 0.005215047563268979, 0.004491716298086729, 0.006010166308872446, 0.005186976949223524, 0.0, 0.0, 0.0, 0.0, 0.0, 1.107e-320, 0.02983657915729719, 0.028893006725328373, 0.030526067389954753, 0.028629390713739978, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0015217840289869456, 0.002751587509779179, 0.001413669523724954, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0024680339073824705, 0.0008254364860386303, 0.0, 0.0, 0.0, 9.965e-321, 1.15348834e-316, 2.3177866547513e-310, 0.0, 0.0, 0.0, 0.002621588539481613, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 9.41e-321, 1.15348834e-316, 2.3177866547513e-310]
    dat = np.reshape(dat,[10,10],order='F')
    
    lx = len(dat[0])
    ly = len(dat[:,0])
    n = lx*ly
    
    # generate colors
    cm = plt.get_cmap('jet')
    vv = range(len(dat))
    cNorm = colors.Normalize(vmin=0, vmax=vv[-1])
    scalarMap = cmx.ScalarMappable(norm=cNorm, cmap=cm)
    colorVals = [scalarMap.to_rgba(i) for i in range(ly)]
    
    # generate plot data
    xpos = np.arange(0,lx,1)  
    ypos = np.arange(0,ly,1)
    xpos, ypos = np.meshgrid(xpos+0.25, ypos+0.25)
    xpos = xpos.flatten()
    ypos = ypos.flatten()
    zpos = np.zeros(n)
    dx = 0.5*np.ones_like(zpos)
    dy = dx.copy()
    dz = dat.flatten()
    cc = np.tile(range(lx), (ly,1))
    cc = cc.T.flatten()
    
    # generate plot
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    opacity = 1
    
    for i in range(n):
        ax.bar3d(xpos[i], ypos[i], zpos[i], dx[i], dy[i], dz[i],
                 color=colorVals[cc[i]], alpha=opacity, zsort='max')
    
    plt.autoscale(enable=True, axis='both', tight=True)
    plt.grid()
    plt.show(block=False)
    


Answer: This isn't the answer that you are looking for, but I think that this might be
a bug in matplotlib. I think that the same problem was [encountered
here](https://github.com/matplotlib/matplotlib/issues/1292/). The problem was
described as "intractable" according to the [mplot3d
FAQ](http://matplotlib.org/mpl_toolkits/mplot3d/faq.html#my-3d-plot-doesn-t-
look-right-at-certain-viewing-angles).

But to me it doesn't seem intractable. You simple need to figure out which
object is closer to the viewer and set the z-order accordingly. So, I think
that the problem might just be a bug.

If I take the matplotlib 3D [histogram
example](http://matplotlib.org/examples/mplot3d/hist3d_demo.html) and just
change "bins=4" to "bins=6" or a higher number, then I get the same
"axes3d.py:1476: RuntimeWarning: invalid value encountered in divide / for n
in normals])". Also, I can reproduce the wrong z-order of the bars (check out
the tall guy near the front who jumps in front of his short friend):

![wrong order of bars](http://i.stack.imgur.com/VlZy9.png)

The incorrect ordering of the bars seems linked to the divide by zero error,
since the plots look just fine when I use a smaller number of bins.

Line 1476 in axes.py is:

    
    
    shade = np.array([np.dot(n / proj3d.mod(n), [-1, -1, 0.5]) for n in normals])
    

Basically, I think it is trying to figure out the shading using the normal
vectors to each face. But, one or more of the normal vectors is zero, which
should not be the case. So, I think that this is just some bug in matplotlib
that can probably be fixed by someone with more programming skills than
myself.

The mplot3d FAQ is correct that MayaVI can be used if you want a better 3D
engine. I used

    
    
    from mayavi import mlab
    mlab.barchart(xpos,ypos,dz*100)
    

to generate a plot of your data: ![enter image description
here](http://i.stack.imgur.com/RgE7g.jpg)

I hope that this gets figured out soon. I would like to make some similar 3D
barcharts in the near future.

