first prototype
This commit is contained in:
48
run.py
Executable file
48
run.py
Executable 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
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