plot_surface does not work

Hi,

My OS is Mac OS X Lion, and the version of matplotlib is 1.2.0 from macport.

Now I have an 2d array

a=array([[ 0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ],
       [ 0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ],
       [ 0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ],
       [ 0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ],
       [ 0. , 0. , 0. , 0. ,
           0. , 6.40312424, 19.02629759, 9.8488578 ,
          12.16552506, 14. , 0. , 37.01351105],
       [ 0. , 0. , 0. , 0. ,
           6.40312424, 4.24264069, 1.41421356, 8.54400375,
           4.47213595, 31.25699922, 0. , 25.70992026],
       [ 0. , 0. , 0. , 0. ,
          19.02629759, 1.41421356, 17.2626765 , 31.32091953,
          24.18677324, 43.829214 , 0. , 55.14526272],
       [ 0. , 0. , 0. , 0. ,
           9.8488578 , 8.54400375, 31.32091953, 35.51056181,
          40.81666326, 57.27128425, 0. , 84.62860037],
       [ 0. , 0. , 0. , 0. ,
          12.16552506, 4.47213595, 24.18677324, 40.81666326,
          43.65775991, 74.24957912, 0. , 112.0044642 ],
       [ 0. , 0. , 0. , 0. ,
          14. , 31.25699922, 43.829214 , 57.27128425,
          74.24957912, 0. , 0. , 0. ],
       [ 0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ,
           0. , 0. , 0. , 0. ],
       [ 0. , 0. , 0. , 0. ,
          37.01351105, 25.70992026, 55.14526272, 84.62860037,
         112.0044642 , 0. , 0. , 0. ]])

first I plot it (in ipython notebook) using:

coord_max=12
fig = plt.figure()
ax = fig.gca(projection='3d')
x,y=np.meshgrid(np.arange(coord_max),np.arange(coord_max))
ax.plot_wireframe(x,y,a)

and the plot looks fine.

but if I use plot_surface instead, the plot looks very wrong: the plot is zero everywhere except on the boundaries.

This is because the default rstride and cstride arguments is 10, IIRC. Since your array is only 12x12, the surface plotting is barely plotting anything. Try calling:

ax.plot_surface(x, y, a, rstride=1, cstride=1)

I hope that helps!
Ben Root

···

On Tue, Dec 11, 2012 at 8:25 AM, Degang Wu <samuelandjw@…287…> wrote:

Hi,

My OS is Mac OS X Lion, and the version of matplotlib is 1.2.0 from macport.

Now I have an 2d array

a=array([[ 0. , 0. , 0. , 0. ,

       0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ],

   [   0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ],

   [   0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ],

   [   0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ],

   [   0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    6.40312424,   19.02629759,    9.8488578 ,

      12.16552506,   14.        ,    0.        ,   37.01351105],

   [   0.        ,    0.        ,    0.        ,    0.        ,

       6.40312424,    4.24264069,    1.41421356,    8.54400375,

       4.47213595,   31.25699922,    0.        ,   25.70992026],

   [   0.        ,    0.        ,    0.        ,    0.        ,

      19.02629759,    1.41421356,   17.2626765 ,   31.32091953,

      24.18677324,   43.829214  ,    0.        ,   55.14526272],

   [   0.        ,    0.        ,    0.        ,    0.        ,

       9.8488578 ,    8.54400375,   31.32091953,   35.51056181,

      40.81666326,   57.27128425,    0.        ,   84.62860037],

   [   0.        ,    0.        ,    0.        ,    0.        ,

      12.16552506,    4.47213595,   24.18677324,   40.81666326,

      43.65775991,   74.24957912,    0.        ,  112.0044642 ],

   [   0.        ,    0.        ,    0.        ,    0.        ,

      14.        ,   31.25699922,   43.829214  ,   57.27128425,

      74.24957912,    0.        ,    0.        ,    0.        ],

   [   0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ,

       0.        ,    0.        ,    0.        ,    0.        ],

   [   0.        ,    0.        ,    0.        ,    0.        ,

      37.01351105,   25.70992026,   55.14526272,   84.62860037,

     112.0044642 ,    0.        ,    0.        ,    0.        ]])

first I plot it (in ipython notebook) using:

coord_max=12

fig = plt.figure()

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

x,y=np.meshgrid(np.arange(coord_max),np.arange(coord_max))

ax.plot_wireframe(x,y,a)

and the plot looks fine.

but if I use plot_surface instead, the plot looks very wrong: the plot is zero everywhere except on the boundaries.

This is because the default rstride and cstride arguments is 10, IIRC. Since your array is only 12x12, the surface plotting is barely plotting anything. Try calling:

ax.plot_surface(x, y, a, rstride=1, cstride=1)

You know, this has tripped me up a few times too. I don't use plot_surface often enough to always remember this, and it is not the first parameter I think to check when debugging a program. Is there a reason the default rstride and cstride aren't 1 other than possible memory constraints for large arrays?

I suppose changing the defaults might break programs that rely on this behavior, but if this API ever gets revamped, consider this a request to make 1 be the default instead. I would think that the default should be that the obvious command "just works" while plots that may require too much memory can be tweaked to work faster (I'm assuming that is the reason for the default of 10).

thanks
Ethan

I actually don’t know the reason for the defaults (I didn’t create mplot3d), but that has always been my suspicion. There is an existing PR to change the default behavior to be somewhat “automatic”. At the time, I wasn’t really in favor of it, but when looked in this light, it does make some more sense.

I’ll have to think about this a bit more.
Ben Root

···

On Tue, Dec 11, 2012 at 12:17 PM, Ethan Gutmann <ethan.gutmann@…287…> wrote:

This is because the default rstride and cstride arguments is 10, IIRC. Since your array is only 12x12, the surface plotting is barely plotting anything. Try calling:

ax.plot_surface(x, y, a, rstride=1, cstride=1)

You know, this has tripped me up a few times too. I don’t use plot_surface often enough to always remember this, and it is not the first parameter I think to check when debugging a program. Is there a reason the default rstride and cstride aren’t 1 other than possible memory constraints for large arrays?

I suppose changing the defaults might break programs that rely on this behavior, but if this API ever gets revamped, consider this a request to make 1 be the default instead. I would think that the default should be that the obvious command “just works” while plots that may require too much memory can be tweaked to work faster (I’m assuming that is the reason for the default of 10).

Would it be workable for the default to be proportional to the size of the array passed in? (suggested only because I do that myself, when deciding how coarse an investigative plot I can get away with.)

&C

···

On Dec 11, 2012, at 9:28 AM, Benjamin Root wrote:

On Tue, Dec 11, 2012 at 12:17 PM, Ethan Gutmann <ethan.gutmann@…287…> wrote:

This is because the default rstride and cstride arguments is 10, IIRC. Since your array is only 12x12, the surface plotting is barely plotting anything. Try calling:

ax.plot_surface(x, y, a, rstride=1, cstride=1)

You know, this has tripped me up a few times too. I don’t use plot_surface often enough to always remember this, and it is not the first parameter I think to check when debugging a program. Is there a reason the default rstride and cstride aren’t 1 other than possible memory constraints for large arrays?

I suppose changing the defaults might break programs that rely on this behavior, but if this API ever gets revamped, consider this a request to make 1 be the default instead. I would think that the default should be that the obvious command “just works” while plots that may require too much memory can be tweaked to work faster (I’m assuming that is the reason for the default of 10).

I actually don’t know the reason for the defaults (I didn’t create mplot3d), but that has always been my suspicion. There is an existing PR to change the default behavior to be somewhat “automatic”. At the time, I wasn’t really in favor of it, but when looked in this light, it does make some more sense.

I’ll have to think about this a bit more.
Ben Root


LogMeIn Rescue: Anywhere, Anytime Remote support for IT. Free Trial
Remotely access PCs and mobile devices and provide instant support
Improve your efficiency, and focus on delivering more value-add services
Discover what IT Professionals Know. Rescue delivers
http://p.sf.net/sfu/logmein_12329d2d_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
matplotlib-users List Signup and Options

That is pretty much what the PR I was referring to does:

https://github.com/matplotlib/matplotlib/pull/1040

It makes it so that the behavior of both plot_surface and plot_wireframe is the same in this respect. So, by default, the rstride and cstride would be 1% of the size of your data array. This would make the default for the recent example be 1, therefore showing every point. I wonder if a logarithmic default would make sense to better handle large data arrays?

Thoughts?
Ben Root

···

On Tue, Dec 11, 2012 at 2:08 PM, Chloe Lewis <chlewis@…1016…> wrote:

&C

Would it be workable for the default to be proportional to the size of the array passed in? (suggested only because I do that myself, when deciding how coarse an investigative plot I can get away with.)

I hope nobody minds if I chime in here.

I'm in favour of making the defaults a little more intelligent that
what is implemented at present, i.e, a constant stride for any
surface. Any non-trivial scaling law to determine what stride to use
will result in more expected behaviour than what our users are
currently seeing.

Could we do better? Could we have plot_surface try and estimate the
stride based on the 'roughness' of the surface to be plotted? This
method would grind to a halt for very rough surfaces, so we could
default to a scaling law in these cases.

What does everyone think about this approach?

···

On Tue, Dec 11, 2012 at 1:16 PM, Benjamin Root <ben.root@...1304...> wrote:

On Tue, Dec 11, 2012 at 2:08 PM, Chloe Lewis <chlewis@...1016...> wrote:

Would it be workable for the default to be proportional to the size of the
array passed in? (suggested only because I do that myself, when deciding how
coarse an investigative plot I can get away with.)

&C

That is pretty much what the PR I was referring to does:

Make 'rstride', 'cstride' default values smarter. by carrutstick · Pull Request #1040 · matplotlib/matplotlib · GitHub

It makes it so that the behavior of both plot_surface and plot_wireframe is
the same in this respect. So, by default, the rstride and cstride would be
1% of the size of your data array. This would make the default for the
recent example be 1, therefore showing every point. I wonder if a
logarithmic default would make sense to better handle large data arrays?

Thoughts?
Ben Root

--
Damon McDougall
http://www.damon-is-a-geek.com
Institute for Computational Engineering Sciences
201 E. 24th St.
Stop C0200
The University of Texas at Austin
Austin, TX 78712-1229

Hi All,

Would it be workable for the default to be proportional to the size of the
array passed in? (suggested only because I do that myself, when deciding how
coarse an investigative plot I can get away with.)

&C

That is pretty much what the PR I was referring to does:

Make 'rstride', 'cstride' default values smarter. by carrutstick · Pull Request #1040 · matplotlib/matplotlib · GitHub

It makes it so that the behavior of both plot_surface and plot_wireframe is
the same in this respect. So, by default, the rstride and cstride would be
1% of the size of your data array. This would make the default for the
recent example be 1, therefore showing every point. I wonder if a
logarithmic default would make sense to better handle large data arrays?

Thoughts?
Ben Root

I hope nobody minds if I chime in here.

I'm in favour of making the defaults a little more intelligent that
what is implemented at present, i.e, a constant stride for any
surface. Any non-trivial scaling law to determine what stride to use
will result in more expected behaviour than what our users are
currently seeing.

Could we do better? Could we have plot_surface try and estimate the
stride based on the 'roughness' of the surface to be plotted? This
method would grind to a halt for very rough surfaces, so we could
default to a scaling law in these cases.

OK, way late here, but

1) I wasted an hour today before I discovered what "rstride" and "cstride" were. Reading the documentation, I still don't actually know what they are, except that if I want to see all my data I need to set them to 1. "Array row stride (step size)", is pretty enigmatic! "stride" is a term I've never heard before except is reference to walking. I see it is used in computer science, but to refer to the byte-wise distance between array elements, so not very analogous.

Can I suggest the docs be improved to say exactly what these do (I assume either average over cstride columns and rstride rows, or subsample on that frequency, not clear which)? Can I also suggest the default is 1? Its pretty frustrating for large a chunk of your data to not show up for no logical reason. If my data set is too large, I am smart enough to subsample it myself before I plot it.

2) Can I suggest this example be added to the tutorial? python - Color matplotlib plot_surface command with surface gradient - Stack Overflow
None of the other examples explain how to colour your surface with data, which is what I wanted.

3) I think plot_surface should accept a fourth (optional) argument C for colouring the faces: plot_surface(X,Y,Z,C). I do this a lot if I want to make a 3-D plot, and normalizing C, clipping it, and indexing a colormap seem clunky, when the routine could do it for me.

Thanks, Jody

···

On Dec 11, 2012, at 16:59 PM, Damon McDougall <damon.mcdougall@...287...> wrote:

On Tue, Dec 11, 2012 at 1:16 PM, Benjamin Root <ben.root@...1304...> wrote:

On Tue, Dec 11, 2012 at 2:08 PM, Chloe Lewis <chlewis@...1016...> wrote:

--
Jody Klymak

On Tue, Sep 24, 2013 at 03:46:52PM -0700, Jody Klymak wrote: [...]

2) Can I suggest this example be added to the tutorial?
python - Color matplotlib plot_surface command with surface gradient - Stack Overflow
None of the other examples explain how to colour your surface with
data, which is what I wanted.

3) I think plot_surface should accept a fourth (optional) argument C
for colouring the faces: plot_surface(X,Y,Z,C). I do this a lot if I
want to make a 3-D plot, and normalizing C, clipping it, and indexing
a colormap seem clunky, when the routine could do it for me.

I largely agree. I spend many days to get my plots and posted a few
times on this list e.g.

Better documetation would be very nice; please provide example code.
And a remark about that: most exemples show functions with symmetry.
This can be confusing when coloring and other techniques are applied.

PS. Please cut down the original message before replying.

···

Subject: Re: [Matplotlib-users] how to create a facecolors map?
Date: Thu, 29 Aug 2013 09:24:40