sub-sub-plots, sub-sub-sub-plots, etc.

I need to generate a fairly complex chart, for which I need the ability to specify not only subplots, but also sub-subplots. (Our group has found such charts useful in the past, but they were generated using horrific MATLAB code, which we’re trying to get away from as quickly as we can, not only because the code is impenetrable, but because the MATLAB GUI is unstable, and produces very poor results when we try to print the charts.)

I’ll try to describe what I want to do in a bit more detail (it’s messy).

First imagine a simple plot (just a simple X-Y line graph connecting 3-4 datapoints). I’ll call this a level-0 plot. Now, join ~10 of these level-0 plots side-by-side (with no space between the plots). This new aggregate is a level-1 plot. Next stack ~10 level-1 plots vertically, again, with no space between them. The resulting aggregate is a level-2 plot. Finally arrange ~10 of these level-2 plots side-by-side, with some spacing between them. The desired final product is this level-3 plot.

(In practice, the numbers of elements within each aggregate is not exactly 10. For example, for my immediate application the numbers would be 8 level-0 plots per level-1 plot; 17 level-1 plots per level-2 plot; and 8 level-2 plots per level-3 plot. The level-0 plots should have an aspect ratio (H:W) of 4. Therefore, the level-2 plots will have an aspect ratio of almost 8.)

How can I achieve this?

Thanks!

~kj

P.S. Without knowing much about the internals of matplotlib, it seems to me that the best way to do this would be to define a container class that can have itself as one of the contained elements. In this way, a containment hierarchy of arbitrary depth could be defined. I understand that in matplot lib Figure objects can contain Axes objects. Can they also contain other Figure objects? If not, what would be required to enable this capability? Any comments or suggestions on what it would take to do this would be appreciated.

2010/10/19 Kynn Jones <kynnjo@...287...>:

I need to generate a fairly complex chart, for which I need the ability to
specify not only subplots, but also sub-subplots. (Our group has found such
charts useful in the past, but they were generated using horrific MATLAB
code, which we're trying to get away from as quickly as we can, not only
because the code is impenetrable, but because the MATLAB GUI is unstable,
and produces very poor results when we try to print the charts.)
I'll try to describe what I want to do in a bit more detail (it's messy).
First imagine a simple plot (just a simple X-Y line graph connecting 3-4
datapoints). I'll call this a level-0 plot. Now, join ~10 of these level-0
plots side-by-side (with no space between the plots). This new aggregate is
a level-1 plot. Next stack ~10 level-1 plots vertically, again, with no
space between them. The resulting aggregate is a level-2 plot. Finally
arrange ~10 of these level-2 plots side-by-side, with some spacing between
them. The desired final product is this level-3 plot.
(In practice, the numbers of elements within each aggregate is not exactly
10. For example, for my immediate application the numbers would be 8
level-0 plots per level-1 plot; 17 level-1 plots per level-2 plot; and 8
level-2 plots per level-3 plot. The level-0 plots should have an aspect
ratio (H:W) of 4. Therefore, the level-2 plots will have an aspect ratio of
almost 8.)
How can I achieve this?

My idea would be to add another layer. Meaning to provide a class
which *creates* Axes, and which has other instances of *this class* in
an attribute. The attrib would be scalar. Repetition is done via
recursive call so some privat e method, initiated by a call to a
public commit method. So you would do in pseudo-code:

level0 = LevelAxesGenerator() # NOT actually creating the Axes, see below.
level1 = LevelAxesGenerator(leaf=level0, repeat=10, direction='x') #
NOT creating too.

level1.create(width=foo, height=bar) # Subdividing automatically,
generating Axes in the recursive calls on level0-level

This shouldn't be super-hard.

Sorry, I cannot help you with implementation currently.

When you code it, think about general usability, also for other users,
if you're inclined. I would maybe have been such a user in the past.

``.create()`` could maybe called ``.commit()``, this is more specific.
Create can mean anything.

You could even add a .populate() method, so that you can derive from
``LevelAxesGenerator`` and the instances automatically populate their
axes based on the "coordinate" tuple (level0, level1, level2, ...).
This would be really neat, and it's not too specific, because it'll be
the main use of this level-functionality.

Success,
Friedrich

Hi Friedrich. Thanks for your comments and suggestions.

What I need to clarify is the following. First consider some simple plot A: it has axes, data points, tick marks, labels, etc., and for all these elements there are associated absolute x-y coordinates on the canvas. If now we make this plot A one of the subplots in a collection of, say, 12 subplots, arranged as 3 rows of 4 subplots each, all the x-y coordinates associated with the original plot A will have to be translated and scaled, so that the subplot lands in the right place on the canvas, and has the appropriate size. This process of translation and scaling is what I want to pinpoint: What exactly is the connection between running the add_subplot method and the translation+scaling that it entails?

The reason I need to do this is that for the hierarchical containment scheme I described in my original post, this translation+scaling operation will have to be done at every level. It is not clear to me how the scheme you describe would take care of all these repeated translation/scaling transformations.

I could use some guidance to the source code. What would be a good entry point for me to answer the questions above by reading the source code?

(Maybe these questions would be more appropriate for the developers’ list.)

~kj

···

On Tue, Oct 19, 2010 at 1:27 PM, Friedrich Romstedt <friedrichromstedt@…287…> wrote:

My idea would be to add another layer. Meaning to provide a class

which creates Axes, and which has other instances of this class in

an attribute. The attrib would be scalar. Repetition is done via

recursive call so some privat e method, initiated by a call to a

public commit method. So you would do in pseudo-code:

level0 = LevelAxesGenerator() # NOT actually creating the Axes, see below.

level1 = LevelAxesGenerator(leaf=level0, repeat=10, direction=‘x’) #

NOT creating too.

level1.create(width=foo, height=bar) # Subdividing automatically,

generating Axes in the recursive calls on level0-level

This shouldn’t be super-hard.

Sorry, I cannot help you with implementation currently.

When you code it, think about general usability, also for other users,

if you’re inclined. I would maybe have been such a user in the past.

.create() could maybe called .commit(), this is more specific.

Create can mean anything.

You could even add a .populate() method, so that you can derive from

LevelAxesGenerator and the instances automatically populate their

axes based on the “coordinate” tuple (level0, level1, level2, …).

This would be really neat, and it’s not too specific, because it’ll be

the main use of this level-functionality.