matlibplotter - 11 months ago 171

Python 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:

- Are these serious warnings? Do I need to look into them and try to

eliminate them? How do I eliminate them? - What is the difference between zsort='max' and zsort='average'?
- 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. The problem was described as "intractable" according to the mplot3d FAQ.

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 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):

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:

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