axes properties

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

axes properties

Jean-Philippe Grivet

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
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: axes properties

Adrien VINCENT
Dear Jean-Philippe,

(If I correctly understood your question 1.:) `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:
```python
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
```python
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:
```python
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
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users

Demo_Jean-Philippe_GRIVET_2.png (172K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: axes properties

Benjamin Root
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, [hidden email] <[hidden email]> wrote:
Dear Jean-Philippe,

(If I correctly understood your question 1.:) `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:
```python
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
```python
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:
```python
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
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users



_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: axes properties

Jean-Philippe Grivet
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


_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: axes properties

Benjamin Root
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 <[hidden email]> 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




_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users
Reply | Threaded
Open this post in threaded view
|

Re: axes properties

Adrien VINCENT
In reply to this post by Jean-Philippe Grivet
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](https://www.python.org/dev/peps/pep-0008/). 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
>
>

_______________________________________________
Matplotlib-users mailing list
[hidden email]
https://mail.python.org/mailman/listinfo/matplotlib-users