This commit is contained in:
Sebastien Bourdeauducq 2020-08-10 18:56:08 +08:00
parent 2851be4709
commit c90744322c
3 changed files with 135 additions and 135 deletions

104
gui.py
View File

@ -1,83 +1,67 @@
import asyncio
import os import os
import logging import sys
import subprocess
import time
import numpy as np import numpy as np
from quamash import QEventLoop, QtWidgets
import pyqtgraph as pg
from sipyco.pipe_ipc import AsyncioChildComm
from sipyco import pyon from sipyco import pyon
class SpectrogramWidget(pg.PlotWidget): # env QT_QPA_PLATFORM=wayland python gui.py
def __init__(self, block_size=4096):
super(SpectrogramWidget, self).__init__()
self.block_size = block_size 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
self.img = pg.ImageItem() def get_address(self):
self.addItem(self.img) return "{},{}".format(self.c_rfd, self.c_wfd)
self.img_array = np.zeros((100, block_size)) def read(self, n):
return self.rf.read(n)
pos = np.array([0., 1., 0.5, 0.25, 0.75]) def readline(self):
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) return self.rf.readline()
cmap = pg.ColorMap(pos, color)
lut = cmap.getLookupTable(0.0, 1.0, 256)
self.img.setLookupTable(lut) def write(self, data):
self.img.setLevels([-50,40]) return self.wf.write(data)
self.show() def write_pyon(self, obj):
self.write(pyon.encode(obj).encode() + b"\n")
def update(self, block): def close(self):
self.img_array = np.roll(self.img_array, -1, 0) self.rf.close()
self.img_array[-1:] = block self.wf.close()
self.img.setImage(self.img_array, autoLevels=True) 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)
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(): def main():
app = QtWidgets.QApplication([]) gui = ParentComm()
loop = QEventLoop(app)
asyncio.set_event_loop(loop)
try: try:
ipc = IPCClient(os.getenv("NOPTICA2_IPC")) gui.create_subprocess([sys.executable, os.path.join(os.path.dirname(os.path.abspath(__file__)), "gui_impl.py")])
loop.run_until_complete(ipc.connect()) for i in range(600):
try: obj = {"action": "update", "data": np.random.normal(size=4096)}
main_widget = SpectrogramWidget() gui.write_pyon(obj)
main_widget.show() time.sleep(1/60)
ipc.set_close_cb(main_widget.close) obj = {"action": "terminate"}
asyncio.ensure_future(ipc.listen(main_widget)) gui.write_pyon(obj)
loop.run_forever()
finally: finally:
ipc.close() gui.close()
finally:
loop.close()
if __name__ == "__main__": if __name__ == "__main__":

84
gui_impl.py Normal file
View File

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

View File

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