first prototype
This commit is contained in:
4
zoetrope/__init__.py
Normal file
4
zoetrope/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
from .zoetrope import *
|
||||
|
||||
|
125
zoetrope/aniplot.py
Normal file
125
zoetrope/aniplot.py
Normal file
@ -0,0 +1,125 @@
|
||||
from functools import wraps
|
||||
from itertools import count
|
||||
|
||||
from matplotlib import pyplot as plt
|
||||
|
||||
from .contaxes import AxesContainer
|
||||
from .contplot import PlotContainer
|
||||
|
||||
from .mpltypes import is_plot_artist
|
||||
from .utils import iflatten, unseq
|
||||
|
||||
|
||||
class AniPlot:
|
||||
|
||||
def __init__(self, blit=True):
|
||||
self.blit = blit
|
||||
self.plots = set()
|
||||
self.axes = set()
|
||||
|
||||
# handle resizing the window
|
||||
fig = plt.gcf()
|
||||
fig.canvas.mpl_connect("draw_event", self.on_resize)
|
||||
|
||||
|
||||
def on_resize(self, event):
|
||||
self._save_bkgs()
|
||||
|
||||
|
||||
def __getattr__(self, name):
|
||||
attr = getattr(plt, name)
|
||||
|
||||
if not callable(attr):
|
||||
return attr
|
||||
|
||||
@wraps(attr)
|
||||
def wrapper(*args, **kwargs):
|
||||
res = attr(*args, **kwargs)
|
||||
|
||||
plots = set()
|
||||
for obj in iflatten(res):
|
||||
if is_plot_artist(obj):
|
||||
plots.add(obj)
|
||||
else:
|
||||
print(f"ignoring: {name}() -> {obj}")
|
||||
|
||||
if not plots:
|
||||
return res
|
||||
|
||||
ax = plt.gca()
|
||||
plots = [PlotContainer(i, ax) for i in plots]
|
||||
|
||||
fig = plt.gcf()
|
||||
ax = AxesContainer(ax, fig)
|
||||
|
||||
self.plots.update(plots)
|
||||
self.axes.add(ax)
|
||||
|
||||
return unseq(plots)
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def show(self):
|
||||
fig = plt.gcf()
|
||||
canvas = fig.canvas
|
||||
canvas.draw()
|
||||
|
||||
if self.blit:
|
||||
self._enable_animated_all()
|
||||
self._save_bkgs()
|
||||
|
||||
plt.show(block=False)
|
||||
|
||||
for i in count():
|
||||
yield i
|
||||
if self.blit:
|
||||
self._update_with_blit()
|
||||
else:
|
||||
canvas.draw()
|
||||
canvas.flush_events()
|
||||
|
||||
|
||||
def _update_with_blit(self):
|
||||
self._restore_bkgs()
|
||||
self._draw_all()
|
||||
self._blit_all()
|
||||
|
||||
|
||||
def _save_bkgs(self):
|
||||
for a in self.axes:
|
||||
a._save_bkg()
|
||||
|
||||
def _restore_bkgs(self):
|
||||
for a in self.axes:
|
||||
a._restore_bkg()
|
||||
|
||||
|
||||
def _draw_all(self):
|
||||
for p in self.plots:
|
||||
p._draw()
|
||||
|
||||
def _blit_all(self):
|
||||
for a in self.axes:
|
||||
a._blit()
|
||||
|
||||
|
||||
def _enable_animated_all(self):
|
||||
for p in self.plots:
|
||||
p._enable_animated()
|
||||
|
||||
def _disable_animated_all(self):
|
||||
for p in self.plots:
|
||||
p._disable_animated()
|
||||
|
||||
|
||||
def enable_blit(self):
|
||||
self.blit = True
|
||||
self._enable_animated_all()
|
||||
|
||||
def disable_blit(self):
|
||||
self.blit = False
|
||||
self._disable_animated_all()
|
||||
|
||||
|
||||
|
24
zoetrope/contaxes.py
Normal file
24
zoetrope/contaxes.py
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
class AxesContainer:
|
||||
|
||||
def __init__(self, ax, fig):
|
||||
self.ax = ax
|
||||
self.fig = fig
|
||||
self._bkg = None
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.ax)
|
||||
|
||||
|
||||
def _save_bkg(self):
|
||||
self._bkg = self.fig.canvas.copy_from_bbox(self.ax.bbox)
|
||||
|
||||
def _restore_bkg(self):
|
||||
if self._bkg:
|
||||
self.fig.canvas.restore_region(self._bkg)
|
||||
|
||||
def _blit(self):
|
||||
self.fig.canvas.blit(self.ax.bbox)
|
||||
|
||||
|
||||
|
27
zoetrope/contplot.py
Normal file
27
zoetrope/contplot.py
Normal file
@ -0,0 +1,27 @@
|
||||
|
||||
class PlotContainer:
|
||||
|
||||
def __init__(self, artist, ax):
|
||||
self.artist = artist
|
||||
self.ax = ax
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.artist)
|
||||
|
||||
|
||||
def set(self, *args):
|
||||
self.artist.set_data(*args)
|
||||
|
||||
|
||||
def _draw(self):
|
||||
self.ax.draw_artist(self.artist)
|
||||
|
||||
|
||||
def _enable_animated(self):
|
||||
self.artist.set_animated(True)
|
||||
|
||||
def _disable_animated(self):
|
||||
self.artist.set_animated(False)
|
||||
|
||||
|
||||
|
15
zoetrope/mpltypes.py
Normal file
15
zoetrope/mpltypes.py
Normal file
@ -0,0 +1,15 @@
|
||||
from matplotlib.artist import Artist
|
||||
from matplotlib.axes import Axes
|
||||
|
||||
|
||||
def is_plot_artist(obj):
|
||||
return is_artist(obj) and not is_axis_artist(obj)
|
||||
|
||||
def is_artist(obj):
|
||||
return isinstance(obj, Artist)
|
||||
|
||||
def is_axis_artist(obj):
|
||||
return isinstance(obj, Axes)
|
||||
|
||||
|
||||
|
33
zoetrope/utils.py
Normal file
33
zoetrope/utils.py
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
def unseq(seq):
|
||||
return seq[0] if len(seq) == 1 else seq
|
||||
|
||||
|
||||
|
||||
#def flatten(obj):
|
||||
# try:
|
||||
# iter(obj)
|
||||
# except TypeError:
|
||||
# return [obj]
|
||||
# else:
|
||||
# res = []
|
||||
# for i in obj:
|
||||
# res.extend(flatten(i))
|
||||
# return res
|
||||
|
||||
|
||||
|
||||
def flatten(obj):
|
||||
return list(iflatten(obj))
|
||||
|
||||
def iflatten(obj):
|
||||
try:
|
||||
iterator = iter(obj)
|
||||
except TypeError:
|
||||
yield obj
|
||||
else:
|
||||
for item in iterator:
|
||||
yield from iflatten(item)
|
||||
|
||||
|
||||
|
7
zoetrope/zoetrope.py
Normal file
7
zoetrope/zoetrope.py
Normal file
@ -0,0 +1,7 @@
|
||||
from .aniplot import AniPlot
|
||||
|
||||
|
||||
aniplot = AniPlot()
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user