forked from M-Labs/artiq
master/gui: track last parameter changes
This commit is contained in:
parent
15b27a1d14
commit
3befafc4e0
|
@ -1,9 +1,10 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
|
import time
|
||||||
|
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
from artiq.gui.tools import Window
|
from artiq.gui.tools import Window, ListSyncer
|
||||||
from artiq.management.sync_struct import Subscriber
|
from artiq.management.sync_struct import Subscriber
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,11 +42,25 @@ class _ParameterStoreSyncer:
|
||||||
del self.parameters_store[self._find_index(key)]
|
del self.parameters_store[self._find_index(key)]
|
||||||
|
|
||||||
|
|
||||||
|
class _LastChangesStoreSyncer(ListSyncer):
|
||||||
|
def convert(self, x):
|
||||||
|
if len(x) == 3:
|
||||||
|
timestamp, name, value = x
|
||||||
|
else:
|
||||||
|
timestamp, name = x
|
||||||
|
value = "<deleted>"
|
||||||
|
return [time.strftime("%m/%d %H:%M:%S", time.localtime(timestamp)),
|
||||||
|
name, str(value)]
|
||||||
|
|
||||||
|
|
||||||
class ParametersWindow(Window):
|
class ParametersWindow(Window):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Window.__init__(self, title="Parameters")
|
Window.__init__(self, title="Parameters")
|
||||||
self.set_default_size(500, 500)
|
self.set_default_size(500, 500)
|
||||||
|
|
||||||
|
notebook = Gtk.Notebook()
|
||||||
|
self.add(notebook)
|
||||||
|
|
||||||
self.parameters_store = Gtk.ListStore(str, str)
|
self.parameters_store = Gtk.ListStore(str, str)
|
||||||
tree = Gtk.TreeView(self.parameters_store)
|
tree = Gtk.TreeView(self.parameters_store)
|
||||||
for i, title in enumerate(["Parameter", "Value"]):
|
for i, title in enumerate(["Parameter", "Value"]):
|
||||||
|
@ -54,17 +69,38 @@ class ParametersWindow(Window):
|
||||||
tree.append_column(column)
|
tree.append_column(column)
|
||||||
scroll = Gtk.ScrolledWindow()
|
scroll = Gtk.ScrolledWindow()
|
||||||
scroll.add(tree)
|
scroll.add(tree)
|
||||||
self.add(scroll)
|
notebook.insert_page(scroll, Gtk.Label("Current values"), -1)
|
||||||
|
|
||||||
|
self.lastchanges_store = Gtk.ListStore(str, str, str)
|
||||||
|
tree = Gtk.TreeView(self.lastchanges_store)
|
||||||
|
for i, title in enumerate(["Time", "Parameter", "Value"]):
|
||||||
|
renderer = Gtk.CellRendererText()
|
||||||
|
column = Gtk.TreeViewColumn(title, renderer, text=i)
|
||||||
|
tree.append_column(column)
|
||||||
|
scroll = Gtk.ScrolledWindow()
|
||||||
|
scroll.add(tree)
|
||||||
|
notebook.insert_page(scroll, Gtk.Label("Last changes"), -1)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def sub_connect(self, host, port):
|
def sub_connect(self, host, port):
|
||||||
self.parameters_subscriber = Subscriber("parameters",
|
self.parameters_subscriber = Subscriber("parameters",
|
||||||
self.init_parameters_store)
|
self.init_parameters_store)
|
||||||
yield from self.parameters_subscriber.connect(host, port)
|
yield from self.parameters_subscriber.connect(host, port)
|
||||||
|
try:
|
||||||
|
self.lastchanges_subscriber = Subscriber(
|
||||||
|
"parameters_simplehist", self.init_lastchanges_store)
|
||||||
|
yield from self.lastchanges_subscriber.connect(host, port)
|
||||||
|
except:
|
||||||
|
yield from self.parameters_subscriber.close()
|
||||||
|
raise
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def sub_close(self):
|
def sub_close(self):
|
||||||
|
yield from self.lastchanges_subscriber.close()
|
||||||
yield from self.parameters_subscriber.close()
|
yield from self.parameters_subscriber.close()
|
||||||
|
|
||||||
def init_parameters_store(self, init):
|
def init_parameters_store(self, init):
|
||||||
return _ParameterStoreSyncer(self.parameters_store, init)
|
return _ParameterStoreSyncer(self.parameters_store, init)
|
||||||
|
|
||||||
|
def init_lastchanges_store(self, init):
|
||||||
|
return _LastChangesStoreSyncer(self.lastchanges_store, init)
|
||||||
|
|
|
@ -3,33 +3,18 @@ import asyncio
|
||||||
|
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
from artiq.gui.tools import Window
|
from artiq.gui.tools import Window, ListSyncer
|
||||||
from artiq.management.sync_struct import Subscriber
|
from artiq.management.sync_struct import Subscriber
|
||||||
|
|
||||||
|
|
||||||
class _QueueStoreSyncer:
|
class _QueueStoreSyncer(ListSyncer):
|
||||||
def __init__(self, queue_store, init):
|
def convert(self, x):
|
||||||
self.queue_store = queue_store
|
|
||||||
self.queue_store.clear()
|
|
||||||
for x in init:
|
|
||||||
self.append(x)
|
|
||||||
|
|
||||||
def _convert(self, x):
|
|
||||||
rid, run_params, timeout = x
|
rid, run_params, timeout = x
|
||||||
row = [rid, run_params["file"]]
|
row = [rid, run_params["file"]]
|
||||||
for e in run_params["unit"], run_params["function"], timeout:
|
for e in run_params["unit"], run_params["function"], timeout:
|
||||||
row.append("-" if e is None else str(e))
|
row.append("-" if e is None else str(e))
|
||||||
return row
|
return row
|
||||||
|
|
||||||
def append(self, x):
|
|
||||||
self.queue_store.append(self._convert(x))
|
|
||||||
|
|
||||||
def insert(self, i, x):
|
|
||||||
self.queue_store.insert(i, self._convert(x))
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
|
||||||
del self.queue_store[key]
|
|
||||||
|
|
||||||
|
|
||||||
class _PeriodicStoreSyncer:
|
class _PeriodicStoreSyncer:
|
||||||
def __init__(self, periodic_store, init):
|
def __init__(self, periodic_store, init):
|
||||||
|
|
|
@ -5,9 +5,27 @@ from gi.repository import Gtk
|
||||||
|
|
||||||
data_dir = os.path.abspath(os.path.dirname(__file__))
|
data_dir = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
|
|
||||||
class Window(Gtk.Window):
|
class Window(Gtk.Window):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
Gtk.Window.__init__(self, *args, **kwargs)
|
Gtk.Window.__init__(self, *args, **kwargs)
|
||||||
self.set_wmclass("ARTIQ", "ARTIQ")
|
self.set_wmclass("ARTIQ", "ARTIQ")
|
||||||
self.set_icon_from_file(os.path.join(data_dir, "icon.png"))
|
self.set_icon_from_file(os.path.join(data_dir, "icon.png"))
|
||||||
self.set_border_width(6)
|
self.set_border_width(6)
|
||||||
|
|
||||||
|
|
||||||
|
class ListSyncer:
|
||||||
|
def __init__(self, store, init):
|
||||||
|
self.store = store
|
||||||
|
self.store.clear()
|
||||||
|
for x in init:
|
||||||
|
self.append(x)
|
||||||
|
|
||||||
|
def append(self, x):
|
||||||
|
self.store.append(self.convert(x))
|
||||||
|
|
||||||
|
def insert(self, i, x):
|
||||||
|
self.store.insert(i, self.convert(x))
|
||||||
|
|
||||||
|
def __delitem__(self, key):
|
||||||
|
del self.store[key]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import importlib
|
import importlib
|
||||||
|
from time import time
|
||||||
|
|
||||||
from artiq.language.context import *
|
from artiq.language.context import *
|
||||||
from artiq.management import pyon
|
from artiq.management import pyon
|
||||||
|
@ -68,6 +69,7 @@ class DeviceParamDB:
|
||||||
self.pdb_file = pdb_file
|
self.pdb_file = pdb_file
|
||||||
self.ddb = Notifier(pyon.load_file(self.ddb_file))
|
self.ddb = Notifier(pyon.load_file(self.ddb_file))
|
||||||
self.pdb = Notifier(pyon.load_file(self.pdb_file))
|
self.pdb = Notifier(pyon.load_file(self.pdb_file))
|
||||||
|
self.parameter_hooks = []
|
||||||
|
|
||||||
def save_ddb(self):
|
def save_ddb(self):
|
||||||
pyon.store_file(self.ddb_file, self.ddb.backing_struct)
|
pyon.store_file(self.ddb_file, self.ddb.backing_struct)
|
||||||
|
@ -92,7 +94,29 @@ class DeviceParamDB:
|
||||||
def set_parameter(self, name, value):
|
def set_parameter(self, name, value):
|
||||||
self.pdb[name] = value
|
self.pdb[name] = value
|
||||||
self.save_pdb()
|
self.save_pdb()
|
||||||
|
timestamp = time()
|
||||||
|
for hook in self.parameter_hooks:
|
||||||
|
hook.set_parameter(timestamp, name, value)
|
||||||
|
|
||||||
def del_parameter(self, name):
|
def del_parameter(self, name):
|
||||||
del self.pdb[name]
|
del self.pdb[name]
|
||||||
self.save_pdb()
|
self.save_pdb()
|
||||||
|
timestamp = time()
|
||||||
|
for hook in self.parameter_hooks:
|
||||||
|
hook.del_parameter(timestamp, name)
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleParameterHistory:
|
||||||
|
def __init__(self, depth):
|
||||||
|
self.depth = depth
|
||||||
|
self.history = Notifier([])
|
||||||
|
|
||||||
|
def set_parameter(self, timestamp, name, value):
|
||||||
|
if len(self.history.backing_struct) >= self.depth:
|
||||||
|
del self.history[0]
|
||||||
|
self.history.append((timestamp, name, value))
|
||||||
|
|
||||||
|
def del_parameter(self, timestamp, name):
|
||||||
|
if len(self.history.backing_struct) >= self.depth:
|
||||||
|
del self.history[0]
|
||||||
|
self.history.append((timestamp, name))
|
||||||
|
|
|
@ -6,7 +6,7 @@ import atexit
|
||||||
|
|
||||||
from artiq.management.pc_rpc import Server
|
from artiq.management.pc_rpc import Server
|
||||||
from artiq.management.sync_struct import Publisher
|
from artiq.management.sync_struct import Publisher
|
||||||
from artiq.management.dpdb import DeviceParamDB
|
from artiq.management.dpdb import DeviceParamDB, SimpleParameterHistory
|
||||||
from artiq.management.scheduler import Scheduler
|
from artiq.management.scheduler import Scheduler
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +26,10 @@ def _get_args():
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
args = _get_args()
|
args = _get_args()
|
||||||
|
|
||||||
dpdb = DeviceParamDB("ddb.pyon", "pdb.pyon")
|
dpdb = DeviceParamDB("ddb.pyon", "pdb.pyon")
|
||||||
|
simplephist = SimpleParameterHistory(30)
|
||||||
|
dpdb.parameter_hooks.append(simplephist)
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
atexit.register(lambda: loop.close())
|
atexit.register(lambda: loop.close())
|
||||||
|
@ -50,7 +53,8 @@ def main():
|
||||||
"queue": scheduler.queue,
|
"queue": scheduler.queue,
|
||||||
"periodic": scheduler.periodic,
|
"periodic": scheduler.periodic,
|
||||||
"devices": dpdb.ddb,
|
"devices": dpdb.ddb,
|
||||||
"parameters": dpdb.pdb
|
"parameters": dpdb.pdb,
|
||||||
|
"parameters_simplehist": simplephist.history
|
||||||
})
|
})
|
||||||
loop.run_until_complete(server_notify.start(
|
loop.run_until_complete(server_notify.start(
|
||||||
args.bind, args.port_notify))
|
args.bind, args.port_notify))
|
||||||
|
|
Loading…
Reference in New Issue