axes properties

Thank you so much Vincent? (and Amit) for your detailed answers.

I have two questions remaining.

?

1. All the code examples that I have looked at (including the "getting

started" example on page 1798 of the user manual for Matplotlib 2.0)

uses the "add_subplot" metod. Why should a 3d projection be included

in a subplot and not in a plot ?

?

2. In all the examples, the figure seems to be viewed down the 1,1,1

direction towards the origin. How can the view point be changed from

within the program ?

?

Thanks again,

Jean-Philippe

?

?

?

?

?

?

?

?

?

?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20170318/86fcc15e/attachment.html>

Dear Jean-Philippe,

(If I correctly understood your question 1.:slight_smile: `fig.add_subplot` creates an Axes
instance where you can then plot more or less *any* kind of plot that Matplotlib
supports (line, scatter, hist, patch, etc.). *It is not specific to the '3d'
projection.* `fig.add_subplot(1, 1, 1)` (or `fig.add_subplot(111)` if your
prefer a syntax closer to MATLAB) simply means that you want to create a single
(sub)plot area on your figure canvas. If you are confused because in 2D you
could get a line plot simply with `plt.plot([0, 1, 2])`, understand that under
the hood it is only some kind of wrapper for the (OO-)equivalent:

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot([0, 1, 2])

The difference here to get a 3D Axes instance is that you have to precise the
projection when you create it (`fig.add_subplot(1, 1, 1, projection='3d')`).

Besides (if I am correct), please note that ?we? tend to promote using an
equivalent (but more OO-)wrapper, namely `plt.subplots` (the final *s* is
important!). In 2D, you can thus write

fig, ax = plt.subplots()  # create a "111-subplot"
ax.plot([0, 1, 2])

and you can pass different **kwargs to it, among which a 'subplot_kw' dictionary
that allows you to precise the projection. For example if you want to get a
"111-subplot" 3d Axes:

fig, ax = plt.subplots(subplot_kw={'projection': '3d'})

It is a bit verbose is this simple situation but becomes rather convenient for
grids with several subplots.

About 2. you may want to have a look at the following properties and methods:
- ax.dist
- ax.azim
- ax.elev
- ax.view_init(elev=..., azim=...)

Here is a small script (PNG output is attached) that demonstrate their usage:

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

def dummy_plot(ax):
    X, Y = np.meshgrid(np.arange(-5, 5, 0.25), np.arange(-5, 5, 0.25))
    Z = np.sin(np.sqrt(X**2 + Y**2))
    ax.plot_surface(X, Y, Z, cmap='coolwarm')
    # Remove all the ticks for eye pleasure
    ax.xaxis.set_major_locator(plt.NullLocator())
    ax.yaxis.set_major_locator(plt.NullLocator())
    ax.zaxis.set_major_locator(plt.NullLocator())
    return ax

# Here is a way to instantiate all the 2x2 subplots at once, without using
# the `fig.add_subplot` method. *axs* is a 2x2-array of Axes instances.
fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(6.4, 4.8),
                        num="Demo_Jean-Philippe_GRIVET_2",  # <- figure label
                        subplot_kw={'projection': '3d'})

ax = dummy_plot(axs[0, 0])
ax.set_title("Forced defaults: dist=10 (a.u.),\nazim=-60 (deg), elev=30 (deg)")
# NB: these values does not seem to be exactly the (1, 1, 1) direction to me.
ax.dist = 10
ax.view_init(azim=-60, elev=30)
# From the docstring of `ax.view_init`:
# Set the elevation and azimuth of the axes. This can be used to rotate
# the axes programatically:
# - 'elev' stores the elevation angle in the z plane.
# - 'azim' stores the azimuth angle in the x,y plane.

ax = dummy_plot(axs[0, 1])
ax.set_title("Doubled 'dist' value")
ax.dist *= 2

# NB: one can also directly set the `ax.azim` and `ax.elev` properties
ax = dummy_plot(axs[1, 0])
ax.set_title("'azim' increased of 45 deg.")
ax.azim += 45

ax = dummy_plot(axs[1, 1])
ax.set_title("'elev' set to 60 deg.")
ax.elev = 60

plt.tight_layout()
plt.show()

Hopefully it will help you to plot what you want :).

Best,
Adrien

Thank you so much Vincent (and Amit) for your detailed answers.

I have two questions remaining.

1. All the code examples that I have looked at (including the "getting
started" example on page 1798 of the user manual for Matplotlib 2.0)
uses the "add_subplot" metod. Why should a 3d projection be included
in a subplot and not in a plot ?

2. In all the examples, the figure seems to be viewed down the 1,1,1
direction towards the origin. How can the view point be changed from
within the program ?

Thanks again,
Jean-Philippe

-------------- next part --------------
A non-text attachment was scrubbed...
Name: Demo_Jean-Philippe_GRIVET_2.png
Type: image/png
Size: 128810 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20170321/d8614daf/attachment-0001.png&gt;

···

On 18/03/2017 17:56, Jean-Philippe GRIVET wrote:

Jean-Philippe,

To answer your second question, you can use the `view_init()` method of the
axes to change the orientation of the axes:
http://matplotlib.org/mpl_toolkits/mplot3d/api.html#mpl_toolkits.mplot3d.axes3d.Axes3D.view_init

An example using it to do a "rotation":
http://matplotlib.org/examples/mplot3d/rotate_axes3d_demo.html

I hope that helps!
Ben Root

···

On Tue, Mar 21, 2017 at 9:57 AM, vincent.adrien at gmail.com < vincent.adrien at gmail.com> wrote:

Dear Jean-Philippe,

(If I correctly understood your question 1.:slight_smile: `fig.add_subplot` creates an
Axes
instance where you can then plot more or less *any* kind of plot that
Matplotlib
supports (line, scatter, hist, patch, etc.). *It is not specific to the
'3d'
projection.* `fig.add_subplot(1, 1, 1)` (or `fig.add_subplot(111)` if your
prefer a syntax closer to MATLAB) simply means that you want to create a
single
(sub)plot area on your figure canvas. If you are confused because in 2D you
could get a line plot simply with `plt.plot([0, 1, 2])`, understand that
under
the hood it is only some kind of wrapper for the (OO-)equivalent:

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot([0, 1, 2])

The difference here to get a 3D Axes instance is that you have to precise
the
projection when you create it (`fig.add_subplot(1, 1, 1,
projection='3d')`).

Besides (if I am correct), please note that ?we? tend to promote using an
equivalent (but more OO-)wrapper, namely `plt.subplots` (the final *s* is
important!). In 2D, you can thus write

fig, ax = plt.subplots()  # create a "111-subplot"
ax.plot([0, 1, 2])

and you can pass different **kwargs to it, among which a 'subplot_kw'
dictionary
that allows you to precise the projection. For example if you want to get a
"111-subplot" 3d Axes:

fig, ax = plt.subplots(subplot_kw={'projection': '3d'})

It is a bit verbose is this simple situation but becomes rather convenient
for
grids with several subplots.

About 2. you may want to have a look at the following properties and
methods:
- ax.dist
- ax.azim
- ax.elev
- ax.view_init(elev=..., azim=...)

Here is a small script (PNG output is attached) that demonstrate their
usage:

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

def dummy_plot(ax):
    X, Y = np.meshgrid(np.arange(-5, 5, 0.25), np.arange(-5, 5, 0.25))
    Z = np.sin(np.sqrt(X**2 + Y**2))
    ax.plot_surface(X, Y, Z, cmap='coolwarm')
    # Remove all the ticks for eye pleasure
    ax.xaxis.set_major_locator(plt.NullLocator())
    ax.yaxis.set_major_locator(plt.NullLocator())
    ax.zaxis.set_major_locator(plt.NullLocator())
    return ax

# Here is a way to instantiate all the 2x2 subplots at once, without using
# the `fig.add_subplot` method. *axs* is a 2x2-array of Axes instances.
fig, axs = plt.subplots(nrows=2, ncols=2, figsize=(6.4, 4.8),
                        num="Demo_Jean-Philippe_GRIVET_2",  # <- figure
label
                        subplot_kw={'projection': '3d'})

ax = dummy_plot(axs[0, 0])
ax.set_title("Forced defaults: dist=10 (a.u.),\nazim=-60 (deg), elev=30
(deg)")
# NB: these values does not seem to be exactly the (1, 1, 1) direction to
me.
ax.dist = 10
ax.view_init(azim=-60, elev=30)
# From the docstring of `ax.view_init`:
# Set the elevation and azimuth of the axes. This can be used to rotate
# the axes programatically:
# - 'elev' stores the elevation angle in the z plane.
# - 'azim' stores the azimuth angle in the x,y plane.

ax = dummy_plot(axs[0, 1])
ax.set_title("Doubled 'dist' value")
ax.dist *= 2

# NB: one can also directly set the `ax.azim` and `ax.elev` properties
ax = dummy_plot(axs[1, 0])
ax.set_title("'azim' increased of 45 deg.")
ax.azim += 45

ax = dummy_plot(axs[1, 1])
ax.set_title("'elev' set to 60 deg.")
ax.elev = 60

plt.tight_layout()
plt.show()

Hopefully it will help you to plot what you want :).

Best,
Adrien

On 18/03/2017 17:56, Jean-Philippe GRIVET wrote:
> Thank you so much Vincent (and Amit) for your detailed answers.
>
> I have two questions remaining.
>
> 1. All the code examples that I have looked at (including the "getting
> started" example on page 1798 of the user manual for Matplotlib 2.0)
> uses the "add_subplot" metod. Why should a 3d projection be included
> in a subplot and not in a plot ?
>
> 2. In all the examples, the figure seems to be viewed down the 1,1,1
> direction towards the origin. How can the view point be changed from
> within the program ?
>
> Thanks again,
> Jean-Philippe

_______________________________________________
Matplotlib-users mailing list
Matplotlib-users at python.org
Matplotlib-users Info Page

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20170321/097af77b/attachment.html&gt;

Thanks a lot Benjamin and Vincent for your most kind and detailed answers.

In reply to Vincent, I regret that the authors of Matplotkib did not pursue
the wrapper idea and propose a function plot3d(x,y,z); it would make
life simpler.

I copied from the net (I can't remember where) the following code fragment:

from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as pt

fig = pt.figure()
ax = fig.gca(projection='3d')
................
surf = ax.plot_wireframe(X, Y, Z, rstride = 10,cstride = 10)

which looks rather similar to Matlab syntax and works well for me.
  Is that considered to be obsolete or in bad style ?

Thanks again,
Jean-Philippe

fig.gca(projection='3d') is perfectly valid, but you need to realize what
it does. It will only work if it is a single plot in the figure, and that
that is the *first* reference to the plot. If some other plotting action
has already happened, then it wouldn't work, because fig.gca() means "get
the current axes in the figure, if it exists; if it doesn't exist yet,
create one with these parameters". So, if an axes already exists, then
it'll fetch that one, and it may not be a 3d axes. Also, if you plan to do
subplots, then `gca()` may be limiting since it is not explicit about which
subplot in a figure it is referring to.

Cheers!
Ben Root

···

On Wed, Mar 22, 2017 at 1:57 PM, Jean-Philippe Grivet < jean-philippe.grivet at wanadoo.fr> wrote:

Thanks a lot Benjamin and Vincent for your most kind and detailed answers.

In reply to Vincent, I regret that the authors of Matplotkib did not pursue
the wrapper idea and propose a function plot3d(x,y,z); it would make life
simpler.

I copied from the net (I can't remember where) the following code fragment:

from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as pt

fig = pt.figure()
ax = fig.gca(projection='3d')
................
surf = ax.plot_wireframe(X, Y, Z, rstride = 10,cstride = 10)

which looks rather similar to Matlab syntax and works well for me.
Is that considered to be obsolete or in bad style ?

Thanks again,
Jean-Philippe

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/matplotlib-users/attachments/20170322/e1599b84/attachment.html&gt;

Hello Jean-Philippe,

From my point of view, coding style only (really) matters if you intend to share

your code with other people. If you are and will ever be the only writer and
reader of your own code, then I would be inclined to say that as long as you are
comfortable with it, you can code as you wish ;). A remaining problem that may
still remain though is if you go asking questions on forums, Stack Overflow,
etc., where people may expect you to write code that follows some guidelines. In
Python, the guidelines are commonly those from the
[PEP8](PEP 8 – Style Guide for Python Code | peps.python.org). A very loose summary and yet
quite sufficient for a day-to-day use might be:

- 'my_variable' and 'my_function' vs 'MyClass' for the naming schemes;
- '_nonpublic_method()' vs 'public_method()' for classe method names
- wrap long lines into smaller ones (usually < 80 characters);
- use 4 spaces (instead of tab) per indentation level;
- mostly use whitespaces around binary operators and except in a few situations:
    - my_function(arg_1, kwarg_1=val_1, kwarg_2=val_2) (no space around '=')
    - 'res = a*b +c*d' is better than 'res = a * b + c * d'
- my_dict = {key_1: item_1, key_2: item_2}, i.e. 'key<no_space>:<space> item'

Concerning Matplotlib conventions, I would say that the common use is to import
pyplot as 'plt', not 'pt'.

import matplotlib.pyplot as plt

It is true that we try in our current documentation to promote the
object-oriented interface (OO-interface), which usually make things clearer when
you write scripts (you explicitely know where the drawing will be performed for
example):

# Either with the most recent wrapper:
fig, ax = plt.subplots()
ax. plot([0, 2, 1])

# or following the older but still perfectly OK fashion:
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([0, 2, 1])

However, at least for 2D plots, you can definitively use the more MATLAB-like
fashion, i.e.

plt.plot([0, 2, 1])

which will implicitly draw in the current Axes instance, and create one , as
well as a Figure one, if none already exists.

In the case of mplot3d, I may be wrong but I think that you have to use at least
partially the OO-interface. Except for a few points stated above, I would say
that your code snippet should still be perfectly OK for a long time :). Here is
a version with the small style fixes I would suggest:

import numpy as np
import matplotlib.pyplot as plt  # 'pt' <- 'plt'
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()  # 'pt' <- 'plt'
ax = fig.gca(projection='3d')
# yada yada yada
surf = ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)  # no space around '='

And if you really want concise code (for example during an interactive session),
I think you can achieve things that are rather close to MATLAB (at least from
what I remember), like:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# Just for demonstration sake, we create dummy data with a convenient helper
from mpl_toolkits.mplot3d.axes3d import get_test_data
X, Y, Z = get_test_data(0.05)

# Straightforward case with a single 3D-plot

ax = plt.gca(projection='3d')  # a figure is created implicitly if none exists
ax.plot_wireframe(X, Y, Z)
plt.title("Single plot")  # <=> ax.set_title("Single plot")

# Straightforward case with 1x2 subplots.
plt.figure()  # new figure, just to avoid drawing in the previous one

ax = plt.subplot(121, projection='3d')
ax.plot_wireframe(X, Y, Z)
plt.title("1st subplot:\ndefault parameters")

ax = plt.subplot(122, projection='3d')
ax.plot_wireframe(X, Y, Z, cstride=10, rstride=5)
plt.title("2nd subplot:\ncustom parameters")

Regards,
Adrien

···

On 22/03/2017 18:57, Jean-Philippe Grivet wrote:

Thanks a lot Benjamin and Vincent for your most kind and detailed answers.

In reply to Vincent, I regret that the authors of Matplotkib did not pursue
the wrapper idea and propose a function plot3d(x,y,z); it would make life simpler.

I copied from the net (I can't remember where) the following code fragment:

from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as pt

fig = pt.figure()
ax = fig.gca(projection='3d')
................
surf = ax.plot_wireframe(X, Y, Z, rstride = 10,cstride = 10)

which looks rather similar to Matlab syntax and works well for me.
Is that considered to be obsolete or in bad style ?

Thanks again,
Jean-Philippe