def do_GET(self): self.thread = thread = OSCThread() thread.daemon = True thread.start() actors = list() is_item1 = True is_item2 = True is_item3 = True def setPositions(): for ix, item in enumerate(actors): item.setPos(0, ix * 6) def scale_data(data, ix, max_items): scale = 254 / max_items * ix return [value / max_items + scale for value in data] try: self.path = re.sub('[^.a-zA-Z0-9]', "", str(self.path)) if self.path == "" or self.path == None or self.path[:1] == ".": return if self.path.endswith(".html"): f = open(curdir + sep + self.path) self.send_response(200) self.send_header('Content-type', 'text/html') self.end_headers() self.wfile.write(f.read()) f.close() elif self.path.endswith(".mjpeg"): data_points = 1000 self.send_response(200) plot_data1 = data = deque([0] * data_points) plot_data2 = data = deque([0] * data_points) plot_data3 = data = deque([0] * data_points) plt = PlotWidget(title="<h1>EKG</h1>", name="Merle") plt.hide() plotItem1 = pg.PlotCurveItem(pen=pg.mkPen('r', width=2), name="bjoern") plotItem2 = pg.PlotCurveItem(pen=pg.mkPen('g', width=2), name="merle") plotItem3 = pg.PlotCurveItem(pen=pg.mkPen('b', width=2), name="uwe") print type(plotItem1) pen = pg.mkPen(254, 254, 254) plotItem1.setShadowPen(pen=pen, width=6, cosmetic=True) plotItem2.setShadowPen(pen=pen, width=6, cosmetic=True) plotItem3.setShadowPen(pen=pen, width=6, cosmetic=True) actors.append(plotItem1) actors.append(plotItem2) actors.append(plotItem3) plotItem1.setPos(0, 0 * 6) plotItem2.setPos(0, 1 * 6) plotItem3.setPos(0, 2 * 6) plt.addItem(plotItem1) plt.addItem(plotItem2) plt.addItem(plotItem3) plt.setLabel('left', "<h2>Amplitude</h2>") plt.setLabel('bottom', "<h2>Time</h2>") plt.showGrid(True, True) ba = plt.getAxis("bottom") bl = plt.getAxis("left") ba.setTicks([]) bl.setTicks([]) plt.setYRange(0, 254) self.wfile.write( "Content-Type: multipart/x-mixed-replace; boundary=--aaboundary" ) self.wfile.write("\r\n\r\n") plt.resize(1280, 720) while 1: while 1: try: osc_address, args = queue.get_nowait() except Queue.Empty: break value = args[0] if osc_address == "/bjoern/ekg": plot_data1.append(value) plot_data1.popleft() try: plotItem1.setData(y=np.array( scale_data(plot_data1, actors.index(plotItem1), len(actors))), clear=True) except ValueError: pass elif osc_address == "/merle/ekg": plot_data2.append(value) plot_data2.popleft() try: plotItem2.setData(y=np.array( scale_data(plot_data2, actors.index(plotItem2), len(actors))), clear=True) except ValueError: pass elif osc_address == "/uwe/ekg": plot_data3.append(value) plot_data3.popleft() try: plotItem3.setData(y=np.array( scale_data(plot_data3, actors.index(plotItem3), len(actors))), clear=True) except ValueError: pass elif osc_address == "/plot/uwe": if value == 1 and is_item3 == False: print "uwe on" plt.addItem(plotItem3) is_item3 = True actors.append(plotItem3) setPositions() elif value == 0 and is_item3 == True: print "uwe off" plt.removeItem(plotItem3) is_item3 = False actors.remove(plotItem3) setPositions() elif osc_address == "/plot/merle": if value == 1 and is_item2 == False: print "merle on" plt.addItem(plotItem2) is_item2 = True actors.append(plotItem2) setPositions() elif value == 0 and is_item2 == True: print "merle off" plt.removeItem(plotItem2) is_item2 = False actors.remove(plotItem2) setPositions() elif osc_address == "/plot/bjoern": if value == 1 and is_item1 == False: print "bjoern on" plt.addItem(plotItem1) is_item1 = True actors.append(plotItem1) setPositions() elif value == 0 and is_item1 == True: print "bjoern off" plt.removeItem(plotItem1) is_item1 = False actors.remove(plotItem1) setPositions() exporter = pg.exporters.ImageExporter.ImageExporter( plt.plotItem) img = exporter.export("tmpfile", True) buffer = QBuffer() buffer.open(QIODevice.WriteOnly) img.save(buffer, "JPG", 100) JpegData = buffer.data() del buffer self.wfile.write( "--aaboundary\r\nContent-Type: image/jpeg\r\nContent-length: %d\r\n\r\n%s\r\n\r\n\r\n" % (len(JpegData), JpegData)) elif self.path.endswith(".jpeg"): f = open(curdir + sep + self.path) self.send_response(200) self.send_header('Content-type', 'image/jpeg') self.end_headers() self.wfile.write(f.read()) f.close() return except (KeyboardInterrupt, SystemError): thread.running = False thread.join() except IOError: self.send_error(404, 'File Not Found: %s' % self.path)
class QtPlotView(QtControl, ProxyPlotView): __weakref__ = None widget = Typed(PlotWidget) _views = List() _colors = List(default=['r', 'g', 'b']) def create_widget(self): self.widget = PlotWidget(self.parent_widget(), background='w') def init_widget(self): super(QtPlotView, self).init_widget() d = self.declaration #self.widget.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) self.set_data(d.data) self.set_antialiasing(d.antialiasing) self.set_aspect_locked(d.aspect_locked) self.set_axis_scales(d.axis_scales) self.set_labels(d.labels) self.widget.showGrid(d.grid[0], d.grid[1], d.grid_alpha) d.setup(self.widget) def set_title(self, title): self.set_labels(self.declaration.labels) def set_labels(self, labels): if self.declaration.title: labels['title'] = self.declaration.title self.widget.setLabels(**labels) def set_antialiasing(self,enabled): self.widget.setAntialiasing(enabled) def set_aspect_locked(self,locked): self.widget.setAspectLocked(locked) def set_axis_scales(self,scales): if not scales: return for k, v in scales.items(): if k in self.widget.plotItem.axes: self.widget.plotItem.axes[k]['item'].setScale(v) def set_data(self, data): self.widget.clear() if not data: return if isinstance(data, (list, tuple)) and isinstance(data[0], GraphicsObject): self._set_graphic_items(data) else: self._set_numeric_data(data) def _set_graphic_items(self, items): self.widget.clear() for item in items: self.widget.addItem(item) def _set_numeric_data(self,data): self.widget.plotItem.clear() if self._views: for view in self._views: view.clear() views = [] i = 0 if self.declaration.multi_axis: for i,plot in enumerate(data): if i>3: break if 'pen' not in plot: plot['pen'] = self._colors[i] if i>0: view = ViewBox() views.append(view) self.widget.plotItem.scene().addItem(view) if i==1: axis = self.widget.plotItem.getAxis('right') elif i>1: axis = AxisItem('right') axis.setZValue(-10000) self.widget.plotItem.layout.addItem(axis,2,3) axis.linkToView(view) view.setXLink(self.widget.plotItem) view.addItem(PlotCurveItem(**plot)) else: #view.setYLink(self.widget.plotItem) self.widget.plot(**plot) if i>0: def syncViews(): for v in views: v.setGeometry(self.widget.plotItem.vb.sceneBoundingRect()) v.linkedViewChanged(self.widget.plotItem.vb,v.XAxis) syncViews() self.widget.plotItem.vb.sigResized.connect(syncViews) self._views = views
class QtPlotView(QtControl, ProxyPlotView): __weakref__ = None widget = Typed(PlotWidget) _views = List() _colors = List(default=['r', 'g', 'b']) def create_widget(self): self.widget = PlotWidget(self.parent_widget(), background='w') def init_widget(self): super(QtPlotView, self).init_widget() d = self.declaration #self.widget.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding) self.set_data(d.data) self.set_antialiasing(d.antialiasing) self.set_aspect_locked(d.aspect_locked) self.set_axis_scales(d.axis_scales) self.set_labels(d.labels) self.widget.showGrid(d.grid[0], d.grid[1], d.grid_alpha) d.setup(self.widget) def set_title(self, title): self.set_labels(self.declaration.labels) def set_labels(self, labels): if self.declaration.title: labels['title'] = self.declaration.title self.widget.setLabels(**labels) def set_antialiasing(self, enabled): self.widget.setAntialiasing(enabled) def set_aspect_locked(self, locked): self.widget.setAspectLocked(locked) def set_axis_scales(self, scales): if not scales: return for k, v in scales.items(): if k in self.widget.plotItem.axes: self.widget.plotItem.axes[k]['item'].setScale(v) def set_grid(self, grid): d = self.declaration self.widget.showGrid(grid[0], grid[1], d.grid_alpha) def set_grid_alpha(self, alpha): d = self.declaration self.widget.showGrid(d.grid[0], d.grid[1], alpha) def set_data(self, data): self.widget.clear() if not data: return if isinstance(data, (list, tuple)) and \ isinstance(data[0], GraphicsObject): self._set_graphic_items(data) else: self._set_numeric_data(data) def _set_graphic_items(self, items): self.widget.clear() for item in items: self.widget.addItem(item) def _set_numeric_data(self, data): self.widget.plotItem.clear() if self._views: for view in self._views: view.clear() views = [] i = 0 if self.declaration.multi_axis: for i, plot in enumerate(data): if i > 3: break if 'pen' not in plot: plot['pen'] = self._colors[i] if i > 0: view = ViewBox() views.append(view) self.widget.plotItem.scene().addItem(view) if i == 1: axis = self.widget.plotItem.getAxis('right') elif i > 1: axis = AxisItem('right') axis.setZValue(-10000) self.widget.plotItem.layout.addItem(axis, 2, 3) axis.linkToView(view) view.setXLink(self.widget.plotItem) view.addItem(PlotCurveItem(**plot)) else: self.widget.plot(**plot) if i > 0: def syncViews(): for v in views: v.setGeometry(self.widget.plotItem.vb.sceneBoundingRect()) v.linkedViewChanged(self.widget.plotItem.vb, v.XAxis) syncViews() self.widget.plotItem.vb.sigResized.connect(syncViews) self._views = views
class EkgPlotWidget(QMainWindow): def __init__(self, args, parent=None): self.args = args QMainWindow.__init__(self, parent) self.mcount = 0 self.osc_sock = QUdpSocket(self) logger.info("osc bind localhost %d", self.args.client_port) self.osc_sock.bind(QHostAddress(self.args.client_host), self.args.client_port) self.osc_sock.readyRead.connect(self.got_message) self.osc_sock.error.connect(self.handle_osc_error) self.subscribe() self.plot_widget = PlotWidget() self.setCentralWidget(self.plot_widget) self.resize(args.client_width, args.client_height) colors = ["r", "g", "b"] self.active_actors = list() self.actors = dict() self.max_value = 255 actor_names = ["merle", "uwe", "bjoern"] self.max_actors = len(actor_names) self.actor_height = self.max_value / self.max_actors self.fps = 12.5 self.num_data = 100 self.plot_widget.showGrid(False, False) self.plot_widget.setYRange(0, 255) self.plot_widget.setXRange(0, self.num_data) self.plot_widget.resize(args.client_width, args.client_height) bottom_axis = self.plot_widget.getAxis("bottom") left_axis = self.plot_widget.getAxis("left") bottom_axis.setTicks([]) left_axis.setTicks([]) bottom_axis.hide() left_axis.hide() for ix, (actor_name, color) in enumerate(zip(actor_names, colors)): self.add_actor(actor_name, self.num_data, color, ix, self.max_actors, self.actor_height) self.set_positions() self.ekg_regex = re.compile("^/(.*?)/ekg$") self.heartbeat_regex = re.compile("^/(.*?)/heartbeat$") self.timer = QtCore.QTimer() self.timer.timeout.connect(self.render_image) self.timer.start(50) def subscribe(self): logger.info("subscribe") msg = OSCMessage("/subscribe") msg.appendTypedArg(self.args.client_host, "s") msg.appendTypedArg(self.args.client_port, "i") msg.appendTypedArg(self.args.authenticate, "s") if self.args.subscriber_label is not None: msg.appendTypedArg(self.args.subscriber_label, "s") self.osc_sock.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress(self.args.chaosc_host), self.args.chaosc_port) def unsubscribe(self): logger.info("unsubscribe") msg = OSCMessage("/unsubscribe") msg.appendTypedArg(self.args.client_host, "s") msg.appendTypedArg(self.args.client_port, "i") msg.appendTypedArg(self.args.authenticate, "s") self.osc_sock.writeDatagram(QByteArray(msg.encode_osc()), QHostAddress(self.args.chaosc_host), self.args.chaosc_port) def handle_osc_error(self, error): logger.info("osc socket error %d", error) def closeEvent(self, event): logger.info("closeEvent %r", event) self.unsubscribe() event.accept() def pubdir(self): return os.path.dirname(os.path.abspath(__file__)) def add_actor(self, actor_name, num_data, color, ix, max_actors, actor_height): actor_obj = Actor(actor_name, num_data, color, ix, max_actors, actor_height) self.actors[actor_name] = actor_obj self.plot_widget.addItem(actor_obj.plotItem) self.plot_widget.addItem(actor_obj.plotPoint) self.active_actors.append(actor_obj) def set_positions(self): for ix, actor_obj in enumerate(self.active_actors): actor_obj.plotItem.setPos(0, ix * 2) actor_obj.plotPoint.setPos(0, ix * 2) def active_actor_count(self): return self.max_actors def update(self, osc_address, args): res = self.ekg_regex.match(osc_address) if res: self.mcount += 1 actor_name = res.group(1) actor_obj = self.actors[actor_name] actor_obj.add_value(args[0]) logger.info("actor: %r, %r", actor_name, args) def render_image(self): for actor_obj in self.active_actors: actor_obj.add_value(actor_obj.osci.next()) actor_obj.render() @QtCore.pyqtSlot() def render_image(self): for actor_obj in self.active_actors: actor_obj.render() print self.mcount def got_message(self): while self.osc_sock.hasPendingDatagrams(): data, address, port = self.osc_sock.readDatagram(self.osc_sock.pendingDatagramSize()) try: osc_address, typetags, args = decode_osc(data, 0, len(data)) self.update(osc_address, args) except ValueError, error: logger.exception(error)