Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 39c6bc940cc5
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: dd7920f0c3ea
Choose a head ref
  • 4 commits
  • 8 files changed
  • 1 contributor

Commits on Jul 17, 2015

  1. Copy the full SHA
    4907991 View commit details
  2. Copy the full SHA
    6b36d93 View commit details
  3. Copy the full SHA
    2576036 View commit details
  4. Copy the full SHA
    dd7920f View commit details
8 changes: 8 additions & 0 deletions artiq/frontend/artiq_client.py
Original file line number Diff line number Diff line change
@@ -82,6 +82,9 @@ def get_argparser():
"what",
help="select object to show: schedule/devices/parameters")

parser_scan_repository = subparsers.add_parser(
"scan-repository", help="rescan repository")

return parser


@@ -134,6 +137,10 @@ def _action_del_parameter(remote, args):
remote.delete(args.name)


def _action_scan_repository(remote, args):
remote.scan_async()


def _show_schedule(schedule):
clear_screen()
if schedule:
@@ -228,6 +235,7 @@ def main():
"del_device": "master_ddb",
"set_parameter": "master_pdb",
"del_parameter": "master_pdb",
"scan_repository": "master_repository"
}[action]
remote = Client(args.server, port, target_name)
try:
2 changes: 1 addition & 1 deletion artiq/frontend/artiq_gui.py
Original file line number Diff line number Diff line change
@@ -66,7 +66,7 @@ def main():
win.resize(1400, 800)
win.setWindowTitle("ARTIQ")

d_explorer = ExplorerDock(status_bar, schedule_ctl)
d_explorer = ExplorerDock(win, status_bar, schedule_ctl)
loop.run_until_complete(d_explorer.sub_connect(
args.server, args.port_notify))
atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close()))
7 changes: 4 additions & 3 deletions artiq/frontend/artiq_master.py
Original file line number Diff line number Diff line change
@@ -56,18 +56,19 @@ def main():
scheduler.start()
atexit.register(lambda: loop.run_until_complete(scheduler.stop()))

repository = Repository()
repository.scan_async()

server_control = Server({
"master_ddb": ddb,
"master_pdb": pdb,
"master_schedule": scheduler,
"master_repository": repository
})
loop.run_until_complete(server_control.start(
args.bind, args.port_control))
atexit.register(lambda: loop.run_until_complete(server_control.stop()))

repository = Repository()
loop.run_until_complete(repository.scan())

server_notify = Publisher({
"schedule": scheduler.notifier,
"devices": ddb.data,
83 changes: 75 additions & 8 deletions artiq/gui/explorer.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import asyncio
import traceback

from quamash import QtGui, QtCore
from pyqtgraph import dockarea
from pyqtgraph import LayoutWidget

from artiq.protocols.sync_struct import Subscriber
from artiq.protocols import pyon
from artiq.gui.tools import DictSyncModel


@@ -21,20 +23,68 @@ def convert(self, k, v, column):
return k


class _FreeValueEntry(QtGui.QLineEdit):
def __init__(self, procdesc):
QtGui.QLineEdit.__init__(self)
if "default" in procdesc:
self.insert(pyon.encode(procdesc["default"]))

def get_argument_value(self):
return pyon.decode(self.text())


_procty_to_entry = {
"FreeValue": _FreeValueEntry
}


class _ArgumentSetter(LayoutWidget):
def __init__(self, dialog_parent, arguments):
LayoutWidget.__init__(self)
self.dialog_parent = dialog_parent

if not arguments:
self.addWidget(QtGui.QLabel("No arguments"), 0, 0)

self._args_to_entries = dict()
for n, (name, procdesc) in enumerate(arguments):
self.addWidget(QtGui.QLabel(name), n, 0)
entry = _procty_to_entry[procdesc["ty"]](procdesc)
self.addWidget(entry, n, 1)
self._args_to_entries[name] = entry

def get_argument_values(self):
r = dict()
for arg, entry in self._args_to_entries.items():
try:
r[arg] = entry.get_argument_value()
except:
msgbox = QtGui.QMessageBox(self.dialog_parent)
msgbox.setWindowTitle("Error")
msgbox.setText("Failed to obtain value for argument '{}'.\n{}"
.format(arg, traceback.format_exc()))
msgbox.setStandardButtons(QtGui.QMessageBox.Ok)
msgbox.show()
return None
return r


class ExplorerDock(dockarea.Dock):
def __init__(self, status_bar, schedule_ctl):
def __init__(self, dialog_parent, status_bar, schedule_ctl):
dockarea.Dock.__init__(self, "Explorer", size=(1500, 500))

self.dialog_parent = dialog_parent
self.status_bar = status_bar
self.schedule_ctl = schedule_ctl

splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
self.addWidget(splitter)
self.splitter = QtGui.QSplitter(QtCore.Qt.Horizontal)
self.addWidget(self.splitter)

grid = LayoutWidget()
splitter.addWidget(grid)
self.splitter.addWidget(grid)

self.el = QtGui.QListView()
self.el.selectionChanged = self.update_argsetter
grid.addWidget(self.el, 0, 0, colspan=4)

self.datetime = QtGui.QDateTimeEdit()
@@ -63,8 +113,22 @@ def __init__(self, status_bar, schedule_ctl):
grid.addWidget(submit, 3, 0, colspan=4)
submit.clicked.connect(self.submit_clicked)

placeholder = QtGui.QWidget()
splitter.addWidget(placeholder)
self.argsetter = _ArgumentSetter(self.dialog_parent, [])
self.splitter.addWidget(self.argsetter)
self.splitter.setSizes([grid.minimumSizeHint().width(), 1000])

def update_argsetter(self, selected, deselected):
selected = selected.indexes()
if selected:
row = selected[0].row()
key = self.explist_model.row_to_key[row]
expinfo = self.explist_model.backing_store[key]
arguments = expinfo["arguments"]
sizes = self.splitter.sizes()
self.argsetter.deleteLater()
self.argsetter = _ArgumentSetter(self.dialog_parent, arguments)
self.splitter.insertWidget(1, self.argsetter)
self.splitter.setSizes(sizes)

def enable_duedate(self):
self.datetime_en.setChecked(True)
@@ -106,7 +170,10 @@ def submit_clicked(self):
due_date = self.datetime.dateTime().toMSecsSinceEpoch()/1000
else:
due_date = None
arguments = self.argsetter.get_argument_values()
if arguments is None:
return
asyncio.async(self.submit(self.pipeline.text(),
expinfo["file"], expinfo["class_name"],
dict(), self.priority.value(), due_date,
self.flush.isChecked()))
arguments, self.priority.value(),
due_date, self.flush.isChecked()))
3 changes: 2 additions & 1 deletion artiq/language/environment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from collections import OrderedDict
from inspect import isclass


@@ -41,7 +42,7 @@ class HasEnvironment:
parameters, results, arguments)."""
def __init__(self, dmgr=None, pdb=None, rdb=None, *,
param_override=dict(), default_arg_none=False, **kwargs):
self.requested_args = dict()
self.requested_args = OrderedDict()

self.__dmgr = dmgr
self.__pdb = pdb
8 changes: 8 additions & 0 deletions artiq/master/repository.py
Original file line number Diff line number Diff line change
@@ -54,8 +54,16 @@ def _sync_explist(target, source):
class Repository:
def __init__(self):
self.explist = Notifier(dict())
self._scanning = False

@asyncio.coroutine
def scan(self):
if self._scanning:
return
self._scanning = True
new_explist = yield from _scan_experiments()
_sync_explist(self.explist, new_explist)
self._scanning = False

def scan_async(self):
asyncio.async(self.scan())
4 changes: 2 additions & 2 deletions artiq/master/worker_impl.py
Original file line number Diff line number Diff line change
@@ -127,8 +127,8 @@ def examine(dmgr, pdb, rdb, file):
if name[-1] == ".":
name = name[:-1]
exp_inst = exp_class(dmgr, pdb, rdb, default_arg_none=True)
arguments = {k: v.describe()
for k, v in exp_inst.requested_args.items()}
arguments = [(k, v.describe())
for k, v in exp_inst.requested_args.items()]
register_experiment(class_name, name, arguments)


7 changes: 1 addition & 6 deletions artiq/protocols/sync_struct.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,6 @@
Structures must be PYON serializable and contain only lists, dicts, and
immutable types. Lists and dicts can be nested arbitrarily.
"""

import asyncio
@@ -23,9 +22,7 @@


def process_mod(target, mod):
"""Apply a *mod* to the target, mutating it.
"""
"""Apply a *mod* to the target, mutating it."""
for key in mod["path"]:
target = getitem(target, key)
action = mod["action"]
@@ -134,7 +131,6 @@ class Notifier:
:param backing_struct: Structure to encapsulate. For convenience, it
also becomes available as the ``read`` property of the ``Notifier``.
"""
def __init__(self, backing_struct, root=None, path=[]):
self.read = backing_struct
@@ -203,7 +199,6 @@ class Publisher(AsyncioServer):
:param notifiers: A dictionary containing the notifiers to associate with
the ``Publisher``. The keys of the dictionary are the names of the
notifiers to be used with ``Subscriber``.
"""
def __init__(self, notifiers):
AsyncioServer.__init__(self)