Hi, I have a function fig(x) that returns a subplot instance, and I'd like to make a new figure by calling this function twice. For example: def fig(x): s = subplot(111) return s.plot(x) and i wan't to do something like: fig = figure(figsize = (6,12)) fig.add_axes(fig(x1)) fig.add_axes(fig(x2)) ax1, ax2 = fig.get_axes() ax1.set_position([.125, .5, .75, .4]) But it looks like the position is not understood relative to the new figure size, so it doesn't work. Should it or is there a better way to do that ? Thanks, David
>>>>> "David" == David Huard <dav...@gm...> writes: David> Hi, I have a function fig(x) that returns a subplot David> instance, and I'd like to make a new figure by calling this David> function twice. David> For example: def fig(x): s = subplot(111) return s.plot(x) David> and i wan't to do something like: David> fig = figure(figsize = (6,12)) fig.add_axes(fig(x1)) David> fig.add_axes(fig(x2)) David> ax1, ax2 = fig.get_axes() ax1.set_position([.125, .5, .75, David> .4]) David> But it looks like the position is not understood relative David> to the new figure size, so it doesn't work. Should it or David> is there a better way to do that ? There are lots of problems with your code that makes it hard to understand what you are trying to do. Let's get some terminology straight by way of commenting your code, then maybe you can describe what you really want to do def fig(x): # subplot creates an Axes instance on a regular grid; it will add # this Axes to the current Figure, and if no Figure exists, it will # create on. If a current Figure exists, and you have already # created an Axes in it with subplot(111), this call simply makes # the Axes the current Axes. Technically, it creates a Subplot, # which is derived from Axes s = subplot(111) # plot returns a list of Line2D objects, and so the function "fig" # is returning a list of lines return s.plot(x) # this call creates a Figure instance fig = figure(figsize = (6,12)) # add_axes is used to add an Axes to the figure. It expects either an # Axes instance, or a rectangle determined by [left, bottom, width, # height]. You are passing it a list of lines, as noted above fig.add_axes(fig(x1)) fig.add_axes(fig(x2)) # this returns a list of axes ax1, ax2 = fig.get_axes() # this sets the rectangle for the first Axes ax1.set_position([.125, .5, .75, .4]) OK, now that we have some terminology down and hopefully you can see why you are failing, I'll try and guess what you want. You want to add an Axes to the current figure, and have them stacked one above the other. So on the first call, you basically have subplot(111), and on the second call, you have two subplots, subplot(211) and subplot(212). Something like from pylab import figure, show def pushax(fig, x): n = len(fig.axes) for i, ax in enumerate(fig.axes): print 'new gemo', n+1,1,i+1 ax.change_geometry(n+1,1,i+1) ax = fig.add_subplot(n+1, 1, n+1) ax.plot(x) fig = figure() pushax(fig, [1,2,3,4]) pushax(fig, [1,4,9,16]) show() See also the devel list, where Andrew Straw recently added a "Sizer" model along the lines of wx sizers for axes placement. Or I may have misunderstood what you want to do.... JDH
Hi John, Thanks for taking the time to answer a badly formulated question. With your indications, I have been able to get an example working. The point was that I had a function with a number of arguments that returned a subplot(111) instance. Inside this function there are thousands of calls to plot, there are labels and a title. I called the function from my main script, called savefig and stored the figure. Now I want to compare two such figures side by side, and ideally tweak the axes so they are identical. Here is what I came up with your help: def make_complicated_graph(x, sub = None): s = sub or subplot(111) s.plot(x) s.set_title('test12') s.set_xlabel('T') s.set_ylabel('Y') s.scatter([3,4], [5,2], s= 5, c='r') if sub is None: return s fig = figure(1) s1 = subplot(2,1,1) s2 = subplot(2,1,2) make_complicated_graph(arange(5), sub = s1) make_complicated_graph(arange(10), sub = s2) s1.set_xlim(s2.get_xlim()) show() Thanks again for your help. David
>>>>> "David" == David Huard <dav...@gm...> writes: David> Hi John, Thanks for taking the time to answer a badly David> formulated question. With your indications, I have been David> able to get an example working. Great. David> s1.set_xlim(s2.get_xlim()) There is a nice little trick where you can make two axes share the same xaxis. Then when you pan or zoom on one, the other is automagically changed to ax1 = subplot(211) ax2 = subplot(212, sharex=ax1) Ditto for sharey. A very useful trick! JDH
> > > There is a nice little trick where you can make two axes share the > same xaxis. Then when you pan or zoom on one, the other is > automagically changed to > > ax1 = subplot(211) > ax2 = subplot(212, sharex=ax1) But that's not retroactive, or is it ? i.e. if ax2 has a wider x range than ax1, it won't show up. f = figure(1) s1 = subplot(211) s1.plot([1,2,3], [1,2,3]) s2 = subplot(212, sharex = s1) s2.plot([4,5,6], [1,2,3]) I came up with the following function to solve that problem. Is there a more elegant solution? def uniform_limits(axes, xrange = 'widest', yrange = 'widest'): """For all axes, sets xlim and ylim to the widest (shortest) range.""" x = [] y = [] for ax in axes: x.append(ax.get_xlim()) y.append(ax.get_ylim()) x = vstack(asarray(x)) y = vstack(asarray(y)) if xrange == 'widest': xlims = x.min(0)[0], x.max(0)[1] elif xrange == 'shortest': xlims = x.max(0)[0], x.min(0)[1] if yrange == 'widest': ylims = y.min(0)[0], y.max(0)[1] elif yrange == 'shortest': ylims = y.max(0)[0], y.min(0)[1] setp(axes, 'xlim', xlims, 'ylim', ylims) David