first prototype

This commit is contained in:
2021-09-15 15:29:10 +02:00
parent e90f013e54
commit e8c4630ffa
8 changed files with 283 additions and 0 deletions

4
zoetrope/__init__.py Normal file
View File

@ -0,0 +1,4 @@
from .zoetrope import *

125
zoetrope/aniplot.py Normal file
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,7 @@
from .aniplot import AniPlot
aniplot = AniPlot()