From: Robin <ro...@gm...> - 2008-02-15 12:04:22
|
Hello, I have some functions that produce various figures. This is usually done by calling figure(), then the plot function (eg bar). I save the figure object and pass it out. I would like to be able to collect several figure objects from such functions and collect them as subplots in a single figure for easy printing, comparison. I don't want to change the functions that create them though, because I will also want to view them individually in the future. So given a load of figure objects, how can I make a new figure with each subplot one of the existing figures? (I hope this is clear). Does it matter if the original figure object has been closed? I'm having a look through the help to see if I could find it but it's taking a bit of time and I thought it's probably quite easy if your more familiar with the object structure of matplotlib. Thanks Robin |
From: Robin <ro...@gm...> - 2008-02-17 21:26:01
|
On Feb 15, 2008 12:04 PM, Robin <ro...@gm...> wrote: > Hello, > > I have some functions that produce various figures. This is usually > done by calling figure(), then the plot function (eg bar). I save the > figure object and pass it out. > > I would like to be able to collect several figure objects from such > functions and collect them as subplots in a single figure for easy > printing, comparison. I don't want to change the functions that create > them though, because I will also want to view them individually in the > future. > > So given a load of figure objects, how can I make a new figure with > each subplot one of the existing figures? (I hope this is clear). Does > it matter if the original figure object has been closed? I'm having a > look through the help to see if I could find it but it's taking a bit > of time and I thought it's probably quite easy if your more familiar > with the object structure of matplotlib. I'm afraid I haven't been able to make very much progress with this on my own. I tried calling get_children on the figure objects I have, and then tried calling set_axes with the subplot of a new figure on each of the children in the hope that this would bind them over, but after playing a bit nothing I've tried seems to work. Is it possible to do this, or even if it is is it perhaps too complicated/involved to be worth while? (I had hoped it would be relatively straightforward once I found the right combination of get/set functions to move the plot objects over to the new subplot). Thanks, Robin |
From: Eric F. <ef...@ha...> - 2008-02-18 04:44:34
|
Robin, I'm not sure I understand what you want to do; is it to recycle axes objects that were originally in one or more figures and put them in another figure? It looks like that might be doable if you create the new figure, then for each axes call ax.set_figure(newfig), and then for each axes call newfig.add_axes(ax). I would be not the least surprised if all this failed, though. Eric Robin wrote: > On Feb 15, 2008 12:04 PM, Robin <ro...@gm...> wrote: >> Hello, >> >> I have some functions that produce various figures. This is usually >> done by calling figure(), then the plot function (eg bar). I save the >> figure object and pass it out. >> >> I would like to be able to collect several figure objects from such >> functions and collect them as subplots in a single figure for easy >> printing, comparison. I don't want to change the functions that create >> them though, because I will also want to view them individually in the >> future. >> >> So given a load of figure objects, how can I make a new figure with >> each subplot one of the existing figures? (I hope this is clear). Does >> it matter if the original figure object has been closed? I'm having a >> look through the help to see if I could find it but it's taking a bit >> of time and I thought it's probably quite easy if your more familiar >> with the object structure of matplotlib. > > I'm afraid I haven't been able to make very much progress with this on > my own. I tried calling get_children on the figure objects I have, and > then tried calling set_axes with the subplot of a new figure on each > of the children in the hope that this would bind them over, but after > playing a bit nothing I've tried seems to work. > > Is it possible to do this, or even if it is is it perhaps too > complicated/involved to be worth while? (I had hoped it would be > relatively straightforward once I found the right combination of > get/set functions to move the plot objects over to the new subplot). > > Thanks, > > Robin > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Matplotlib-users mailing list > Mat...@li... > https://lists.sourceforge.net/lists/listinfo/matplotlib-users |
From: Robin <ro...@gm...> - 2008-02-18 07:43:21
|
On Feb 18, 2008 4:44 AM, Eric Firing <ef...@ha...> wrote: > I'm not sure I understand what you want to do; is it to recycle axes > objects that were originally in one or more figures and put them in > another figure? Hi, I have a number of figures created from functions like this: fig1 = plot_fig1(data1) fig2 = plot_fig2(data2) etc. Now instead of having two separate figure windows displaying the plots, I would like them to appear as subplots in a new figure (single window) and close the previous figures. Other than moving to the subplot in a new figure, I would like everything about the plot to remain the same (titles, labels, scale,ticks etc.) I had imagined something like this would be possible: newfig = figure() sp1 = subplot(211) for x in fig1.get_children(): x.set_axes(sp1) or similar, but it doesn't seem to work. Also, when trying something like this, does it matter if the original figure windows are already closed? (ie does the act of closing the window change the objects to make them not show-able any more). I'm not sure if I can do this reallocation by figure or axes, that is what I was asking really. > It looks like that might be doable if you create the > new figure, then for each axes call ax.set_figure(newfig), and then for > each axes call newfig.add_axes(ax). I would be not the least surprised > if all this failed, though. If I move the axes over as you describe, will this also bring the plotted data, titles etc.? I will try and play around with this later today. Would I first have to delete the existing axes created when I create the subplot? Wouldn't that make a problem, since isn't it these created axis that have the important subplot position properties (if I just move over the existing axes how will the subplot placing work). I imagine I might have to, copy over the axes from old figure, set position and size of old axes to those of new subplot axes, copy over all children (rectangles, text etc.)? Alternatively if theres another way of achieving the same thing. I thought I could modify the functions to take an optional axes argument, so if not present they make a new figure, and if present they use that: fig = figure() sp1 = subplot(211) plot_data1(data1, axes=sp1) but then I'm not sure how inside the function, I use plot commands (bar, plot, imshow) on this provided subplot axis. Thanks, Robin |
From: John H. <jd...@gm...> - 2008-02-18 14:00:32
|
On Feb 18, 2008 1:43 AM, Robin <ro...@gm...> wrote: > If I move the axes over as you describe, will this also bring the > plotted data, titles etc.? I will try and play around with this later > today. Would I first have to delete the existing axes created when I > create the subplot? Wouldn't that make a problem, since isn't it these You will need to remove the axes from the original figure: oldfig.delaxes(ax) and then add it to the new figure ax.set_figure(newfig) newfig.add_axes(ax) If you are adding several, you may want to play with the axes position or geometry (for subplots) ax.set_position and ax.change_geometry And yes, the data, titles, labels, grids, ticks, etc will be brought over. As Eric points out, this is an under-exercised part of the code so something may break, though last time I tried it it worked. JDH |
From: Robin <ro...@gm...> - 2008-02-18 15:35:24
|
On Feb 18, 2008 2:00 PM, John Hunter <jd...@gm...> wrote: > You will need to remove the axes from the original figure: > > oldfig.delaxes(ax) > > > and then add it to the new figure > > ax.set_figure(newfig) > newfig.add_axes(ax) > > If you are adding several, you may want to play with the axes position > or geometry (for subplots) ax.set_position and ax.change_geometry > > And yes, the data, titles, labels, grids, ticks, etc will be brought > over. As Eric points out, this is an under-exercised part of the code > so something may break, though last time I tried it it worked. Thanks, that allowed me to make some real progress, and worked to some degree. Here is the code I am using: figs = [x[0] for x in results] oldaxs = [fig.get_children()[1] for fig in figs] for fig, ax in zip(figs,oldaxs): fig.delaxes(ax) pl.close(fig) newf = pl.figure() for i,ax in enumerate(oldaxs): ax.set_figure(newf) newf.add_axes(ax) ax.change_geometry(2,2,i+1) pl.show() Unfortunately, there are some problems: - while the subplots are correct, they don't resize when I resize the window - the plots are bar graphs, only the first xtick label is there, the others are missing - top of the xaxis of the bottom row of plots overlaps with the bottom of the x axis of the top row - generally it looks pretty bad Since this approach is proving problematic, and sounds like it isn't really supported anyway (I had imagined it would be relatively straightforward) I think it would be better to try the other way (passing optional axes argument to plot to if I want it in a multi-subplot figure, otherwise just create a new figure). I would appreciate some pointers on how to do this. ie: fig = plot_data1(data1) # this should create a new figure obect and return it newfig = figure() sp1 = subplot(221) plot_data1(data1, axes=sp1) # this should plot the data on the provided subplot axes. However I do not know how to make the bar, title, xlabel, xtick etc. commands I am using from pylab within the function act on the specified subplot axes (if present). Is this possible? Thanks, Robin |
From: John H. <jd...@gm...> - 2008-02-18 15:44:22
|
On Feb 18, 2008 9:34 AM, Robin <ro...@gm...> wrote: > figs = [x[0] for x in results] > oldaxs = [fig.get_children()[1] for fig in figs] > for fig, ax in zip(figs,oldaxs): > fig.delaxes(ax) > pl.close(fig) Probably better: oldaxs = [] for fig in figs: for ax in fig.axes: fig.delaxes(ax) oldaxs.append(ax) pl.close(fig) > Unfortunately, there are some problems: > - while the subplots are correct, they don't resize when I resize the window > - the plots are bar graphs, only the first xtick label is there, the > others are missing > - top of the xaxis of the bottom row of plots overlaps with the bottom > of the x axis of the top row - generally it looks pretty bad > > Since this approach is proving problematic, and sounds like it isn't > really supported anyway (I had imagined it would be relatively It's not that it isn't supported, it's just rarely used and so may have slowly broken over time. It is useful, so It would be worthwhile for us to fix it. Are you using 0.91.2 or svn? > straightforward) I think it would be better to try the other way > (passing optional axes argument to plot to if I want it in a > multi-subplot figure, otherwise just create a new figure). I would > appreciate some pointers on how to do this. ie: You might consider something like def myfunc(ax=None): if ax is None: fig = figure() ax = fig.add_subplot(111) ax.plot(something) > However I do not know how to make the bar, title, xlabel, xtick etc. > commands I am using from pylab within the function act on the > specified subplot axes (if present). > Is this possible? ax.set_xlabel('mylabel') ax.set_title('my title') ax.grid(True) etc... See help(matplotlib.axes.Axes) JDH |
From: Robin <ro...@gm...> - 2008-02-18 16:02:43
|
Thanks very much for all your help. On Feb 18, 2008 3:44 PM, John Hunter <jd...@gm...> wrote: > It's not that it isn't supported, it's just rarely used and so may > have slowly broken over time. It is useful, so It would be worthwhile > for us to fix it. Are you using 0.91.2 or svn? I am using 0.91.2 at the moment (on Mac OS X - I think this was the downloaded binary). I could build from svn if you think it would make a difference. I guess for now I will use the function argument method, but I'm happy to keep this code around and provide what feedback I can. I suspect that if the subplot geometry was set to autoupdate when the window is resized as it is for a fresh subplot, then the overlapping axes might go away after a window resize. The missing xticks is a bit of a mystery though - they all seems to be there, just not shown. I tried setting them visible and redrawing but no luck. Thanks again, Robin |
From: Christiaan P. <cep...@go...> - 2008-03-05 17:04:16
|
Hi guys, I've been wanting to do something similar as well. Create a figure from other figures. The function accepts a list of figures, and according to the ratio (rows to columns) creates a bigger figure of appropriate size and 'copies' the axes into the new figure. I calculate the positions and size of the subplots in the new figure proportionately (ie. a value between 0 and 1), and then do a ax.set_position. This seems to be broken somehow, the axes still think the size of the figure they're in is the original figure's size. Even though I already moved them over to the new larger figure. I've tried to hack this by simply passing in values bigger then 1, but I can't get it to work. If I don't make the new figure bigger everything works, though the labels get a bit cramped then. If someone can have a look and give me some advise it would be very appreciated. Regards, Christiaan _________________________ import math from matplotlib.figure import * def multisubplot(figures=[], ratio=1.0, wspace=0.0, hspace=0.0): fig = Figure() n = len(figures) if n < 1: fig.add_subplot(111) return fig # calculate number of rows and columns columns = int(math.ceil(sqrt(float(n)/(ratio)))) rows = int(math.ceil(float(n)/float(columns))) # resize the new figure w_inches = figures[0].get_size_inches()[0]*(columns) h_inches = figures[0].get_size_inches()[1]*(rows) fig.set_size_inches(w_inches, h_inches, forward=True) print fig.get_size_inches() # calculate the spacing wspace = wspace / (float(columns)) hspace = hspace / (float(rows)) # calculate the l,b,w,h of all subplots width = 1/float(columns) - wspace height = 1/float(rows) - hspace positions = [] for i in range(rows): for j in range(columns): positions.append([(j)*(width + wspace) + wspace/2, \ (rows-i-1)*(height + hspace) + hspace/2 , \ width, height]) # hack broken axes scaling for pos in positions: print '' #pos[0] = pos[0] * (columns) #pos[1] = pos[1] * (rows) #pos[2] = pos[2] * (columns) #pos[3] = pos[3] * (rows) print n print 'columns', columns, 'rows', rows print 'wspace', wspace, 'hspace', hspace print 'width', width, 'height', height for pos in positions: print pos for i in range(rows): for j in range(columns): x = i*(columns) + j if x < n: for ax in figures[x].axes: figures[x].delaxes(ax) ax.set_figure(fig) fig.add_axes(ax) ax.set_position(positions[x]) return fig #create some figures to pass to our function pl = [] for i in range(13): fig = Figure() ax = fig.add_subplot(111) ax.plot([1,math.sin(i),2]) pl.append(fig) figsub = multisubplot(pl,ratio=1, wspace=0.1, hspace=0.1) _______________________________-- On 18/02/2008, Robin <ro...@gm...> wrote: > > Thanks very much for all your help. > > > On Feb 18, 2008 3:44 PM, John Hunter <jd...@gm...> wrote: > > It's not that it isn't supported, it's just rarely used and so may > > have slowly broken over time. It is useful, so It would be worthwhile > > for us to fix it. Are you using 0.91.2 or svn? > > > I am using 0.91.2 at the moment (on Mac OS X - I think this was the > downloaded binary). I could build from svn if you think it would make > a difference. > > I guess for now I will use the function argument method, but I'm happy > to keep this code around and provide what feedback I can. > > I suspect that if the subplot geometry was set to autoupdate when the > window is resized as it is for a fresh subplot, then the overlapping > axes might go away after a window resize. The missing xticks is a bit > of a mystery though - they all seems to be there, just not shown. I > tried setting them visible and redrawing but no luck. > > Thanks again, > > > Robin > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by: Microsoft > Defy all challenges. Microsoft(R) Visual Studio 2008. > http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ > _______________________________________________ > Matplotlib-users mailing list > Mat...@li... > https://lists.sourceforge.net/lists/listinfo/matplotlib-users > |