rendering problem in mplot3d

Hi,

There seems to be a problem in how 3D surfaces and lines are rendered
in mplot3d. The following is a simple script that plots a yellow
sphere, a blue wireframe on the surface of the sphere, and a red
wireframe outside the sphere. The semi-transparent yellow sphere is
rendered beautifully. The blue wireframe can only be seen with certain
viewing angles. The red wireframe is seen all the time, but its part
that is supposedly behind the sphere appears in front of the sphere.
Did I do something wrong or is it a bug of mplot3d? I am using
matplotlib 1.0.0 on Mac OS X 10.6. Thanks!

-Mike

···

===================================================
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')

u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))
ax.plot_surface(x, y, z, rstride=4, cstride=4, color='y', alpha=0.5)
ax.plot_wireframe(x, y, z, rstride=10, cstride=10, color='b')
ax.plot_wireframe(x*1.1, y*1.1, z*1.1, rstride=20, cstride=20, color='r')

Additionally the presented example (after adding a plt.show()) will give the appended traceback if the sphere is panned around. That won't happen if the line

ax = fig.gca(projection='3d')

is replaced with:

ax = Axes3D(fig)

Latest mpl svn (r8565), OS: Debian testing.

Regards,
Jo�o Lu�s

Traceback (most recent call last):
   File "/usr/local/lib/python2.6/dist-packages/matplotlib/backends/backend_gtk.py", line 253, in button_release_event
     FigureCanvasBase.button_release_event(self, x, y, event.button, guiEvent=event)
   File "/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py", line 1603, in button_release_event
     self.callbacks.process(s, event)
   File "/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py", line 262, in process
     proxy(*args, **kwargs)
   File "/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py", line 188, in __call__
     return mtd(*args, **kwargs)
   File "/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py", line 2575, in release_pan
     a.end_pan()
   File "/usr/local/lib/python2.6/dist-packages/matplotlib/axes.py", line 2788, in end_pan
     del self._pan_start
AttributeError: _pan_start

···

On 07/18/2010 04:58 AM, H Mike Duan wrote:

Hi,

There seems to be a problem in how 3D surfaces and lines are rendered
in mplot3d. The following is a simple script that plots a yellow
sphere, a blue wireframe on the surface of the sphere, and a red
wireframe outside the sphere. The semi-transparent yellow sphere is
rendered beautifully. The blue wireframe can only be seen with certain
viewing angles. The red wireframe is seen all the time, but its part
that is supposedly behind the sphere appears in front of the sphere.
Did I do something wrong or is it a bug of mplot3d? I am using
matplotlib 1.0.0 on Mac OS X 10.6. Thanks!

-Mike

Hi,

There seems to be a problem in how 3D surfaces and lines are rendered

in mplot3d. The following is a simple script that plots a yellow

sphere, a blue wireframe on the surface of the sphere, and a red

wireframe outside the sphere. The semi-transparent yellow sphere is

rendered beautifully. The blue wireframe can only be seen with certain

viewing angles. The red wireframe is seen all the time, but its part

that is supposedly behind the sphere appears in front of the sphere.

Did I do something wrong or is it a bug of mplot3d? I am using

matplotlib 1.0.0 on Mac OS X 10.6. Thanks!

-Mike

Additionally the presented example (after adding a plt.show()) will give

the appended traceback if the sphere is panned around. That won’t happen

if the line

ax = fig.gca(projection=‘3d’)

is replaced with:

ax = Axes3D(fig)

Latest mpl svn (r8565), OS: Debian testing.

Regards,

João Luís

Traceback (most recent call last):

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backends/backend_gtk.py”,

line 253, in button_release_event

 FigureCanvasBase.button_release_event(self, x, y, event.button,

guiEvent=event)

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py”,

line 1603, in button_release_event

 self.callbacks.process(s, event)

File “/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py”,

line 262, in process

 proxy(*args, **kwargs)

File “/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py”,

line 188, in call

 return mtd(*args, **kwargs)

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py”,

line 2575, in release_pan

 a.end_pan()

File “/usr/local/lib/python2.6/dist-packages/matplotlib/axes.py”,

line 2788, in end_pan

 del self._pan_start

AttributeError: _pan_start

Joao,

Yes, there is a known issue with objects not properly rendering when viewed at certain angles. How to go about solving this seems to be a difficult one to figure out.

Also, thanks for pointing out the difference between calling gca() and creating the Axes3D object directly. I am not sure exactly why there would be a difference, but I will look into it right away.

Ben Root

···

On Sun, Jul 18, 2010 at 8:56 AM, João Luís Silva <jsilva@…250…> wrote:

On 07/18/2010 04:58 AM, H Mike Duan wrote:


This SF.net email is sponsored by Sprint

What will you do first with EVO, the first 4G phone?

Visit sprint.com/firsthttp://p.sf.net/sfu/sprint-com-first


Matplotlib-devel mailing list

Matplotlib-devel@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Hi,

There seems to be a problem in how 3D surfaces and lines are rendered

in mplot3d. The following is a simple script that plots a yellow

sphere, a blue wireframe on the surface of the sphere, and a red

wireframe outside the sphere. The semi-transparent yellow sphere is

rendered beautifully. The blue wireframe can only be seen with certain

viewing angles. The red wireframe is seen all the time, but its part

that is supposedly behind the sphere appears in front of the sphere.

Did I do something wrong or is it a bug of mplot3d? I am using

matplotlib 1.0.0 on Mac OS X 10.6. Thanks!

-Mike

Additionally the presented example (after adding a plt.show()) will give

the appended traceback if the sphere is panned around. That won’t happen

if the line

ax = fig.gca(projection=‘3d’)

is replaced with:

ax = Axes3D(fig)

Latest mpl svn (r8565), OS: Debian testing.

Regards,

João Luís

Traceback (most recent call last):

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backends/backend_gtk.py”,

line 253, in button_release_event

 FigureCanvasBase.button_release_event(self, x, y, event.button,

guiEvent=event)

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py”,

line 1603, in button_release_event

 self.callbacks.process(s, event)

File “/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py”,

line 262, in process

 proxy(*args, **kwargs)

File “/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py”,

line 188, in call

 return mtd(*args, **kwargs)

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py”,

line 2575, in release_pan

 a.end_pan()

File “/usr/local/lib/python2.6/dist-packages/matplotlib/axes.py”,

line 2788, in end_pan

 del self._pan_start

AttributeError: _pan_start

Joao,

Yes, there is a known issue with objects not properly rendering when viewed at certain angles. How to go about solving this seems to be a difficult one to figure out.

Also, thanks for pointing out the difference between calling gca() and creating the Axes3D object directly. I am not sure exactly why there would be a difference, but I will look into it right away.

Ben Root

Ok, it appears that the .add_subplot() or .gca() approach to creating 3D axes appears to be adding the axes twice to the figure’s canvas. Therefore, while the callback to press_pan() is connected only once, the function loops over all the axes in the figure, and connecting end_pan() twice.

The end_pan() function deletes _pan_start, so the second subsequent call is trying to delete something that doesn’t exist, thereby causing the traceback.

So, now the question remains, why is the Axes3D object added twice to the figure?

Ben Root

···

On Sun, Jul 18, 2010 at 12:05 PM, Benjamin Root <ben.root@…867…> wrote:

On Sun, Jul 18, 2010 at 8:56 AM, João Luís Silva <jsilva@…250…> wrote:

On 07/18/2010 04:58 AM, H Mike Duan wrote:


This SF.net email is sponsored by Sprint

What will you do first with EVO, the first 4G phone?

Visit sprint.com/firsthttp://p.sf.net/sfu/sprint-com-first


Matplotlib-devel mailing list

Matplotlib-devel@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Ben,

Yes, there is a known issue with objects not properly rendering when viewed
at certain angles. How to go about solving this seems to be a difficult one
to figure out.

I think the problem is that mplot3d can't reliably determine which
parts of the surfaces or lines are in front and which are behind. This
is especially clear in the test example where the yellow sphere
doesn't cover parts of the red wire frame. The issue that some objects
can only be seen at certain angles is likely to be a consequence of
this bug.

I want to use mplot3d to visualize my simulations. Is it your opinion
that this bug can't be fixed in a short term? If so, I'll have to
explore other options. Thanks!

-Mike

Further investigation reveals that this actually isn’t all that unusual. If one were to do the same thing, but for a 2d plot, one would find that a figure’s self.axes list would contain a SubplotAxes object, and a regular Axes object. However, in our 3d case, it appears that instead of the SubplotAxes object being placed, the regular object is being placed instead.

Hmmm, curiouser, and curiouser…

Ben Root

···

On Sun, Jul 18, 2010 at 1:40 PM, Benjamin Root <ben.root@…854…> wrote:

On Sun, Jul 18, 2010 at 12:05 PM, Benjamin Root <ben.root@…553…> wrote:

On Sun, Jul 18, 2010 at 8:56 AM, João Luís Silva <jsilva@…250…> wrote:

On 07/18/2010 04:58 AM, H Mike Duan wrote:

Hi,

There seems to be a problem in how 3D surfaces and lines are rendered

in mplot3d. The following is a simple script that plots a yellow

sphere, a blue wireframe on the surface of the sphere, and a red

wireframe outside the sphere. The semi-transparent yellow sphere is

rendered beautifully. The blue wireframe can only be seen with certain

viewing angles. The red wireframe is seen all the time, but its part

that is supposedly behind the sphere appears in front of the sphere.

Did I do something wrong or is it a bug of mplot3d? I am using

matplotlib 1.0.0 on Mac OS X 10.6. Thanks!

-Mike

Additionally the presented example (after adding a plt.show()) will give

the appended traceback if the sphere is panned around. That won’t happen

if the line

ax = fig.gca(projection=‘3d’)

is replaced with:

ax = Axes3D(fig)

Latest mpl svn (r8565), OS: Debian testing.

Regards,

João Luís

Traceback (most recent call last):

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backends/backend_gtk.py”,

line 253, in button_release_event

 FigureCanvasBase.button_release_event(self, x, y, event.button,

guiEvent=event)

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py”,

line 1603, in button_release_event

 self.callbacks.process(s, event)

File “/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py”,

line 262, in process

 proxy(*args, **kwargs)

File “/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py”,

line 188, in call

 return mtd(*args, **kwargs)

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py”,

line 2575, in release_pan

 a.end_pan()

File “/usr/local/lib/python2.6/dist-packages/matplotlib/axes.py”,

line 2788, in end_pan

 del self._pan_start

AttributeError: _pan_start

Joao,

Yes, there is a known issue with objects not properly rendering when viewed at certain angles. How to go about solving this seems to be a difficult one to figure out.

Also, thanks for pointing out the difference between calling gca() and creating the Axes3D object directly. I am not sure exactly why there would be a difference, but I will look into it right away.

Ben Root

Ok, it appears that the .add_subplot() or .gca() approach to creating 3D axes appears to be adding the axes twice to the figure’s canvas. Therefore, while the callback to press_pan() is connected only once, the function loops over all the axes in the figure, and connecting end_pan() twice.

The end_pan() function deletes _pan_start, so the second subsequent call is trying to delete something that doesn’t exist, thereby causing the traceback.

So, now the question remains, why is the Axes3D object added twice to the figure?

Ben Root

My guess is yes, this can not be fixed in a short term, but I am very new to mplot3d, so I don’t know for sure.

Ben

···

On Sun, Jul 18, 2010 at 3:33 PM, H Mike Duan <h.mike.duan@…552…149…> wrote:

Ben,

Yes, there is a known issue with objects not properly rendering when viewed

at certain angles. How to go about solving this seems to be a difficult one

to figure out.

I think the problem is that mplot3d can’t reliably determine which

parts of the surfaces or lines are in front and which are behind. This

is especially clear in the test example where the yellow sphere

doesn’t cover parts of the red wire frame. The issue that some objects

can only be seen at certain angles is likely to be a consequence of

this bug.

I want to use mplot3d to visualize my simulations. Is it your opinion

that this bug can’t be fixed in a short term? If so, I’ll have to

explore other options. Thanks!

-Mike

A few corrections. First, I wrong, it is unusual. The second axes that I noticed in a 2d case came from a colorbar being added. Second, in the 3d case, it was the Axes3DSubplot object being added twice, not the regular object like I originally said.

The cause of this is due to the Axes3D initializer adding itself to the figure object being passed in. This initializer is called when add_subplot() is called, so add_subplot also adds the axes when it is finished making it. For normal projections, the initializer does not add itself to the axes.

Removing the add_axes in the Axes3D initializer would “solve” the issue outright, however, there are plenty of legacy code where Axes3D is called with a figure passed in in order to create the axes, and this would break that use pattern.

Not exactly sure how to proceed here.

Ben Root

···

On Sun, Jul 18, 2010 at 3:35 PM, Benjamin Root <ben.root@…854…> wrote:

On Sun, Jul 18, 2010 at 1:40 PM, Benjamin Root <ben.root@…553…> wrote:

On Sun, Jul 18, 2010 at 12:05 PM, Benjamin Root <ben.root@…553…> wrote:

On Sun, Jul 18, 2010 at 8:56 AM, João Luís Silva <jsilva@…250…> wrote:

On 07/18/2010 04:58 AM, H Mike Duan wrote:

Hi,

There seems to be a problem in how 3D surfaces and lines are rendered

in mplot3d. The following is a simple script that plots a yellow

sphere, a blue wireframe on the surface of the sphere, and a red

wireframe outside the sphere. The semi-transparent yellow sphere is

rendered beautifully. The blue wireframe can only be seen with certain

viewing angles. The red wireframe is seen all the time, but its part

that is supposedly behind the sphere appears in front of the sphere.

Did I do something wrong or is it a bug of mplot3d? I am using

matplotlib 1.0.0 on Mac OS X 10.6. Thanks!

-Mike

Additionally the presented example (after adding a plt.show()) will give

the appended traceback if the sphere is panned around. That won’t happen

if the line

ax = fig.gca(projection=‘3d’)

is replaced with:

ax = Axes3D(fig)

Latest mpl svn (r8565), OS: Debian testing.

Regards,

João Luís

Traceback (most recent call last):

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backends/backend_gtk.py”,

line 253, in button_release_event

 FigureCanvasBase.button_release_event(self, x, y, event.button,

guiEvent=event)

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py”,

line 1603, in button_release_event

 self.callbacks.process(s, event)

File “/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py”,

line 262, in process

 proxy(*args, **kwargs)

File “/usr/local/lib/python2.6/dist-packages/matplotlib/cbook.py”,

line 188, in call

 return mtd(*args, **kwargs)

File

“/usr/local/lib/python2.6/dist-packages/matplotlib/backend_bases.py”,

line 2575, in release_pan

 a.end_pan()

File “/usr/local/lib/python2.6/dist-packages/matplotlib/axes.py”,

line 2788, in end_pan

 del self._pan_start

AttributeError: _pan_start

Joao,

Yes, there is a known issue with objects not properly rendering when viewed at certain angles. How to go about solving this seems to be a difficult one to figure out.

Also, thanks for pointing out the difference between calling gca() and creating the Axes3D object directly. I am not sure exactly why there would be a difference, but I will look into it right away.

Ben Root

Ok, it appears that the .add_subplot() or .gca() approach to creating 3D axes appears to be adding the axes twice to the figure’s canvas. Therefore, while the callback to press_pan() is connected only once, the function loops over all the axes in the figure, and connecting end_pan() twice.

The end_pan() function deletes _pan_start, so the second subsequent call is trying to delete something that doesn’t exist, thereby causing the traceback.

So, now the question remains, why is the Axes3D object added twice to the figure?

Ben Root

Further investigation reveals that this actually isn’t all that unusual. If one were to do the same thing, but for a 2d plot, one would find that a figure’s self.axes list would contain a SubplotAxes object, and a regular Axes object. However, in our 3d case, it appears that instead of the SubplotAxes object being placed, the regular object is being placed instead.

Hmmm, curiouser, and curiouser…

Ben Root

I think the fact that add_axes will just blindly add a duplicate axes
is a bug. So why not have add_axes do something like the following:

if ax not in axes_list:
  axes_list.append(ax)
  <more stuff>

Anyone see anything wrong with this approach?

Ryan

···

On Sun, Jul 18, 2010 at 6:16 PM, Benjamin Root <ben.root@...553...> wrote:

A few corrections. First, I wrong, it is unusual. The second axes that I
noticed in a 2d case came from a colorbar being added. Second, in the 3d
case, it was the Axes3DSubplot object being added twice, not the regular
object like I originally said.

The cause of this is due to the Axes3D initializer adding itself to the
figure object being passed in. This initializer is called when
add_subplot() is called, so add_subplot also adds the axes when it is
finished making it. For normal projections, the initializer does not add
itself to the axes.

Removing the add_axes in the Axes3D initializer would "solve" the issue
outright, however, there are plenty of legacy code where Axes3D is called
with a figure passed in in order to create the axes, and this would break
that use pattern.

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

I agree, this is probably the best way to nip this in the bud without breaking backwards compatibility. However, I am concerned that this might bury other bugs (current or future) by preventing a mistake from making itself apparent. Is there some way to have a special warning put out in the “else” branch of that if?

Ben Root

···

On Mon, Jul 19, 2010 at 10:13 AM, Ryan May <rmay31@…149…> wrote:

On Sun, Jul 18, 2010 at 6:16 PM, Benjamin Root <ben.root@…553…> wrote:

A few corrections. First, I wrong, it is unusual. The second axes that I

noticed in a 2d case came from a colorbar being added. Second, in the 3d

case, it was the Axes3DSubplot object being added twice, not the regular

object like I originally said.

The cause of this is due to the Axes3D initializer adding itself to the

figure object being passed in. This initializer is called when

add_subplot() is called, so add_subplot also adds the axes when it is

finished making it. For normal projections, the initializer does not add

itself to the axes.

Removing the add_axes in the Axes3D initializer would “solve” the issue

outright, however, there are plenty of legacy code where Axes3D is called

with a figure passed in in order to create the axes, and this would break

that use pattern.

I think the fact that add_axes will just blindly add a duplicate axes

is a bug. So why not have add_axes do something like the following:

if ax not in axes_list:

axes_list.append(ax)

Anyone see anything wrong with this approach?