findobj in pylab

Thanks Matthias. That is a helpful example.

I have been trying to figure out how to recursively examine all the objects
in fig to see if there is a particular settable property. It seems like the
algorithm has to be recursive so that it goes deep into all the lists, etc.
I have not figured out how to know when you have reached the bottom/end of a
trail.

Such a function would let me set any text property in the whole figure
without needing to know if it was a text object, label, legend, etc... maybe
that is not as valuable as I think it would be though.

j

Message: 2

···

Date: Wed, 2 Jul 2008 10:00:31 +0200
From: Matthias Michler <MatthiasMichler@...361...>
Subject: Re: [Matplotlib-users] findobj in pylab
To: matplotlib-users@lists.sourceforge.net
Message-ID: <200807021000.31826.MatthiasMichler@...361...>
Content-Type: text/plain; charset="iso-8859-1"

Hello John,

I'm not sure there is a better way, but the following works for me:
----------------------------------------------------------------------------
----------
from pylab import *

fig = figure()

# adding some subplots / axes instances
subplot(121)
x = linspace(-0.5, 1.5, 10)
plot(x, 0.5*x**2, 'ro', x, 0.33*x**3, 'bs') for i in [2, 4]:
    subplot(2,2,i)

# get all axes of the figure 'fig' ...
allaxes = fig.get_axes()
# ... and reset their property x-limits setp(allaxes, 'xlim', (-.5, 1.5))

ax = allaxes[0]
# get all lines of the axes 'ax' ...
lines = ax.get_lines() # == ax.lines
# ... and reset their markerfacecolor
setp(lines, 'mfc', 'g')

show()
----------------------------------------------------------------------------
-----------

best regards
Matthias

On Thursday 26 June 2008 00:21:13 John Kitchin wrote:

Is there a way to find all the "axes" objects or "line" object handles
in pylab? In matlab I used to do something like A = findobj(gcf)
Allaxes = findall(a,'Type','axes')
Set(allaxes,'Fontname','Arial')

Is there a way to do that in pylab/matplotlib?

Thanks,

j

-----------------------------------
John Kitchin
Assistant Professor
NETL-IAES Resident Institute Fellow
Doherty Hall 3112
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803
http://kitchingroup.cheme.cmu.edu

-----------------------------------
John Kitchin
Assistant Professor
NETL-IAES Resident Institute Fellow
Doherty Hall 3112
Department of Chemical Engineering
Carnegie Mellon University
Pittsburgh, PA 15213
412-268-7803

This is a good idea, and I just added an artist method "findobj" in
svn that recursively calls get_children and implements a match
criteria (class instance or callable filter). There is also a
pyplot/pylab wrapper that operates on current figure by default. Here
is an example:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.text as text

a = np.arange(0,3,.02)
b = np.arange(0,3,.02)
c = np.exp(a)
d = c[::-1]

fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(a,c,'k--',a,d,'k:',a,c+d,'k')
plt.legend(('Model length', 'Data length', 'Total message length'),
           'upper center', shadow=True)
plt.ylim([-1,20])
plt.grid(False)
plt.xlabel('Model complexity --->')
plt.ylabel('Message length --->')
plt.title('Minimum Message Length')

# match on arbitrary function
def myfunc(x):
    return hasattr(x, 'set_color')

for o in fig.findobj(myfunc):
    o.set_color('blue')

# match on class instances
for o in fig.findobj(text.Text):
    o.set_fontstyle('italic')

plt.show()

···

On Thu, Jul 3, 2008 at 8:42 AM, John Kitchin <jkitchin@...1648...> wrote:

Thanks Matthias. That is a helpful example.

I have been trying to figure out how to recursively examine all the objects
in fig to see if there is a particular settable property. It seems like the
algorithm has to be recursive so that it goes deep into all the lists, etc.
I have not figured out how to know when you have reached the bottom/end of a
trail.

Such a function would let me set any text property in the whole figure
without needing to know if it was a text object, label, legend, etc... maybe
that is not as valuable as I think it would be though.

Cool! That is exactly what I wanted to do!

j

···

-----Original Message-----
From: John Hunter [mailto:jdh2358@…287…]
Sent: Thursday, July 03, 2008 10:31 AM
To: John Kitchin
Cc: matplotlib-users@lists.sourceforge.net; MatthiasMichler@...361...
Subject: Re: [Matplotlib-users] findobj in pylab

On Thu, Jul 3, 2008 at 8:42 AM, John Kitchin <jkitchin@...1648...> wrote:

Thanks Matthias. That is a helpful example.

I have been trying to figure out how to recursively examine all the

objects

in fig to see if there is a particular settable property. It seems like

the

algorithm has to be recursive so that it goes deep into all the lists,

etc.

I have not figured out how to know when you have reached the bottom/end of

a

trail.

Such a function would let me set any text property in the whole figure
without needing to know if it was a text object, label, legend, etc...

maybe

that is not as valuable as I think it would be though.

This is a good idea, and I just added an artist method "findobj" in
svn that recursively calls get_children and implements a match
criteria (class instance or callable filter). There is also a
pyplot/pylab wrapper that operates on current figure by default. Here
is an example:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.text as text

a = np.arange(0,3,.02)
b = np.arange(0,3,.02)
c = np.exp(a)
d = c[::-1]

fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(a,c,'k--',a,d,'k:',a,c+d,'k')
plt.legend(('Model length', 'Data length', 'Total message length'),
           'upper center', shadow=True)
plt.ylim([-1,20])
plt.grid(False)
plt.xlabel('Model complexity --->')
plt.ylabel('Message length --->')
plt.title('Minimum Message Length')

# match on arbitrary function
def myfunc(x):
    return hasattr(x, 'set_color')

for o in fig.findobj(myfunc):
    o.set_color('blue')

# match on class instances
for o in fig.findobj(text.Text):
    o.set_fontstyle('italic')

plt.show()

John Hunter wrote:

Thanks Matthias. That is a helpful example.

I have been trying to figure out how to recursively examine all the objects
in fig to see if there is a particular settable property. It seems like the
algorithm has to be recursive so that it goes deep into all the lists, etc.
I have not figured out how to know when you have reached the bottom/end of a
trail.

Such a function would let me set any text property in the whole figure
without needing to know if it was a text object, label, legend, etc... maybe
that is not as valuable as I think it would be though.

This is a good idea, and I just added an artist method "findobj" in
svn that recursively calls get_children and implements a match
criteria (class instance or callable filter). There is also a
pyplot/pylab wrapper that operates on current figure by default. Here
is an example:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.text as text

a = np.arange(0,3,.02)
b = np.arange(0,3,.02)
c = np.exp(a)
d = c[::-1]

fig = plt.figure()
ax = fig.add_subplot(111)
plt.plot(a,c,'k--',a,d,'k:',a,c+d,'k')
plt.legend(('Model length', 'Data length', 'Total message length'),
           'upper center', shadow=True)
plt.ylim([-1,20])
plt.grid(False)
plt.xlabel('Model complexity --->')
plt.ylabel('Message length --->')
plt.title('Minimum Message Length')

# match on arbitrary function
def myfunc(x):
    return hasattr(x, 'set_color')

for o in fig.findobj(myfunc):
    o.set_color('blue')

# match on class instances
for o in fig.findobj(text.Text):
    o.set_fontstyle('italic')

Great! I used to write many such functions for setting font sizes of all
elements in a figure. But speaking about the font sizes, one usually wants the title to be in larger font then the axis labels etc. How could something like this be implemented within your general findobj()?

Just for the reference, this is how I did it:
def setAxesFontSize( ax, size, titleMul = 1.2, labelMul = 1.0 ):
     """size : tick label size,
        titleMul: title label size multiplicator,
        labelMul: x, y axis label size multiplicator"""
     labels = ax.get_xticklabels() + ax.get_yticklabels()
     for label in labels:
         label.set_size( size )

     labels = [ax.get_xaxis().get_label(), ax.get_yaxis().get_label()]
     for label in labels:
         label.set_size( labelMul * size )

     for child in ax.get_children():
         if isinstance( child, pylab.Text ):
             child.set_size( titleMul * size )

Maybe it could be implemented in the sense of:

def myfontsizes( x ):
     """Depending on class of x, return also suggested value of the font

        size."""

for o, size in fig.findobj( myfontsizes, suggest_value = True ):
     o.set_size( size )

# Default for suggest_value is False...
for o in fig.findobj(text.Text):
     o.set_fontstyle('italic')

What do you think?
r.

···

On Thu, Jul 3, 2008 at 8:42 AM, John Kitchin <jkitchin@...1648...> wrote:

Robert Cimrman wrote:
[...]

Great! I used to write many such functions for setting font sizes of all
elements in a figure. But speaking about the font sizes, one usually wants the title to be in larger font then the axis labels etc. How could something like this be implemented within your general findobj()?

Just for the reference, this is how I did it:
def setAxesFontSize( ax, size, titleMul = 1.2, labelMul = 1.0 ):
     """size : tick label size,
        titleMul: title label size multiplicator,
        labelMul: x, y axis label size multiplicator"""
     labels = ax.get_xticklabels() + ax.get_yticklabels()
     for label in labels:
         label.set_size( size )

     labels = [ax.get_xaxis().get_label(), ax.get_yaxis().get_label()]
     for label in labels:
         label.set_size( labelMul * size )

     for child in ax.get_children():
         if isinstance( child, pylab.Text ):
             child.set_size( titleMul * size )

Maybe it could be implemented in the sense of:

def myfontsizes( x ):
     """Depending on class of x, return also suggested value of the font

        size."""

for o, size in fig.findobj( myfontsizes, suggest_value = True ):
     o.set_size( size )

# Default for suggest_value is False...
for o in fig.findobj(text.Text):
     o.set_fontstyle('italic')

What do you think?

I'm not sure if this is addressing your situation, but the simplest way to adjust all font sizes is to use the rcParams dictionary, either directly or via the matplotlibrc file. If the default font sizes for various items are specified using "medium", "large", etc, instead of with numerical values in points, then everything can be scaled by changing the single value, font.size, which is the point size corresponding to "medium".

Eric

Eric Firing wrote:

I'm not sure if this is addressing your situation, but the simplest way to adjust all font sizes is to use the rcParams dictionary, either directly or via the matplotlibrc file. If the default font sizes for various items are specified using "medium", "large", etc, instead of with numerical values in points, then everything can be scaled by changing the single value, font.size, which is the point size corresponding to "medium".

Yes, this certainly works, but only for future plots, no? Or it works
also if a figure already exists and I want to play with the sizes to get
something that looks nice?

r.

Eric Firing wrote:

Robert Cimrman wrote:

Eric Firing wrote:

I'm not sure if this is addressing your situation, but the simplest way to adjust all font sizes is to use the rcParams dictionary, either directly or via the matplotlibrc file. If the default font sizes for various items are specified using "medium", "large", etc, instead of with numerical values in points, then everything can be scaled by changing the single value, font.size, which is the point size corresponding to "medium".

Yes, this certainly works, but only for future plots, no? Or it works also if a figure already exists and I want to play with the sizes to get something that looks nice?

You are correct, it is for future plots, not for interactive experimentation with font sizes. An alternative, though, is to make a very simple script with a test plot using rcParams, run that repeatedly as needed to tune the values, and then use those values when making the plots you want to keep.

Yep. That, or accessing the object properties specific for a given figure, as posted in my first message. I am by no means saying that the rcParams way is not sufficient, I just wanted to elaborate a bit on the findobj idea, as an alternative...

Thanks for your feedback,
r.