From c90744322c8e6d5e72fde562bcc28ac318ba31e5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 10 Aug 2020 18:56:08 +0800 Subject: [PATCH] cleanup --- gui.py | 118 +++++++++++++++++++++++----------------------------- gui_impl.py | 84 +++++++++++++++++++++++++++++++++++++ gui_test.py | 68 ------------------------------ 3 files changed, 135 insertions(+), 135 deletions(-) create mode 100644 gui_impl.py delete mode 100644 gui_test.py diff --git a/gui.py b/gui.py index 08a6bbb..f4f8af2 100644 --- a/gui.py +++ b/gui.py @@ -1,83 +1,67 @@ -import asyncio import os -import logging +import sys +import subprocess +import time import numpy as np -from quamash import QEventLoop, QtWidgets -import pyqtgraph as pg -from sipyco.pipe_ipc import AsyncioChildComm from sipyco import pyon - - -class SpectrogramWidget(pg.PlotWidget): - def __init__(self, block_size=4096): - super(SpectrogramWidget, self).__init__() - - self.block_size = block_size - - self.img = pg.ImageItem() - self.addItem(self.img) - - self.img_array = np.zeros((100, block_size)) - - pos = np.array([0., 1., 0.5, 0.25, 0.75]) - color = np.array([[0,255,255,255], [255,255,0,255], [0,0,0,255], (0, 0, 255, 255), (255, 0, 0, 255)], dtype=np.ubyte) - cmap = pg.ColorMap(pos, color) - lut = cmap.getLookupTable(0.0, 1.0, 256) - - self.img.setLookupTable(lut) - self.img.setLevels([-50,40]) - - self.show() - - def update(self, block): - self.img_array = np.roll(self.img_array, -1, 0) - self.img_array[-1:] = block - self.img.setImage(self.img_array, autoLevels=True) -class IPCClient(AsyncioChildComm): - def set_close_cb(self, close_cb): - self.close_cb = close_cb +# env QT_QPA_PLATFORM=wayland python gui.py - async def read_pyon(self): - line = await self.readline() - return pyon.decode(line.decode()) +class ParentComm: + def __init__(self): + self.c_rfd, self.p_wfd = os.pipe() + self.p_rfd, self.c_wfd = os.pipe() + self.rf = open(int(self.p_rfd), "rb", 0) + self.wf = open(int(self.p_wfd), "wb", 0) + self.process = None + + def get_address(self): + return "{},{}".format(self.c_rfd, self.c_wfd) + + def read(self, n): + return self.rf.read(n) + + def readline(self): + return self.rf.readline() + + def write(self, data): + return self.wf.write(data) + + def write_pyon(self, obj): + self.write(pyon.encode(obj).encode() + b"\n") + + def close(self): + self.rf.close() + self.wf.close() + if self.process is not None: + self.process.wait() + + def create_subprocess(self, *args): + env = os.environ.copy() + env["PYTHONUNBUFFERED"] = "1" + env["NOPTICA2_IPC"] = self.get_address() + self.process = subprocess.Popen( + *args, pass_fds={self.c_rfd, self.c_wfd}, + env=env) + os.close(self.c_rfd) + os.close(self.c_wfd) - async def listen(self, spectrogram): - while True: - obj = await self.read_pyon() - try: - action = obj["action"] - if action == "update": - spectrogram.update(obj["data"]) - if action == "terminate": - self.close_cb() - return - except: - logging.error("error processing parent message", - exc_info=True) - self.close_cb() def main(): - app = QtWidgets.QApplication([]) - loop = QEventLoop(app) - asyncio.set_event_loop(loop) - + gui = ParentComm() try: - ipc = IPCClient(os.getenv("NOPTICA2_IPC")) - loop.run_until_complete(ipc.connect()) - try: - main_widget = SpectrogramWidget() - main_widget.show() - ipc.set_close_cb(main_widget.close) - asyncio.ensure_future(ipc.listen(main_widget)) - loop.run_forever() - finally: - ipc.close() + gui.create_subprocess([sys.executable, os.path.join(os.path.dirname(os.path.abspath(__file__)), "gui_impl.py")]) + for i in range(600): + obj = {"action": "update", "data": np.random.normal(size=4096)} + gui.write_pyon(obj) + time.sleep(1/60) + obj = {"action": "terminate"} + gui.write_pyon(obj) finally: - loop.close() + gui.close() if __name__ == "__main__": diff --git a/gui_impl.py b/gui_impl.py new file mode 100644 index 0000000..08a6bbb --- /dev/null +++ b/gui_impl.py @@ -0,0 +1,84 @@ +import asyncio +import os +import logging + +import numpy as np +from quamash import QEventLoop, QtWidgets +import pyqtgraph as pg +from sipyco.pipe_ipc import AsyncioChildComm +from sipyco import pyon + + +class SpectrogramWidget(pg.PlotWidget): + def __init__(self, block_size=4096): + super(SpectrogramWidget, self).__init__() + + self.block_size = block_size + + self.img = pg.ImageItem() + self.addItem(self.img) + + self.img_array = np.zeros((100, block_size)) + + pos = np.array([0., 1., 0.5, 0.25, 0.75]) + color = np.array([[0,255,255,255], [255,255,0,255], [0,0,0,255], (0, 0, 255, 255), (255, 0, 0, 255)], dtype=np.ubyte) + cmap = pg.ColorMap(pos, color) + lut = cmap.getLookupTable(0.0, 1.0, 256) + + self.img.setLookupTable(lut) + self.img.setLevels([-50,40]) + + self.show() + + def update(self, block): + self.img_array = np.roll(self.img_array, -1, 0) + self.img_array[-1:] = block + self.img.setImage(self.img_array, autoLevels=True) + + +class IPCClient(AsyncioChildComm): + def set_close_cb(self, close_cb): + self.close_cb = close_cb + + async def read_pyon(self): + line = await self.readline() + return pyon.decode(line.decode()) + + async def listen(self, spectrogram): + while True: + obj = await self.read_pyon() + try: + action = obj["action"] + if action == "update": + spectrogram.update(obj["data"]) + if action == "terminate": + self.close_cb() + return + except: + logging.error("error processing parent message", + exc_info=True) + self.close_cb() + + +def main(): + app = QtWidgets.QApplication([]) + loop = QEventLoop(app) + asyncio.set_event_loop(loop) + + try: + ipc = IPCClient(os.getenv("NOPTICA2_IPC")) + loop.run_until_complete(ipc.connect()) + try: + main_widget = SpectrogramWidget() + main_widget.show() + ipc.set_close_cb(main_widget.close) + asyncio.ensure_future(ipc.listen(main_widget)) + loop.run_forever() + finally: + ipc.close() + finally: + loop.close() + + +if __name__ == "__main__": + main() diff --git a/gui_test.py b/gui_test.py deleted file mode 100644 index e56b6a3..0000000 --- a/gui_test.py +++ /dev/null @@ -1,68 +0,0 @@ -import os -import sys -import subprocess -import time - -import numpy as np -from sipyco import pyon - - -# env QT_QPA_PLATFORM=wayland python gui_test.py - -class ParentComm: - def __init__(self): - self.c_rfd, self.p_wfd = os.pipe() - self.p_rfd, self.c_wfd = os.pipe() - self.rf = open(int(self.p_rfd), "rb", 0) - self.wf = open(int(self.p_wfd), "wb", 0) - self.process = None - - def get_address(self): - return "{},{}".format(self.c_rfd, self.c_wfd) - - def read(self, n): - return self.rf.read(n) - - def readline(self): - return self.rf.readline() - - def write(self, data): - return self.wf.write(data) - - def write_pyon(self, obj): - self.write(pyon.encode(obj).encode() + b"\n") - - def close(self): - self.rf.close() - self.wf.close() - if self.process is not None: - self.process.wait() - - def create_subprocess(self, *args): - env = os.environ.copy() - env["PYTHONUNBUFFERED"] = "1" - env["NOPTICA2_IPC"] = self.get_address() - self.process = subprocess.Popen( - *args, pass_fds={self.c_rfd, self.c_wfd}, - env=env) - os.close(self.c_rfd) - os.close(self.c_wfd) - - - -def main(): - gui = ParentComm() - try: - gui.create_subprocess([sys.executable, "gui.py"]) - for i in range(600): - obj = {"action": "update", "data": np.random.normal(size=4096)} - gui.write_pyon(obj) - time.sleep(1/60) - obj = {"action": "terminate"} - gui.write_pyon(obj) - finally: - gui.close() - - -if __name__ == "__main__": - main()