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 |
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 |
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 http://matplotlib.org/examples/mplot3d/rotate_axes3d_demo.html On Tue, Mar 21, 2017 at 9:57 AM, [hidden email] <[hidden email]> wrote: Dear Jean-Philippe, _______________________________________________ Matplotlib-users mailing list [hidden email] https://mail.python.org/mailman/listinfo/matplotlib-users |
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 |
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 RootOn 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. _______________________________________________ Matplotlib-users mailing list [hidden email] https://mail.python.org/mailman/listinfo/matplotlib-users |
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 |
Free forum by Nabble | Edit this page |