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

48
run.py Executable file
View File

@ -0,0 +1,48 @@
#!/usr/bin/env python3
from time import sleep
import numpy as np
from zoetrope import aniplot as plt
def noise(arr):
rand = np.random.random(arr.shape) - 0.5
return arr * rand
x = np.arange(0.0, 2.0, 0.01)
y = 1 + np.sin(2 * np.pi * x)
xdim = ydim = 10
img = np.arange(0, xdim *ydim, 1).reshape(xdim, ydim)
plt.subplot(121)
pln1 = plt.plot(x, noise(y)+1)
pln2 = plt.plot(x, noise(y)+2)
pln3, pln4 = plt.plot(x, noise(y)+3, x, noise(y)+4)
plt.subplot(122)
pimg = plt.imshow(noise(img))
plt.show()
for i in plt.show():
print(i)
pln1.set(x, noise(y)+1)
pln2.set(x, noise(y)+2)
pln3.set(x, noise(y)+3)
pln4.set(x, noise(y)+4)
pimg.set(noise(img))
# if i % 500 == 250:
# plt.disable_blit()
# if i % 500 == 350:
# plt.enable_blit()

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()