1"""
2============
3Oscilloscope
4============
5
6Emulates an oscilloscope.
7"""
8
9import numpy as np
10from matplotlib.lines import Line2D
11import matplotlib.pyplot as plt
12import matplotlib.animation as animation
13
14
15class Scope(object):
16    def __init__(self, ax, maxt=2, dt=0.02):
17        self.ax = ax
18        self.dt = dt
19        self.maxt = maxt
20        self.tdata = [0]
21        self.ydata = [0]
22        self.line = Line2D(self.tdata, self.ydata)
23        self.ax.add_line(self.line)
24        self.ax.set_ylim(-.1, 1.1)
25        self.ax.set_xlim(0, self.maxt)
26
27    def update(self, y):
28        lastt = self.tdata[-1]
29        if lastt > self.tdata[0] + self.maxt:  # reset the arrays
30            self.tdata = [self.tdata[-1]]
31            self.ydata = [self.ydata[-1]]
32            self.ax.set_xlim(self.tdata[0], self.tdata[0] + self.maxt)
33            self.ax.figure.canvas.draw()
34
35        t = self.tdata[-1] + self.dt
36        self.tdata.append(t)
37        self.ydata.append(y)
38        self.line.set_data(self.tdata, self.ydata)
39        return self.line,
40
41
42def emitter(p=0.03):
43    'return a random value with probability p, else 0'
44    while True:
45        v = np.random.rand(1)
46        if v > p:
47            yield 0.
48        else:
49            yield np.random.rand(1)
50
51# Fixing random state for reproducibility
52np.random.seed(19680801)
53
54
55fig, ax = plt.subplots()
56scope = Scope(ax)
57
58# pass a generator in "emitter" to produce data for the update func
59ani = animation.FuncAnimation(fig, scope.update, emitter, interval=10,
60                              blit=True)
61
62plt.show()
63