How to name figure in python - python

I want to name figures like this:
import matplotlib as plt
for i in range(0,3):
plt.figure('Method%s',%i)
But seems it is not possible this way.
another way I found is using super title but still it does not work:
from pylab import *
for i in range(0,3):
fig = gcf()
fig.suptitle('Method%s',%i)
do you know any solutions?

If you need to use the figures you are going to create, it may be a good move to store them in some kind of data structure. In my example I will use a list and I will give also an example of using later one of the figures that have been instantiated.
Re naming your figures according to a sequence number, you are correct with the general idea but not with the details, as it happend that in plt.figure() to have a user defined name you have to use a keyword argument that is not named name as one could expect, but … num …
figures = [plt.figure(num="Figure n.%d"%(i+1)) for i in range(3)]
# ^^^
...
figures[1].add_axes(...)
...

Related

Simple way to do a 3d plot interactively using Mayavi?

Reading Mayavi's documentation "http://docs.enthought.com/mayavi/mayavi/building_applications.html" gets me real confused.
My question is, if I just want a 3d plot that allows user interaction, for example, dragging a slider and change the content of the plot, I don't have to use Traits, right? By the documentation, the standard procedure is something like:
class visual(HasTraits):
scene = ...
view = View(...)
#on_trait_change(...)
def do_something()
...
I don't know what traits are. I don't even understand what's an attribute in a class that's defined outside of the constructor (it's a 'trait'?).
Back to the original question, if I just wanted a 3d plot that's changeable, why don't I just directly do it? A working example is as follows:
import numpy as np
from mayavi import mlab
from matplotlib import pyplot as plt
from matplotlib.widgets import Slider
def slider_changed(val):
s.mlab_source.scalars = np.asarray(x * (val + 1), 'd')
# mayavi 3d plot
x, y = np.mgrid[0:3:1,0:3:1]
s = mlab.surf(x, y, np.asarray(x*0.1, 'd'))
# a matplotlib slider
plt.figure()
ax = plt.subplot(1, 1, 1)
slider = Slider(ax, valmin=0., valmax=1., label='test')
slider.on_changed(slider_changed)
plt.show()
mlab.show()
Seems to me if I don't care about embedding the 3d plot in applications, this is a much simpler way to do it? A lot of the attributes of the 3d plot is manipulable through the attributes of mlab_source. I am using a matplotlib slider here as an example, but it seems it can be a pyqt UI or whatever.
However, the documentation says
All the different properties of the pipeline and pipeline objects are expressed as Traits, i.e. special attributes that can be visualized in dialogs and that fire callbacks when they are modified. In particular this means that when a visualization object is modified, the scene can update automatically.
Does it mean if I wanted something that's automatically updated, I have to use Traits in the way it was described above?
Possibly a good start understanding traits would be this article. Those traits, we are talking about here, have been developped by Enthough. It is worth noting that there are also other objects/concepts called traits, which are completely unrelated to what is relevant for using mayavi.
I don't have to use Traits, right?
You are using Traits when calling s.mlab_source.scalars = np.asarray(x * (val + 1), 'd'). The fact that Mayavi updates the plot simply because you change the underlying data is a result of Traits being used.
Mayavi simply uses those traits, instead of usual objects. So once you use mayavi, you inevitably use traits.
Does it mean if I wanted something that's automatically updated, I have to use Traits in the way it was described above?
No, you gave the counter example yourself. You do not have to subclass HasTraits to update a plot. You may use whatever other solution you can think of. However, once you want to embed a mayavi scene into a GUI, it is probably a good idea to do it the way the documentation states it.
Also, subclassing HasTraits is actually a very neat way to easily obtain an interactive figure. So the example from the question could look like
import numpy as np
from mayavi import mlab
from traits.api import HasTraits, Range, Instance,on_trait_change
from traitsui.api import View, Item, Group
from mayavi.core.ui.api import MayaviScene, SceneEditor, MlabSceneModel
x, y = np.mgrid[0:3:1,0:3:1]
class MyModel(HasTraits):
slider = Range(-5., 5., 0.5, )
scene = Instance(MlabSceneModel, ())
def __init__(self):
HasTraits.__init__(self)
self.s = mlab.surf(x, y, np.asarray(x*1.5, 'd'), figure=self.scene.mayavi_scene)
#on_trait_change('slider')
def slider_changed(self):
self.s.mlab_source.scalars = np.asarray(x * (self.slider + 1), 'd')
view = View(Item('scene', editor=SceneEditor(scene_class=MayaviScene)),
Group("slider"))
my_model = MyModel()
my_model.configure_traits()
The nice thing to notice here is that you do not actually define an explicit callback (i.e. there is no on_slider_change or similar).

What does Python's matplotlib figure constructor do with this number?

The code I am currently using has the following:
import matplotlib.pyplot as plt
fig = plt.figure(1)
My question is the following: What is the "1" for? I assume it is some kind of index, but the documentation does not have this parameter:
class matplotlib.figure.Figure(figsize=None, dpi=None, facecolor=None, edgecolor=None, linewidth=0.0, frameon=None, subplotpars=None, tight_layout=None)
Am I missing something? I am pretty sure that I am not the first one to ask this, but neither search nor "Questions that may already have your answer" gave me an answer...
Am I supposed to increase this for the next figure I plot?
You would need to look at the documentation of the command you're using, not some other.
matplotlib.pyplot.figure(num=None, figsize=None, dpi=None,...) has a num argument.
num : integer or string, optional, default: none
If not provided, a new figure will be created, and the figure number will be incremented. The figure objects holds this number in a number attribute. If num is provided, and a figure with this id already exists, make it active, and returns a reference to it. If this figure does not exists, create it and returns it. If num is a string, the window title will be set to this figure’s num.
You don't need to use this, successive calls of plt.figure() will create new figures automatically.

How to delete and resize matplotlib annotations?

I am using the basic axis.annotate(str(i)) function to show values along the points of my graph. The problem is quite quickly they get to bunched together. So I have two questions: How can I remove an annotation? And how can I make one smaller (font size)?
Here is the reference to the annotation method:
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.annotate
I have done my research and surprisingly found nothing. Cheers.
axis.annotate(str(i)) returns an axes Annotation object. You need to assign a variable to it and then you manipulate it however you want.
fig, ax = plt.subplots(1,1)
ax.plot(range(5))
text = ax.annotate(xy = (2,2), s='asdf')
# use any set_ function to change all the properties
text.set_fontsize(20)

How to inspect a numpy/pandas object, i.e. str() in R

When I use R, I can use str() to inspect objects which are a list of things most of the times.
I recently switched to Python for statistics and don't know how to inspect the objects I encounter. For example:
import statsmodels.api as sm
heart = sm.datasets.heart.load_pandas().data
heart.groupby(['censors'])['age']
I want to investigate what kind of object is heart.groupby(['censors']) that allows me to add ['age'] at the end. However, print heart.groupby(['censors']) only tells me the type of the object, not its structure and what I can do with it.
So how do I get to understand the structure of numpy / pandas object, similar to str() in R?
If you're trying to get some insight into what you can do with a Python object, you can inspect it using a beefed-up Python console like IPython. In an IPython session, first put the object you want to look at into a variable:
import statsmodels.api as sm
heart = sm.datasets.heart.load_pandas().data
h_grouped = heart.groupby(['censors'])
Then type out the variable name and double-tap Tab to bring up a list of the object's methods:
In [5]: h_grouped.<Tab><Tab>
# Shows the object's methods
A further benefit of the IPython console is you can quickly check the
help for any individual method by adding a ?:
h_grouped.apply?
# Apply function and combine results
# together in an intelligent way.
If you don't have IPython or a similar console, you can achieve something similar using dir(), e.g. dir(h_grouped), although this will also list
the object's private methods which are generally not useful and shouldn't be
touched in regular use.
type(heart.groupby(['censors'])['age'])
type will tell you what kind of object it is. At the moment you are grouping by a dimension and not telling pandas what to do with age. If you want the mean for example you could do:
heart.groupby(['censors'])['age'].mean()
This would take the mean of age by the group, and return a series.
The groupby is I think a red herring -- "age" is just a column name:
import statsmodels.api as sm
heart = sm.datasets.heart.load_pandas().data
heart
# survival censors age
# 0 15 1 54.3
# ...
heart.keys()
# Index([u'survival', u'censors', u'age'], dtype='object')

function arguments in python

I'm trying to wrap my head around the way positional and keyword arguments work in python, and, it seems, I'm failing rather miserably.
Given a function with a call signature matplotlib.pyplot.plot(*args,**kwargs), it can be called as
import matplotlib.pyplot as plt
x=[1,2,3]
y=[5,6,7]
plt.plot(x,y,'ro-')
plt.show()
Now, I'm trying to wrap it into something which I can call as mplot(x,y,'ro-',...) where ... are whatever arguments the original function was ready to accept. The following fails miserably, but I can't really figure how to fix it:
def mplot(x,y,fmt,*args,**kwargs):
return plt.plot(x,y,fmt,*args,**kwargs)
mplot(x,y,'ro-')
Any pointers to a way out would be very much appreciated.
You need it this way:
def mplot(x,y,fmt,*args,**kwargs):
#do stuff with x, y and fmt
return plt.plot(*args,**kwargs)
I'm assuming that your intention is to consume the x, y and fmt in your mplot routine and then pass the remaining parameters to plt.plot.
I don't believe that this is actually what you want (I can see that plt.plot wants to receive x, y and fmt and so they should not be consumed). I had deleted this answer but since your posted code apparently works, I'll leave this visible for a little while and see if it provokes the real question to be revealed!

Categories

Resources