6

I have several lines, bars and artists in one figure/axes. I would like to add different sets of components onto the original figure/axes. Is that possible to duplicate all the objects of the original figure/axes into another figure/axes without redraw everything by code?

One way will be remove all the new added components before drawing another set of components. However, if I want to put several axes into one figure, this will not work. Some discussion has been done here. But it copy/add all objects one by one, which is not better than redraw everything when there are many objects.

@Greg, thanks a lot for replying. If I just plot out data, it will be simple, just replot the data, or even copy some lines. However, this figures contain lots of artists, which can also be added by user through GUI interface, or bot by on-the-fly script, their types I might not known at runtime. And the plot are generated on-the-fly. Of course, I can try to copy all the data, record all the artists type, properties and replot them again. But it just too much and involved in modifying the software which generates those figures. Maybe I can loop through all possible objects do copy and add_xxx. But I hoope there will be a better way.

Thanks to @Joe Kington and his post: "add an axes instance to another figure".

I wrapped up a way to duplicate the axes and insert the axes into a subplot:

def test_pickleAxes():
    import pickle
    import numpy as npy
    x = npy.arange(0,4*npy.pi,0.2)
    y = npy.sin(x)

    fig, ax = plt.subplots()


    p = pickle.dumps(ax)
    ax2 = pickle.loads(p)

    ax.change_geometry(2,1,1)
    ax2.change_geometry(2,1,2)
    fig._axstack.add(fig._make_key(ax2), ax2)
    plt.show()

However, in most cases it is seems no better than blit so far. Why is that? Because the pickle of the axes is actually the pickle of the entire figure. When unpickle it, it will create a new figure and the loaded axes instance will associate with it. Even we managed to add the axes into the old figure. ax2 are still ONLY associate with the new figure. Thus when we try to interact with the old figure, the ax2 will not interact. Instead, if we scale/pan the new figure, ax2 in both figures will change. If we just save svg or pdf file, it seems a quite OK solution.

Still try to find a way to decouple the ax2 from new figure and make it couple with the old one.

Community
  • 1
  • 1
Wang
  • 7,250
  • 4
  • 35
  • 66
  • 1
    Couldn't you use a function to generate the figure with all the static stuff and then on top of that draw the individual things? – hitzg Jan 05 '15 at 09:19
  • I agree with @hitzg here: such a solution was previously posted [here](http://stackoverflow.com/questions/24682850/matplotlib-duplicate-figure-and-apply-changes). – Greg Jan 05 '15 at 10:55
  • In addition to what @Greg linked to, have a look at [How do I reuse plots in matplotlib?](http://stackoverflow.com/questions/10499482/how-do-i-reuse-plots-in-matplotlib) – Schorsch Jan 05 '15 at 14:04
  • As I mentioned some discussing has been down in the `so-called` duplicated previous question. But I doubt those guys wailing about `duplication` has read my post carefully. I am aware of that post. And I have already describe why it is a different question. – Wang Jan 06 '15 at 20:41
  • 1
    @Wang - It really does seem to be a duplicate from what you've described so far. If you're really wanting to avoid re-drawing the axes for performance reasons, then you should look into blitting. However, if you're not making a stand-alone application with matplotlib embedded, then that's probably not what you want. Can you give more background? Often people feel like they need to duplicate matplotlib axes when a much better solution is a bit of reorganization of their plotting functions. – Joe Kington Jan 06 '15 at 20:58
  • @joe Kington, thanks! As I said in my 2nd paragraph, I would like to avoid redraw everything both performance-wise reason and the reason I described below. Well, no matter what, this is about if I can duplicate a figure without redraw everything or loop-through all possible objects to duplicate them. Seems possible to `blit` in matplotlib: http://stackoverflow.com/questions/14844223/python-matplotlib-blit-to-axes-or-sides-of-the-figure – Wang Jan 06 '15 at 21:09
  • @Wang - How is it impossible to blit in matplotlib? Regardless, if you're going to want farther interaction with the plot afterwards, blitting isn't going to help. You need to reconstruct the full `axes` "stack". The linked question is one way of doing it. In my opinion, a better way would be to keep track of things in your code. That way you have more "semantic" control (e.g. "a plot of returns over time" vs. "a bar plot"). – Joe Kington Jan 06 '15 at 21:10
  • @Joe Kington , sorry, it should be `possible` :p. What I quote is your post anyway. I am going to ask for an example. Can you describe more detail about what the `further interaction` you mean? like plot new artists on it? scaling? – Wang Jan 06 '15 at 21:16
  • @Wang - Actually, I meant zoom/pan/scaling, etc. If you're adding more artists on top, you could get away with just blitting in some cases (e.g. no transparency), but not in every case. – Joe Kington Jan 06 '15 at 21:18
  • @Joe Kington, I found your another post (8955869), which described how to `canvas.blit`. It seems it will just snapshot the pixels of the axes to form background. Is it correct? If I can somehow link the interaction with the original figure. Then I can `canvas.copy_from_bbox` after each interaction and redo the `blit`. – Wang Jan 06 '15 at 21:38
  • 1
    There is also one additional way to copy everything: Use pickling. In most cases it won't be terribly fast, but it might fit your use case. See here for a simplified example: https://gist.github.com/joferkington/bbadb22da6949a285f95 – Joe Kington Jan 06 '15 at 21:39
  • @Wang - Yes, that's correct. That's certainly a reasonable (though possibly tedious) approach. – Joe Kington Jan 06 '15 at 21:40
  • @Joe Kington, if the `pickle of axes` works, it will be a fatanstic way to do it. It seems only experimental. And I do not know how to insert an unpickled axes into a subplot. It seems tricky. – Wang Jan 06 '15 at 22:11

0 Answers0