forked from M-Labs/artiq
gui: switch to Qt
This commit is contained in:
parent
c91cd0ab38
commit
ea53ed1af7
|
@ -4,4 +4,3 @@ from artiq.language.db import *
|
||||||
from artiq.language.units import check_unit
|
from artiq.language.units import check_unit
|
||||||
from artiq.language.units import ps, ns, us, ms, s
|
from artiq.language.units import ps, ns, us, ms, s
|
||||||
from artiq.language.units import Hz, kHz, MHz, GHz
|
from artiq.language.units import Hz, kHz, MHz, GHz
|
||||||
from artiq.gui.explib import *
|
|
||||||
|
|
|
@ -4,17 +4,14 @@ import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
import atexit
|
import atexit
|
||||||
|
|
||||||
import gbulb
|
# Quamash must be imported first so that pyqtgraph picks up the Qt binding
|
||||||
from gi.repository import Gtk
|
# it has chosen.
|
||||||
|
from quamash import QEventLoop, QtGui
|
||||||
|
from pyqtgraph.dockarea import DockArea
|
||||||
|
|
||||||
from artiq.protocols.file_db import FlatFileDB
|
from artiq.protocols.file_db import FlatFileDB
|
||||||
from artiq.protocols.pc_rpc import AsyncioClient
|
from artiq.gui.schedule import ScheduleDock
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
from artiq.gui.parameters import ParametersDock
|
||||||
from artiq.gui.tools import LayoutManager
|
|
||||||
from artiq.gui.scheduler import SchedulerWindow
|
|
||||||
from artiq.gui.parameters import ParametersWindow
|
|
||||||
from artiq.gui.rt_results import RTResults
|
|
||||||
from artiq.gui.explorer import ExplorerWindow
|
|
||||||
|
|
||||||
|
|
||||||
def get_argparser():
|
def get_argparser():
|
||||||
|
@ -38,67 +35,31 @@ def main():
|
||||||
args = get_argparser().parse_args()
|
args = get_argparser().parse_args()
|
||||||
|
|
||||||
db = FlatFileDB(args.db_file, default_data=dict())
|
db = FlatFileDB(args.db_file, default_data=dict())
|
||||||
lmgr = LayoutManager(db)
|
|
||||||
|
|
||||||
asyncio.set_event_loop_policy(gbulb.GtkEventLoopPolicy())
|
app = QtGui.QApplication([])
|
||||||
loop = asyncio.get_event_loop()
|
loop = QEventLoop(app)
|
||||||
|
asyncio.set_event_loop(loop)
|
||||||
atexit.register(lambda: loop.close())
|
atexit.register(lambda: loop.close())
|
||||||
|
|
||||||
# share the schedule control and repository connections
|
win = QtGui.QMainWindow()
|
||||||
schedule_ctl = AsyncioClient()
|
area = DockArea()
|
||||||
loop.run_until_complete(schedule_ctl.connect_rpc(
|
win.setCentralWidget(area)
|
||||||
args.server, args.port_control, "master_schedule"))
|
win.resize(1000, 500)
|
||||||
atexit.register(lambda: schedule_ctl.close_rpc())
|
win.setWindowTitle("ARTIQ")
|
||||||
repository = AsyncioClient()
|
|
||||||
loop.run_until_complete(repository.connect_rpc(
|
|
||||||
args.server, args.port_control, "master_repository"))
|
|
||||||
atexit.register(lambda: repository.close_rpc())
|
|
||||||
|
|
||||||
scheduler_win = lmgr.create_window(SchedulerWindow,
|
d_params = ParametersDock(area)
|
||||||
"scheduler",
|
area.addDock(d_params, "left")
|
||||||
schedule_ctl)
|
loop.run_until_complete(d_params.sub_connect(
|
||||||
loop.run_until_complete(scheduler_win.sub_connect(
|
|
||||||
args.server, args.port_notify))
|
args.server, args.port_notify))
|
||||||
atexit.register(
|
atexit.register(lambda: loop.run_until_complete(d_params.sub_close()))
|
||||||
lambda: loop.run_until_complete(scheduler_win.sub_close()))
|
|
||||||
|
|
||||||
parameters_win = lmgr.create_window(ParametersWindow, "parameters")
|
d_schedule = ScheduleDock(area)
|
||||||
loop.run_until_complete(parameters_win.sub_connect(
|
area.addDock(d_schedule, "top", d_params)
|
||||||
|
loop.run_until_complete(d_schedule.sub_connect(
|
||||||
args.server, args.port_notify))
|
args.server, args.port_notify))
|
||||||
atexit.register(
|
atexit.register(lambda: loop.run_until_complete(d_schedule.sub_close()))
|
||||||
lambda: loop.run_until_complete(parameters_win.sub_close()))
|
|
||||||
|
|
||||||
def exit(*args):
|
|
||||||
lmgr.save()
|
|
||||||
Gtk.main_quit(*args)
|
|
||||||
explorer_win = lmgr.create_window(ExplorerWindow,
|
|
||||||
"explorer",
|
|
||||||
exit,
|
|
||||||
schedule_ctl,
|
|
||||||
repository)
|
|
||||||
loop.run_until_complete(explorer_win.sub_connect(
|
|
||||||
args.server, args.port_notify))
|
|
||||||
atexit.register(
|
|
||||||
lambda: loop.run_until_complete(explorer_win.sub_close()))
|
|
||||||
|
|
||||||
parameters_sub = Subscriber("parameters",
|
|
||||||
[parameters_win.init_parameters_store,
|
|
||||||
explorer_win.init_parameters_dict])
|
|
||||||
loop.run_until_complete(
|
|
||||||
parameters_sub.connect(args.server, args.port_notify))
|
|
||||||
atexit.register(
|
|
||||||
lambda: loop.run_until_complete(parameters_sub.close()))
|
|
||||||
|
|
||||||
scheduler_win.show_all()
|
|
||||||
parameters_win.show_all()
|
|
||||||
explorer_win.show_all()
|
|
||||||
|
|
||||||
rtr = RTResults()
|
|
||||||
loop.run_until_complete(rtr.sub_connect(
|
|
||||||
args.server, args.port_notify))
|
|
||||||
atexit.register(
|
|
||||||
lambda: loop.run_until_complete(rtr.sub_close()))
|
|
||||||
|
|
||||||
|
win.show()
|
||||||
loop.run_forever()
|
loop.run_forever()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
import asyncio as _aio
|
|
||||||
|
|
||||||
|
|
||||||
class BaseControls:
|
|
||||||
def __init__(self, facilities):
|
|
||||||
self.facilities = facilities
|
|
||||||
|
|
||||||
@_aio.coroutine
|
|
||||||
def build(self):
|
|
||||||
self.finalize()
|
|
||||||
|
|
||||||
def finalize(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class GladeControls(BaseControls):
|
|
||||||
def __init__(self, facilities, glade_file, top_widget_name="top"):
|
|
||||||
BaseControls.__init__(self, facilities)
|
|
||||||
self.glade_file = glade_file
|
|
||||||
self.top_widget_name = top_widget_name
|
|
||||||
|
|
||||||
@_aio.coroutine
|
|
||||||
def build(self):
|
|
||||||
# lazy import GTK so that the artiq top-level
|
|
||||||
# (which imports from us) can be imported on systems
|
|
||||||
# without GTK installed
|
|
||||||
from gi.repository import Gtk
|
|
||||||
|
|
||||||
self.builder = Gtk.Builder()
|
|
||||||
data = yield from self.facilities.get_data(self.glade_file)
|
|
||||||
self.builder.add_from_string(data)
|
|
||||||
self.finalize()
|
|
||||||
|
|
||||||
def get_top_widget(self):
|
|
||||||
return self.builder.get_object(self.top_widget_name)
|
|
|
@ -1,152 +0,0 @@
|
||||||
import asyncio
|
|
||||||
import types
|
|
||||||
|
|
||||||
from gi.repository import Gtk
|
|
||||||
|
|
||||||
from artiq.gui.tools import Window, getitem, DictSyncer
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
|
||||||
|
|
||||||
|
|
||||||
class _ExplistStoreSyncer(DictSyncer):
|
|
||||||
def order_key(self, kv_pair):
|
|
||||||
return kv_pair[0]
|
|
||||||
|
|
||||||
def convert(self, name, value):
|
|
||||||
return [name]
|
|
||||||
|
|
||||||
|
|
||||||
class ExplorerWindow(Window):
|
|
||||||
def __init__(self, exit_fn, schedule_ctl, repository, layout_dict=dict()):
|
|
||||||
self.schedule_ctl = schedule_ctl
|
|
||||||
self.repository = repository
|
|
||||||
|
|
||||||
Window.__init__(self,
|
|
||||||
title="Explorer",
|
|
||||||
default_size=(800, 570),
|
|
||||||
layout_dict=layout_dict)
|
|
||||||
self.connect("delete-event", exit_fn)
|
|
||||||
|
|
||||||
topvbox = Gtk.VBox(spacing=6)
|
|
||||||
self.add(topvbox)
|
|
||||||
|
|
||||||
menubar = Gtk.MenuBar()
|
|
||||||
topvbox.pack_start(menubar, False, False, 0)
|
|
||||||
|
|
||||||
top_menuitem = Gtk.MenuItem("Windows")
|
|
||||||
menu = Gtk.Menu()
|
|
||||||
menuitem = Gtk.MenuItem("Scheduler")
|
|
||||||
menu.append(menuitem)
|
|
||||||
menuitem = Gtk.MenuItem("Parameters")
|
|
||||||
menu.append(menuitem)
|
|
||||||
menu.append(Gtk.SeparatorMenuItem())
|
|
||||||
menuitem = Gtk.MenuItem("Quit")
|
|
||||||
menuitem.connect("activate", exit_fn)
|
|
||||||
menu.append(menuitem)
|
|
||||||
top_menuitem.set_submenu(menu)
|
|
||||||
menubar.append(top_menuitem)
|
|
||||||
|
|
||||||
top_menuitem = Gtk.MenuItem("Registry")
|
|
||||||
menu = Gtk.Menu()
|
|
||||||
menuitem = Gtk.MenuItem("Run selected")
|
|
||||||
menuitem.connect("activate", self.run)
|
|
||||||
menu.append(menuitem)
|
|
||||||
menu.append(Gtk.SeparatorMenuItem())
|
|
||||||
menuitem = Gtk.MenuItem("Add experiment")
|
|
||||||
menu.append(menuitem)
|
|
||||||
menuitem = Gtk.MenuItem("Remove experiment")
|
|
||||||
menu.append(menuitem)
|
|
||||||
top_menuitem.set_submenu(menu)
|
|
||||||
menubar.append(top_menuitem)
|
|
||||||
|
|
||||||
self.pane = Gtk.HPaned(
|
|
||||||
position=getitem(layout_dict, "pane_position", 180))
|
|
||||||
topvbox.pack_start(self.pane, True, True, 0)
|
|
||||||
|
|
||||||
explistvbox = Gtk.VBox(spacing=6)
|
|
||||||
self.pane.pack1(explistvbox)
|
|
||||||
self.explist_store = Gtk.ListStore(str)
|
|
||||||
self.explist_tree = Gtk.TreeView(self.explist_store)
|
|
||||||
renderer = Gtk.CellRendererText()
|
|
||||||
column = Gtk.TreeViewColumn("Registered experiments", renderer, text=0)
|
|
||||||
self.explist_tree.append_column(column)
|
|
||||||
self.explist_tree.connect("row-activated", self.explist_row_activated)
|
|
||||||
self.explist_tree.set_activate_on_single_click(True)
|
|
||||||
scroll = Gtk.ScrolledWindow()
|
|
||||||
scroll.add(self.explist_tree)
|
|
||||||
explistvbox.pack_start(scroll, True, True, 0)
|
|
||||||
button = Gtk.Button("Run")
|
|
||||||
button.connect("clicked", self.run)
|
|
||||||
explistvbox.pack_start(button, False, False, 0)
|
|
||||||
|
|
||||||
self.pane_contents = Gtk.Label("")
|
|
||||||
self.pane.pack2(self.pane_contents)
|
|
||||||
|
|
||||||
def get_layout_dict(self):
|
|
||||||
r = Window.get_layout_dict(self)
|
|
||||||
r["pane_position"] = self.pane.get_position()
|
|
||||||
return r
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def sub_connect(self, host, port):
|
|
||||||
self.explist_subscriber = Subscriber("explist",
|
|
||||||
[self.init_explist_store,
|
|
||||||
self.init_explist_data])
|
|
||||||
yield from self.explist_subscriber.connect(host, port)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def sub_close(self):
|
|
||||||
yield from self.explist_subscriber.close()
|
|
||||||
|
|
||||||
def init_parameters_dict(self, init):
|
|
||||||
self.parameters = init
|
|
||||||
return init
|
|
||||||
|
|
||||||
def set_pane_contents(self, widget):
|
|
||||||
self.pane_contents.destroy()
|
|
||||||
self.pane_contents = widget
|
|
||||||
self.pane.pack2(self.pane_contents)
|
|
||||||
self.pane_contents.show_all()
|
|
||||||
|
|
||||||
def init_explist_store(self, init):
|
|
||||||
return _ExplistStoreSyncer(self.explist_store, init)
|
|
||||||
|
|
||||||
def init_explist_data(self, init):
|
|
||||||
self.explist_data = init
|
|
||||||
return init
|
|
||||||
|
|
||||||
def explist_row_activated(self, widget, index, column):
|
|
||||||
self.controls = None
|
|
||||||
name = self.explist_store[index][0]
|
|
||||||
gui_file = self.explist_data[name]["gui_file"]
|
|
||||||
if gui_file is None:
|
|
||||||
self.set_pane_contents(Gtk.Label("No GUI controls"))
|
|
||||||
else:
|
|
||||||
asyncio.Task(self.load_gui_file(gui_file))
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def load_gui_file(self, gui_file):
|
|
||||||
gui_mod_data = yield from self.repository.get_data(gui_file)
|
|
||||||
gui_mod = dict()
|
|
||||||
exec(gui_mod_data, gui_mod)
|
|
||||||
facilities = types.SimpleNamespace(
|
|
||||||
get_data=self.repository.get_data,
|
|
||||||
get_parameter=lambda p: self.parameters[p])
|
|
||||||
self.controls = gui_mod["Controls"](facilities)
|
|
||||||
yield from self.controls.build()
|
|
||||||
self.set_pane_contents(self.controls.get_top_widget())
|
|
||||||
|
|
||||||
def run(self, widget):
|
|
||||||
store, selected = self.explist_tree.get_selection().get_selected()
|
|
||||||
if selected is not None:
|
|
||||||
name = store[selected][0]
|
|
||||||
data = self.explist_data[name]
|
|
||||||
if self.controls is None:
|
|
||||||
arguments = {}
|
|
||||||
else:
|
|
||||||
arguments = self.controls.get_arguments()
|
|
||||||
expid = {
|
|
||||||
"file": data["file"],
|
|
||||||
"experiment": data["experiment"],
|
|
||||||
"arguments": arguments
|
|
||||||
}
|
|
||||||
asyncio.async(self.schedule_ctl.submit("main", expid, None))
|
|
Binary file not shown.
Before Width: | Height: | Size: 13 KiB |
|
@ -1,74 +1,47 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
from operator import itemgetter
|
|
||||||
import time
|
|
||||||
|
|
||||||
from gi.repository import Gtk
|
from quamash import QtGui
|
||||||
|
from pyqtgraph.dockarea import Dock
|
||||||
|
|
||||||
from artiq.gui.tools import Window, ListSyncer, DictSyncer
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
from artiq.protocols.sync_struct import Subscriber
|
||||||
|
from artiq.gui.tools import DictSyncModel
|
||||||
|
|
||||||
|
|
||||||
class _ParameterStoreSyncer(DictSyncer):
|
class ParametersModel(DictSyncModel):
|
||||||
def order_key(self, kv_pair):
|
def __init__(self, parent, init):
|
||||||
return kv_pair[0]
|
DictSyncModel.__init__(self, ["Parameter", "Value"],
|
||||||
|
parent, init)
|
||||||
|
|
||||||
def convert(self, name, value):
|
def sort_key(self, k, v):
|
||||||
return [name, str(value)]
|
return k
|
||||||
|
|
||||||
|
def convert(self, k, v, column):
|
||||||
class _LastChangesStoreSyncer(ListSyncer):
|
if column == 0:
|
||||||
def convert(self, x):
|
return k
|
||||||
if len(x) == 3:
|
elif column == 1:
|
||||||
timestamp, name, value = x
|
return str(v)
|
||||||
else:
|
else:
|
||||||
timestamp, name = x
|
raise ValueError
|
||||||
value = "<deleted>"
|
|
||||||
return [time.strftime("%m/%d %H:%M:%S", time.localtime(timestamp)),
|
|
||||||
name, str(value)]
|
|
||||||
|
|
||||||
|
|
||||||
class ParametersWindow(Window):
|
class ParametersDock(Dock):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, parent):
|
||||||
Window.__init__(self,
|
Dock.__init__(self, "Parameters", size=(500, 300))
|
||||||
title="Parameters",
|
|
||||||
default_size=(500, 500),
|
|
||||||
**kwargs)
|
|
||||||
|
|
||||||
notebook = Gtk.Notebook()
|
self.table = QtGui.QTableView()
|
||||||
self.add(notebook)
|
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
|
||||||
|
self.addWidget(self.table)
|
||||||
self.parameters_store = Gtk.ListStore(str, str)
|
|
||||||
tree = Gtk.TreeView(self.parameters_store)
|
|
||||||
for i, title in enumerate(["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("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.lastchanges_subscriber = Subscriber(
|
self.subscriber = Subscriber("parameters", self.init_parameters_model)
|
||||||
"parameters_simplehist", self.init_lastchanges_store)
|
yield from self.subscriber.connect(host, port)
|
||||||
yield from self.lastchanges_subscriber.connect(host, port)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def sub_close(self):
|
def sub_close(self):
|
||||||
yield from self.lastchanges_subscriber.close()
|
yield from self.subscriber.close()
|
||||||
|
|
||||||
def init_parameters_store(self, init):
|
def init_parameters_model(self, init):
|
||||||
return _ParameterStoreSyncer(self.parameters_store, init)
|
table_model = ParametersModel(self.table, init)
|
||||||
|
self.table.setModel(table_model)
|
||||||
def init_lastchanges_store(self, init):
|
return table_model
|
||||||
return _LastChangesStoreSyncer(self.lastchanges_store, init)
|
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
from gi.repository import Gtk
|
|
||||||
import cairoplot
|
|
||||||
|
|
||||||
from artiq.gui.tools import Window
|
|
||||||
|
|
||||||
|
|
||||||
class RawWindow(Window):
|
|
||||||
def __init__(self, group_name, set_names):
|
|
||||||
self.labels = dict()
|
|
||||||
|
|
||||||
Window.__init__(self, title=group_name + ": Raw values",
|
|
||||||
default_size=(200, 150))
|
|
||||||
|
|
||||||
grid = Gtk.Grid(row_spacing=6, column_spacing=6)
|
|
||||||
self.add(grid)
|
|
||||||
for i, name in enumerate(set_names):
|
|
||||||
grid.attach(Gtk.Label(name), 0, i, 1, 1)
|
|
||||||
label = Gtk.Label("-")
|
|
||||||
self.labels[name] = label
|
|
||||||
grid.attach(label, 1, i, 1, 1)
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
def set_data(self, data):
|
|
||||||
for name, label in self.labels.items():
|
|
||||||
if name in data:
|
|
||||||
label.set_text(str(data[name]))
|
|
||||||
|
|
||||||
|
|
||||||
class PlotWindow(Window):
|
|
||||||
def __init__(self, group_name, set_names):
|
|
||||||
self.set_names = set_names
|
|
||||||
self.data = None
|
|
||||||
|
|
||||||
Window.__init__(self, title=group_name + ": " + "/".join(set_names),
|
|
||||||
default_size=(700, 500))
|
|
||||||
|
|
||||||
self.darea = Gtk.DrawingArea()
|
|
||||||
self.darea.set_size_request(100, 100)
|
|
||||||
self.darea.connect("draw", self.on_draw)
|
|
||||||
self.add(self.darea)
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
|
|
||||||
class XYWindow(PlotWindow):
|
|
||||||
def on_draw(self, widget, ctx):
|
|
||||||
if self.data is not None:
|
|
||||||
data = self.filter_data()
|
|
||||||
cairoplot.scatter_plot(
|
|
||||||
ctx,
|
|
||||||
data=data,
|
|
||||||
width=widget.get_allocated_width(),
|
|
||||||
height=widget.get_allocated_height(),
|
|
||||||
x_bounds=(min(data[0])*0.98, max(data[0])*1.02),
|
|
||||||
y_bounds=(min(data[1])*0.98, max(data[1])*1.02),
|
|
||||||
border=20, axis=True, grid=True,
|
|
||||||
dots=1, discrete=True,
|
|
||||||
series_colors=[(0.0, 0.0, 0.0)],
|
|
||||||
background="white"
|
|
||||||
)
|
|
||||||
|
|
||||||
def filter_data(self):
|
|
||||||
return [
|
|
||||||
self.data[self.set_names[0]],
|
|
||||||
self.data[self.set_names[1]],
|
|
||||||
]
|
|
||||||
|
|
||||||
def set_data(self, data):
|
|
||||||
self.data = data
|
|
||||||
if not self.data:
|
|
||||||
return
|
|
||||||
# The two axes are not updated simultaneously.
|
|
||||||
# Redraw only after receiving a new point for each.
|
|
||||||
x, y = self.filter_data()
|
|
||||||
if len(x) == len(y):
|
|
||||||
self.darea.queue_draw()
|
|
|
@ -1,120 +0,0 @@
|
||||||
import asyncio
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
|
||||||
from artiq.gui.rt_result_views import RawWindow, XYWindow
|
|
||||||
|
|
||||||
|
|
||||||
def _create_view(group_name, set_names, view_description):
|
|
||||||
if view_description == "raw":
|
|
||||||
r = RawWindow(group_name, set_names)
|
|
||||||
elif view_description == "xy":
|
|
||||||
r = XYWindow(group_name, set_names)
|
|
||||||
else:
|
|
||||||
raise ValueError("Unknown view description: " + view_description)
|
|
||||||
r.show_all()
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
class _Group:
|
|
||||||
def __init__(self, name, init):
|
|
||||||
self.name = name
|
|
||||||
# data key -> list of views using it
|
|
||||||
self.views = defaultdict(list)
|
|
||||||
# original data
|
|
||||||
self.data = dict()
|
|
||||||
for k, v in init.items():
|
|
||||||
self[k] = v
|
|
||||||
|
|
||||||
def all_views(self):
|
|
||||||
r = set()
|
|
||||||
for view_list in self.views.values():
|
|
||||||
for view in view_list:
|
|
||||||
r.add(view)
|
|
||||||
return r
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
for view in self.all_views():
|
|
||||||
view.delete()
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
if key == "data":
|
|
||||||
return self.data
|
|
||||||
else:
|
|
||||||
raise KeyError
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
if key == "description":
|
|
||||||
self.delete()
|
|
||||||
self.views = defaultdict(list)
|
|
||||||
for set_names, view_description in value.items():
|
|
||||||
if not isinstance(set_names, tuple):
|
|
||||||
set_names = (set_names, )
|
|
||||||
view = _create_view(self.name, set_names, view_description)
|
|
||||||
view.set_data(self.data)
|
|
||||||
for set_name in set_names:
|
|
||||||
self.views[set_name].append(view)
|
|
||||||
elif key == "data":
|
|
||||||
self.data = value
|
|
||||||
for view in self.all_views():
|
|
||||||
view.set_data(self.data)
|
|
||||||
else:
|
|
||||||
raise KeyError
|
|
||||||
|
|
||||||
def on_data_modified(self, key):
|
|
||||||
for view in self.views[key]:
|
|
||||||
view.set_data(self.data)
|
|
||||||
|
|
||||||
|
|
||||||
class _Groups:
|
|
||||||
def __init__(self, init):
|
|
||||||
self.groups = dict()
|
|
||||||
for k, v in init.items():
|
|
||||||
self[k] = v
|
|
||||||
|
|
||||||
def delete(self):
|
|
||||||
for s in self.groups.values():
|
|
||||||
s.delete()
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
return self.groups[key]
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
|
||||||
if key in self.groups:
|
|
||||||
self.groups[key].delete()
|
|
||||||
self.groups[key] = _Group(key, value)
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
|
||||||
self.groups[key].delete()
|
|
||||||
del self.groups[key]
|
|
||||||
|
|
||||||
|
|
||||||
class RTResults:
|
|
||||||
def __init__(self):
|
|
||||||
self.current_groups = None
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def sub_connect(self, host, port):
|
|
||||||
self.sets_subscriber = Subscriber("rt_results",
|
|
||||||
self.init_groups, self.on_mod)
|
|
||||||
yield from self.sets_subscriber.connect(host, port)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def sub_close(self):
|
|
||||||
yield from self.sets_subscriber.close()
|
|
||||||
|
|
||||||
def init_groups(self, init):
|
|
||||||
if self.current_groups is not None:
|
|
||||||
self.current_groups.delete()
|
|
||||||
self.current_groups = _Groups(init)
|
|
||||||
return self.current_groups
|
|
||||||
|
|
||||||
def on_mod(self, mod):
|
|
||||||
if mod["action"] != "init" and len(mod["path"]) >= 2:
|
|
||||||
path = mod["path"]
|
|
||||||
group = self.current_groups[path[0]]
|
|
||||||
if path[1] == "data":
|
|
||||||
if len(mod["path"]) >= 3:
|
|
||||||
group.on_data_modified(path[2])
|
|
||||||
else:
|
|
||||||
group.on_data_modified(mod["key"])
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import asyncio
|
||||||
|
import time
|
||||||
|
|
||||||
|
from quamash import QtGui
|
||||||
|
from pyqtgraph.dockarea import Dock
|
||||||
|
|
||||||
|
from artiq.protocols.sync_struct import Subscriber
|
||||||
|
from artiq.gui.tools import DictSyncModel
|
||||||
|
from artiq.tools import format_arguments
|
||||||
|
|
||||||
|
|
||||||
|
class _ScheduleModel(DictSyncModel):
|
||||||
|
def __init__(self, parent, init):
|
||||||
|
DictSyncModel.__init__(self,
|
||||||
|
["RID", "Pipeline", "Status", "Due date",
|
||||||
|
"File", "Experiment", "Arguments"],
|
||||||
|
parent, init)
|
||||||
|
|
||||||
|
def sort_key(self, k, v):
|
||||||
|
# order by due date, and then by RID
|
||||||
|
return (v["due_date"] or 0, k)
|
||||||
|
|
||||||
|
def convert(self, k, v, column):
|
||||||
|
if column == 0:
|
||||||
|
return k
|
||||||
|
elif column == 1:
|
||||||
|
return v["pipeline"]
|
||||||
|
elif column == 2:
|
||||||
|
return v["status"]
|
||||||
|
elif column == 3:
|
||||||
|
if v["due_date"] is None:
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
return time.strftime("%m/%d %H:%M:%S",
|
||||||
|
time.localtime(v["due_date"]))
|
||||||
|
elif column == 4:
|
||||||
|
return v["expid"]["file"]
|
||||||
|
elif column == 5:
|
||||||
|
if v["expid"]["experiment"] is None:
|
||||||
|
return ""
|
||||||
|
else:
|
||||||
|
return v["expid"]["experiment"]
|
||||||
|
elif column == 6:
|
||||||
|
return format_arguments(v["expid"]["arguments"])
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
|
||||||
|
|
||||||
|
class ScheduleDock(Dock):
|
||||||
|
def __init__(self, parent):
|
||||||
|
Dock.__init__(self, "Schedule", size=(1000, 300))
|
||||||
|
|
||||||
|
self.table = QtGui.QTableView()
|
||||||
|
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
|
||||||
|
self.addWidget(self.table)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def sub_connect(self, host, port):
|
||||||
|
self.subscriber = Subscriber("schedule", self.init_schedule_model)
|
||||||
|
yield from self.subscriber.connect(host, port)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def sub_close(self):
|
||||||
|
yield from self.subscriber.close()
|
||||||
|
|
||||||
|
def init_schedule_model(self, init):
|
||||||
|
table_model = _ScheduleModel(self.table, init)
|
||||||
|
self.table.setModel(table_model)
|
||||||
|
return table_model
|
|
@ -1,75 +0,0 @@
|
||||||
import time
|
|
||||||
import asyncio
|
|
||||||
|
|
||||||
from gi.repository import Gtk
|
|
||||||
|
|
||||||
from artiq.gui.tools import Window, DictSyncer
|
|
||||||
from artiq.protocols.sync_struct import Subscriber
|
|
||||||
from artiq.tools import format_arguments
|
|
||||||
|
|
||||||
|
|
||||||
class _ScheduleStoreSyncer(DictSyncer):
|
|
||||||
def order_key(self, kv_pair):
|
|
||||||
# order by due date, and then by RID
|
|
||||||
return (kv_pair[1]["due_date"] or 0, kv_pair[0])
|
|
||||||
|
|
||||||
def convert(self, rid, v):
|
|
||||||
row = [rid, v["pipeline"], v["status"]]
|
|
||||||
if v["due_date"] is None:
|
|
||||||
row.append("")
|
|
||||||
else:
|
|
||||||
row.append(time.strftime("%m/%d %H:%M:%S",
|
|
||||||
time.localtime(v["due_date"])))
|
|
||||||
row.append(v["expid"]["file"])
|
|
||||||
if v["expid"]["experiment"] is None:
|
|
||||||
row.append("")
|
|
||||||
else:
|
|
||||||
row.append(v["expid"]["experiment"])
|
|
||||||
row.append(format_arguments(v["expid"]["arguments"]))
|
|
||||||
return row
|
|
||||||
|
|
||||||
|
|
||||||
class SchedulerWindow(Window):
|
|
||||||
def __init__(self, schedule_ctl, **kwargs):
|
|
||||||
self.schedule_ctl = schedule_ctl
|
|
||||||
|
|
||||||
Window.__init__(self,
|
|
||||||
title="Scheduler",
|
|
||||||
default_size=(950, 570),
|
|
||||||
**kwargs)
|
|
||||||
|
|
||||||
topvbox = Gtk.VBox(spacing=6)
|
|
||||||
self.add(topvbox)
|
|
||||||
|
|
||||||
self.schedule_store = Gtk.ListStore(int, str, str, str, str, str, str)
|
|
||||||
self.schedule_tree = Gtk.TreeView(self.schedule_store)
|
|
||||||
for i, title in enumerate(["RID", "Pipeline", "Status", "Due date",
|
|
||||||
"File", "Experiment", "Arguments"]):
|
|
||||||
renderer = Gtk.CellRendererText()
|
|
||||||
column = Gtk.TreeViewColumn(title, renderer, text=i)
|
|
||||||
self.schedule_tree.append_column(column)
|
|
||||||
scroll = Gtk.ScrolledWindow()
|
|
||||||
scroll.add(self.schedule_tree)
|
|
||||||
topvbox.pack_start(scroll, True, True, 0)
|
|
||||||
button = Gtk.Button("Delete")
|
|
||||||
button.connect("clicked", self.delete)
|
|
||||||
topvbox.pack_start(button, False, False, 0)
|
|
||||||
topvbox.set_border_width(6)
|
|
||||||
|
|
||||||
def delete(self, widget):
|
|
||||||
store, selected = self.schedule_tree.get_selection().get_selected()
|
|
||||||
if selected is not None:
|
|
||||||
rid = store[selected][0]
|
|
||||||
asyncio.async(self.schedule_ctl.delete(rid))
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def sub_connect(self, host, port):
|
|
||||||
self.schedule_subscriber = Subscriber("schedule", self.init_schedule_store)
|
|
||||||
yield from self.schedule_subscriber.connect(host, port)
|
|
||||||
|
|
||||||
@asyncio.coroutine
|
|
||||||
def sub_close(self):
|
|
||||||
yield from self.schedule_subscriber.close()
|
|
||||||
|
|
||||||
def init_schedule_store(self, init):
|
|
||||||
return _ScheduleStoreSyncer(self.schedule_store, init)
|
|
|
@ -1,143 +1,96 @@
|
||||||
import os
|
from quamash import QtCore
|
||||||
|
|
||||||
from gi.repository import Gtk
|
|
||||||
|
|
||||||
|
|
||||||
data_dir = os.path.abspath(os.path.dirname(__file__))
|
class _DictSyncSubstruct:
|
||||||
|
|
||||||
|
|
||||||
def getitem(d, item, default):
|
|
||||||
try:
|
|
||||||
return d[item]
|
|
||||||
except KeyError:
|
|
||||||
return default
|
|
||||||
|
|
||||||
|
|
||||||
class Window(Gtk.Window):
|
|
||||||
def __init__(self, title, default_size, layout_dict=dict()):
|
|
||||||
Gtk.Window.__init__(self, title=title + " - ARTIQ")
|
|
||||||
|
|
||||||
self.set_wmclass("ARTIQ", "ARTIQ")
|
|
||||||
self.set_icon_from_file(os.path.join(data_dir, "icon.png"))
|
|
||||||
self.set_border_width(6)
|
|
||||||
|
|
||||||
size = getitem(layout_dict, "size", default_size)
|
|
||||||
self.set_default_size(size[0], size[1])
|
|
||||||
try:
|
|
||||||
position = layout_dict["position"]
|
|
||||||
except KeyError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
self.move(position[0], position[1])
|
|
||||||
|
|
||||||
def get_layout_dict(self):
|
|
||||||
return {
|
|
||||||
"size": self.get_size(),
|
|
||||||
"position": self.get_position()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class LayoutManager:
|
|
||||||
def __init__(self, db):
|
|
||||||
self.db = db
|
|
||||||
self.windows = dict()
|
|
||||||
|
|
||||||
def create_window(self, cls, name, *args, **kwargs):
|
|
||||||
try:
|
|
||||||
win_layouts = self.db.request("win_layouts")
|
|
||||||
layout_dict = win_layouts[name]
|
|
||||||
except KeyError:
|
|
||||||
layout_dict = dict()
|
|
||||||
win = cls(*args, layout_dict=layout_dict, **kwargs)
|
|
||||||
self.windows[name] = win
|
|
||||||
return win
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
win_layouts = {name: window.get_layout_dict()
|
|
||||||
for name, window in self.windows.items()}
|
|
||||||
self.db.set("win_layouts", win_layouts)
|
|
||||||
|
|
||||||
|
|
||||||
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]
|
|
||||||
|
|
||||||
def convert(self, x):
|
|
||||||
raise NotImplementedError
|
|
||||||
|
|
||||||
|
|
||||||
class _DictSyncerSubstruct:
|
|
||||||
def __init__(self, update_cb, ref):
|
def __init__(self, update_cb, ref):
|
||||||
self.update_cb = update_cb
|
self.update_cb = update_cb
|
||||||
self.ref = ref
|
self.ref = ref
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return _DictSyncerSubstruct(self.update_cb, self.ref[key])
|
return _DictSyncSubstruct(self.update_cb, self.ref[key])
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def __setitem__(self, key, value):
|
||||||
self.ref[key] = value
|
self.ref[key] = value
|
||||||
self.update_cb()
|
self.update_cb()
|
||||||
|
|
||||||
|
|
||||||
class DictSyncer:
|
class DictSyncModel(QtCore.QAbstractTableModel):
|
||||||
def __init__(self, store, init):
|
def __init__(self, headers, parent, init):
|
||||||
self.store = store
|
self.headers = headers
|
||||||
self.store.clear()
|
self.data = init
|
||||||
self.order = []
|
self.row_to_key = sorted(self.data.keys(),
|
||||||
for k, v in sorted(init.items(), key=self.order_key):
|
key=lambda k: self.sort_key(k, self.data[k]))
|
||||||
self.store.append(self.convert(k, v))
|
QtCore.QAbstractTableModel.__init__(self, parent)
|
||||||
self.order.append((k, self.order_key((k, v))))
|
|
||||||
self.local_copy = init
|
|
||||||
|
|
||||||
def _find_index(self, key):
|
def rowCount(self, parent):
|
||||||
for i, e in enumerate(self.order):
|
return len(self.data)
|
||||||
if e[0] == key:
|
|
||||||
return i
|
|
||||||
raise KeyError
|
|
||||||
|
|
||||||
def __setitem__(self, key, value):
|
def columnCount(self, parent):
|
||||||
try:
|
return len(self.headers)
|
||||||
i = self._find_index(key)
|
|
||||||
except KeyError:
|
def data(self, index, role):
|
||||||
pass
|
if not index.isValid():
|
||||||
|
return None
|
||||||
|
elif role != QtCore.Qt.DisplayRole:
|
||||||
|
return None
|
||||||
|
k = self.row_to_key[index.row()]
|
||||||
|
return self.convert(k, self.data[k], index.column())
|
||||||
|
|
||||||
|
def headerData(self, col, orientation, role):
|
||||||
|
if (orientation == QtCore.Qt.Horizontal
|
||||||
|
and role == QtCore.Qt.DisplayRole):
|
||||||
|
return self.headers[col]
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _find_row(self, k, v):
|
||||||
|
lo = 0
|
||||||
|
hi = len(self.row_to_key)
|
||||||
|
while lo < hi:
|
||||||
|
mid = (lo + hi)//2
|
||||||
|
if (self.sort_key(self.row_to_key[mid],
|
||||||
|
self.data[self.row_to_key[mid]])
|
||||||
|
< self.sort_key(k, v)):
|
||||||
|
lo = mid + 1
|
||||||
else:
|
else:
|
||||||
del self.store[i]
|
hi = mid
|
||||||
del self.order[i]
|
return lo
|
||||||
ord_el = self.order_key((key, value))
|
|
||||||
j = len(self.order)
|
|
||||||
for i, (k, o) in enumerate(self.order):
|
|
||||||
if o > ord_el:
|
|
||||||
j = i
|
|
||||||
break
|
|
||||||
self.store.insert(j, self.convert(key, value))
|
|
||||||
self.order.insert(j, (key, ord_el))
|
|
||||||
self.local_copy[key] = value
|
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __setitem__(self, k, v):
|
||||||
i = self._find_index(key)
|
if k in self.data:
|
||||||
del self.store[i]
|
old_row = self.row_to_key.index(k)
|
||||||
del self.order[i]
|
new_row = self._find_row(k, v)
|
||||||
del self.local_copy[key]
|
if old_row == new_row:
|
||||||
|
self.dataChanged.emit(self.index(old_row, 0),
|
||||||
|
self.index(old_row, len(self.headers)))
|
||||||
|
else:
|
||||||
|
self.beginMoveRows(QtCore.QModelIndex(), old_row, old_row,
|
||||||
|
QtCore.QModelIndex(), new_row)
|
||||||
|
self.data[k] = v
|
||||||
|
self.row_to_key[old_row], self.row_to_key[new_row] = \
|
||||||
|
self.row_to_key[new_row], self.row_to_key[old_row]
|
||||||
|
if old_row != new_row:
|
||||||
|
self.endMoveRows()
|
||||||
|
else:
|
||||||
|
row = self._find_row(k, v)
|
||||||
|
self.beginInsertRows(QtCore.QModelIndex(), row, row)
|
||||||
|
self.data[k] = v
|
||||||
|
self.row_to_key.insert(row, k)
|
||||||
|
self.endInsertRows()
|
||||||
|
|
||||||
|
def __delitem__(self, k):
|
||||||
|
row = self.row_to_key.index(k)
|
||||||
|
self.beginRemoveRows(QtCore.QModelIndex(), row, row)
|
||||||
|
del self.row_to_key[row]
|
||||||
|
del self.data[k]
|
||||||
|
self.endRemoveRows()
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
def update():
|
def update():
|
||||||
self[key] = self.local_copy[key]
|
self[key] = self.data[key]
|
||||||
return _DictSyncerSubstruct(update, self.local_copy[key])
|
return _DictSyncSubstruct(update, self.data[key])
|
||||||
|
|
||||||
def order_key(self, kv_pair):
|
def sort_key(self, k, v):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def convert(self, key, value):
|
def convert(self, k, v, column):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
|
@ -25,7 +25,6 @@ def model_numpy(xdata, F0):
|
||||||
|
|
||||||
class FloppingF(Experiment, AutoDB):
|
class FloppingF(Experiment, AutoDB):
|
||||||
"""Flopping F simulation"""
|
"""Flopping F simulation"""
|
||||||
__artiq_gui_file__ = "flopping_f_simulation_gui.py"
|
|
||||||
|
|
||||||
class DBKeys:
|
class DBKeys:
|
||||||
npoints = Argument(100)
|
npoints = Argument(100)
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!-- Generated with glade 3.18.3 -->
|
|
||||||
<interface>
|
|
||||||
<requires lib="gtk+" version="3.10"/>
|
|
||||||
<object class="GtkAdjustment" id="F0">
|
|
||||||
<property name="lower">1000</property>
|
|
||||||
<property name="upper">2000</property>
|
|
||||||
<property name="value">1500</property>
|
|
||||||
<property name="step_increment">1</property>
|
|
||||||
<property name="page_increment">10</property>
|
|
||||||
</object>
|
|
||||||
<object class="GtkGrid" id="top">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="halign">center</property>
|
|
||||||
<property name="valign">center</property>
|
|
||||||
<property name="orientation">vertical</property>
|
|
||||||
<property name="row_spacing">6</property>
|
|
||||||
<property name="column_spacing">6</property>
|
|
||||||
<child>
|
|
||||||
<object class="GtkSpinButton" id="spinbutton1">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="input_purpose">number</property>
|
|
||||||
<property name="adjustment">F0</property>
|
|
||||||
<property name="value">1500</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">1</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkButton" id="getparam">
|
|
||||||
<property name="label" translatable="yes">Get from parameter DB</property>
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">True</property>
|
|
||||||
<property name="receives_default">True</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">0</property>
|
|
||||||
<property name="top_attach">1</property>
|
|
||||||
<property name="width">2</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="GtkLabel" id="label2">
|
|
||||||
<property name="visible">True</property>
|
|
||||||
<property name="can_focus">False</property>
|
|
||||||
<property name="label" translatable="yes">Simulated flopping frequency:</property>
|
|
||||||
</object>
|
|
||||||
<packing>
|
|
||||||
<property name="left_attach">0</property>
|
|
||||||
<property name="top_attach">0</property>
|
|
||||||
</packing>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</interface>
|
|
|
@ -1,20 +0,0 @@
|
||||||
from artiq import GladeControls
|
|
||||||
|
|
||||||
|
|
||||||
class Controls(GladeControls):
|
|
||||||
def __init__(self, facilities):
|
|
||||||
GladeControls.__init__(self, facilities,
|
|
||||||
"flopping_f_simulation_gui.glade")
|
|
||||||
|
|
||||||
def finalize(self):
|
|
||||||
getparam = self.builder.get_object("getparam")
|
|
||||||
getparam.connect("clicked", self.getparam)
|
|
||||||
|
|
||||||
def getparam(self, widget):
|
|
||||||
F0 = self.facilities.get_parameter("flopping_freq")
|
|
||||||
self.builder.get_object("F0").set_value(F0)
|
|
||||||
|
|
||||||
def get_arguments(self):
|
|
||||||
return {
|
|
||||||
"F0": self.builder.get_object("F0").get_value()
|
|
||||||
}
|
|
17
setup.py
17
setup.py
|
@ -1,18 +1,19 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
from setuptools import setup, find_packages
|
from setuptools import setup, find_packages
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
requirements = [
|
requirements = [
|
||||||
"sphinx", "sphinx-argparse", "pyserial", "numpy", "scipy",
|
"sphinx", "sphinx-argparse", "pyserial", "numpy", "scipy",
|
||||||
"python-dateutil", "prettytable", "h5py", "pydaqmx", "pyelftools"
|
"python-dateutil", "prettytable", "h5py", "pydaqmx", "pyelftools",
|
||||||
|
"quamash", "pyqtgraph"
|
||||||
]
|
]
|
||||||
|
|
||||||
scripts = [
|
scripts = [
|
||||||
"artiq_client=artiq.frontend.artiq_client:main",
|
"artiq_client=artiq.frontend.artiq_client:main",
|
||||||
"artiq_compile=artiq.frontend.artiq_compile:main",
|
"artiq_compile=artiq.frontend.artiq_compile:main",
|
||||||
"artiq_ctlmgr=artiq.frontend.artiq_ctlmgr:main",
|
"artiq_ctlmgr=artiq.frontend.artiq_ctlmgr:main",
|
||||||
|
"artiq_gui=artiq.frontend.artiq_gui:main",
|
||||||
"artiq_master=artiq.frontend.artiq_master:main",
|
"artiq_master=artiq.frontend.artiq_master:main",
|
||||||
"artiq_mkfs=artiq.frontend.artiq_mkfs:main",
|
"artiq_mkfs=artiq.frontend.artiq_mkfs:main",
|
||||||
"artiq_rpctool=artiq.frontend.artiq_rpctool:main",
|
"artiq_rpctool=artiq.frontend.artiq_rpctool:main",
|
||||||
|
@ -25,13 +26,6 @@ scripts = [
|
||||||
"thorlabs_tcube_controller=artiq.frontend.thorlabs_tcube_controller:main",
|
"thorlabs_tcube_controller=artiq.frontend.thorlabs_tcube_controller:main",
|
||||||
]
|
]
|
||||||
|
|
||||||
if os.getenv("ARTIQ_GUI") == "1":
|
|
||||||
requirements += ["pygobject", "gbulb", "cairoplot"]
|
|
||||||
scripts += [
|
|
||||||
"artiq_gui=artiq.frontend.artiq_gui:main"
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name="artiq",
|
name="artiq",
|
||||||
version="0.0+dev",
|
version="0.0+dev",
|
||||||
|
@ -43,14 +37,9 @@ setup(
|
||||||
license="BSD",
|
license="BSD",
|
||||||
install_requires=requirements,
|
install_requires=requirements,
|
||||||
extras_require={},
|
extras_require={},
|
||||||
dependency_links=[
|
|
||||||
"git+https://github.com/m-labs/gbulb.git#egg=gbulb",
|
|
||||||
"git+https://github.com/m-labs/cairoplot3.git#egg=cairoplot"
|
|
||||||
],
|
|
||||||
packages=find_packages(),
|
packages=find_packages(),
|
||||||
namespace_packages=[],
|
namespace_packages=[],
|
||||||
test_suite="artiq.test",
|
test_suite="artiq.test",
|
||||||
package_data={"artiq": [os.path.join("gui", "icon.png")]},
|
|
||||||
ext_modules=[],
|
ext_modules=[],
|
||||||
entry_points={
|
entry_points={
|
||||||
"console_scripts": scripts,
|
"console_scripts": scripts,
|
||||||
|
|
Loading…
Reference in New Issue