Skip to content
This repository


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Script that wraps (haunts) objects and tracks all changes to them, the matplotlib part is not useful (espeacially since pickling support is there or almost there), but its a funny hack so I keep it around.

branch: master

Fetching latest commit…

Cannot retrieve the latest commit at this time


Please note that this is a grown code and was not cleaned up at all, its more a
proof of concept and I am not even sure if the concept is not nonsense...
however, it works for me and if you should be seriously interested it, notify me
and I will work a bit on cleaning it.

This is a script which wraps itself around an arbitrary python object and then
tracks all things done with it (not internal things). This list of things
done with it can be saved with pickle even if the object itself cannot be saved
easily, and also provides a complete history of what is done with the object
in what order.

These wrapped objects are called Haunted here...

    o There are some smaller things that would not be tracked, but for cleanly
        written object orientated code that should be almost nothing.
        (For example if a wrapped object inside a function call passes one of
        its attributes out, so that it can be changed there lateron -- it does
        not matter if it would be immidiatly, as then )
    o The is operator will fail if there is a not haunted version around, this
        _could_ happen, but should be mostly avoided by not hindering execution
        if there is a function call in progress which is tracked.

For Matplotlib

The pyplot module provides some extra functionality (savesession, figure,
loadfigure) on top of matpltlib.pyplot which it extends though you only need to
use it for figure creation.
Also the resulting figure objects have some extra attributes:
    o savesession (save figure to file)
    o loadsession (load figure from file, should be possible to combine figures
    o haunt (Can be used to track complex items that cannot be simply passed
        in tothe figure and then saved, see Axes3D example.)
    o get_history (returns the history that was used to create the figure, can
        be edited, but needs to be loaded into a new figure by hand to take
Note that these are not visible in IPythons tab completion because the __dict__
and __members__ are overriden to be the figures.

This is sufficient for my purpose of opening a bit more flexible version of
images done of parameter scans. I set it up for double click to open and a
second option for opening in an IPython shell to be editable... (see scripts and, even if they are hacks :))

Some details

For the most part the script seems to work fine. It wills tore quite a bit of
extra things, so if you move around in a figure with the mouse and then save it,
you will get bloated figures. While it tries to discard some duplicate set events
while saving (ie. resizing the figure multiple times), this will most likely
not work for many things.
While saving all things that are not posisble to be pickled and everything
depending on this will be discarted, this is usually not a problem though, but
the check for not pickable input should be set earlier to allow tracking
the consecutive calls which are right now discareted.
As said, during a wrapped function call, no more action are actually tracked
and only the real objects passed to avoid bloating, this should typically be no
problem unless in some weird program designs.
One thing is, that its probably better to do such wrapping/haunting by
subclassing (where possible) instead of an extra layer around the object.


I have not tried many things with this program, but Axes3D toolkit is possible.
However it seems that the mouse events to change the view angle/distance are
not stored for a 3D Axes, which I guess is because of unpickable objects, and
could maybe be fixed by checking earlier if it is pickable or not.

Axes3D (and other objects that may otherwise not save) can be used by a script
such as this:

from mpl_toolkits.mplot3d import Axes3D
import haunt.pyplot

fig = haunt.pyplot.figure()
Axes3D = fig.haunt(Axes3D) # now this Axes3D class is tracked by the figure

# As it is tracked, its initialization is tracked too (and the figure is passed
# into it as the normal figure object and nothing weird (actually probably only
# important because of a single assert in my version of matplotlib which uses
# the is operator)
ax = Axes3D(fig)

# ax is returned by a haunted/wrapped call, so it is wrapped too, you can now
# do everything fine with it:
ax.plot3D(np.random.random(100), np.random.random(100), np.random.random(100), ',')

Something went wrong with that request. Please try again.