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: 7a2405146a63
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: 7ce9fc714aef
Choose a head ref
  • 4 commits
  • 6 files changed
  • 1 contributor

Commits on Jul 9, 2016

  1. Copy the full SHA
    cfb9fb8 View commit details
  2. worker_impl: style

    jordens committed Jul 9, 2016
    Copy the full SHA
    9ca27e6 View commit details
  3. 4
    Copy the full SHA
    48a42cd View commit details
  4. Copy the full SHA
    7ce9fc7 View commit details
Showing with 88 additions and 42 deletions.
  1. +17 −1 artiq/browser/datasets.py
  2. +18 −15 artiq/browser/experiments.py
  3. +29 −13 artiq/browser/files.py
  4. +14 −8 artiq/frontend/artiq_browser.py
  5. +6 −2 artiq/language/environment.py
  6. +4 −3 artiq/master/worker_impl.py
18 changes: 17 additions & 1 deletion artiq/browser/datasets.py
Original file line number Diff line number Diff line change
@@ -43,8 +43,20 @@ def __init__(self, datasets_sub, master_host, master_port):
QtWidgets.QAbstractItemView.SingleSelection)
grid.addWidget(self.table, 1, 0)

metadata_grid = LayoutWidget()
self.metadata = {}
for i, label in enumerate("artiq_version repo_rev file class_name "
"rid start_time".split()):
metadata_grid.addWidget(QtWidgets.QLabel(label), i, 0)
v = QtWidgets.QLabel()
v.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse)
metadata_grid.addWidget(v, i, 1)
self.metadata[label] = v
grid.addWidget(metadata_grid, 2, 0)

self.table.setContextMenuPolicy(QtCore.Qt.ActionsContextMenu)
upload_action = QtWidgets.QAction("Upload dataset to master", self.table)
upload_action = QtWidgets.QAction("Upload dataset to master",
self.table)
upload_action.triggered.connect(self.upload_clicked)
self.table.addAction(upload_action)

@@ -59,6 +71,10 @@ def _search_datasets(self):
self.table_model_filter.setFilterFixedString(
self.search.displayText())

def metadata_changed(self, new):
for k, v in new.items():
self.metadata[k].setText("{}".format(v))

def set_model(self, model):
self.table_model = model
self.table_model_filter = QtCore.QSortFilterProxyModel()
33 changes: 18 additions & 15 deletions artiq/browser/experiments.py
Original file line number Diff line number Diff line change
@@ -84,8 +84,17 @@ def __init__(self, dock):
QtWidgets.QStyle.SP_BrowserReload))
recompute_arguments.clicked.connect(self._recompute_arguments_clicked)

load = QtWidgets.QPushButton("Set arguments from HDF5")
load.setToolTip("Set arguments from currently selected HDF5 "
"file (Ctrl+Space)")
load.setIcon(QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_DialogApplyButton))
load.setShortcut("CTRL+SPACE")
load.clicked.connect(self._load_clicked)

buttons = LayoutWidget()
buttons.addWidget(recompute_arguments, 1, 1)
buttons.addWidget(load, 2, 1)
for i, s in enumerate((1, 0, 0, 1)):
buttons.layout.setColumnStretch(i, s)
self.setItemWidget(widget_item, 1, buttons)
@@ -104,6 +113,9 @@ def _get_group(self, name):
self._groups[name] = group
return group

def _load_clicked(self):
asyncio.ensure_future(self._dock.load_hdf5_task())

def _recompute_arguments_clicked(self):
asyncio.ensure_future(self._dock._recompute_arguments())

@@ -194,15 +206,6 @@ def update_log_level(index):
log_level.currentIndexChanged.connect(update_log_level)
self.log_level = log_level

load = QtWidgets.QPushButton("Set arguments")
load.setToolTip("Set arguments from currently selected HDF5 "
"file (Ctrl+Space)")
load.setIcon(QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_DialogApplyButton))
load.setShortcut("CTRL+SPACE")
load.clicked.connect(self._load_clicked)
self.layout.addWidget(load, 1, 4)

run = QtWidgets.QPushButton("Analyze")
run.setIcon(QtWidgets.QApplication.style().standardIcon(
QtWidgets.QStyle.SP_DialogOkButton))
@@ -259,7 +262,12 @@ async def _recompute_arguments(self, overrides={}):
self.argeditor = _ArgumentEditor(self)
self.layout.addWidget(self.argeditor, 0, 0, 1, 5)

async def load_hdf5_task(self, filename):
async def load_hdf5_task(self, filename=None):
if filename is None:
if self._area.dataset is None:
return
filename = self._area.dataset

try:
with h5py.File(filename, "r") as f:
expid = f["expid"][()]
@@ -280,11 +288,6 @@ async def load_hdf5_task(self, filename):

await self._recompute_arguments(arguments)

def _load_clicked(self):
if self._area.dataset is None:
return
asyncio.ensure_future(self.load_hdf5_task(self._area.dataset))

def _run_clicked(self):
class_name, file = self.expurl.split("@", maxsplit=1)
expid = {
42 changes: 29 additions & 13 deletions artiq/browser/files.py
Original file line number Diff line number Diff line change
@@ -118,8 +118,9 @@ def data(self, idx, role):
class FilesDock(QtWidgets.QDockWidget):
dataset_activated = QtCore.pyqtSignal(str)
dataset_changed = QtCore.pyqtSignal(str)
metadata_changed = QtCore.pyqtSignal(dict)

def __init__(self, datasets, browse_root="", select=None):
def __init__(self, datasets, browse_root="", restore_selection=True):
QtWidgets.QDockWidget.__init__(self, "Files")
self.setObjectName("Files")
self.setFeatures(self.DockWidgetMovable | self.DockWidgetFloatable)
@@ -168,13 +169,7 @@ def __init__(self, datasets, browse_root="", select=None):
rev_copy.setShortcutContext(QtCore.Qt.WidgetShortcut)
self.rl.addAction(rev_copy)

self.restore_selected = select is None
if select is not None:
f = os.path.abspath(select)
if os.path.isdir(f):
self.select_dir(f)
else:
self.select_file(f)
self.restore_selection = restore_selection

def _copy_repo_rev(self):
pass
@@ -190,10 +185,24 @@ def list_current_changed(self, current, previous):
return
logger.debug("loading datasets from %s", info.filePath())
with f:
if "datasets" not in f:
return
rd = {k: (True, v.value) for k, v in f["datasets"].items()}
self.datasets.init(rd)
try:
expid = pyon.decode(f["expid"].value)
start_time = datetime.fromtimestamp(f["start_time"].value)
v = {
"artiq_version": f["artiq_version"].value,
"repo_rev": expid["repo_rev"],
"file": expid["file"],
"class_name": expid["class_name"],
"rid": f["rid"].value,
"start_time": start_time,
}
self.metadata_changed.emit(v)
except:
logger.warning("unable to read metadata from %s",
info.filePath(), exc_info=True)
if "datasets" in f:
rd = {k: (True, v.value) for k, v in f["datasets"].items()}
self.datasets.init(rd)
self.dataset_changed.emit(info.filePath())

def list_activated(self, idx):
@@ -206,6 +215,13 @@ def list_activated(self, idx):
self.rt.expand(idx)
self.rt.setCurrentIndex(idx)

def select(self, path):
f = os.path.abspath(path)
if os.path.isdir(f):
self.select_dir(f)
else:
self.select_file(f)

def select_dir(self, path):
if not os.path.exists(path):
return
@@ -247,7 +263,7 @@ def save_state(self):
}

def restore_state(self, state):
if self.restore_selected:
if self.restore_selection:
self.select_dir(state["dir"])
self.select_file(state["file"])
self.splitter.restoreState(QtCore.QByteArray(state["splitter"]))
22 changes: 14 additions & 8 deletions artiq/frontend/artiq_browser.py
Original file line number Diff line number Diff line change
@@ -45,7 +45,7 @@ def get_argparser():


class Browser(QtWidgets.QMainWindow):
def __init__(self, smgr, datasets_sub, browse_root, select,
def __init__(self, smgr, datasets_sub, browse_root, restore_selection,
master_host, master_port):
QtWidgets.QMainWindow.__init__(self)
smgr.register(self)
@@ -70,7 +70,8 @@ def __init__(self, smgr, datasets_sub, browse_root, select,
QtCore.Qt.ScrollBarAsNeeded)
self.setCentralWidget(self.experiments)

self.files = files.FilesDock(datasets_sub, browse_root, select=select)
self.files = files.FilesDock(datasets_sub, browse_root,
restore_selection)
smgr.register(self.files)

self.files.dataset_activated.connect(
@@ -85,6 +86,7 @@ def __init__(self, smgr, datasets_sub, browse_root, select,
self.datasets = datasets.DatasetsDock(
datasets_sub, master_host, master_port)
smgr.register(self.datasets)
self.files.metadata_changed.connect(self.datasets.metadata_changed)

self.log = log.LogDock(None, "log")
smgr.register(self.log)
@@ -145,20 +147,24 @@ def main():

smgr = state.StateManager(args.db_file)

main_window = Browser(smgr, datasets_sub, args.browse_root,
args.select, args.server, args.port)
widget_log_handler.callback = main_window.log.append_message
browser = Browser(smgr, datasets_sub, args.browse_root,
args.select is not None, args.server,
args.port)
widget_log_handler.callback = browser.log.append_message

if args.select is not None:
browser.files.select(args.select)

if os.name == "nt":
# HACK: show the main window before creating applets.
# Otherwise, the windows of those applets that are in detached
# QDockWidgets fail to be embedded.
main_window.show()
browser.show()
smgr.load()
smgr.start()
atexit_register_coroutine(smgr.stop)
main_window.show()
loop.run_until_complete(main_window.exit_request.wait())
browser.show()
loop.run_until_complete(browser.exit_request.wait())


if __name__ == "__main__":
8 changes: 6 additions & 2 deletions artiq/language/environment.py
Original file line number Diff line number Diff line change
@@ -213,8 +213,12 @@ def build(self):
Other initialization steps such as requesting devices may also be
performed here.
When the repository is scanned, any requested devices and arguments
are set to ``None``.
There are two situations where the requested devices are replaced by
``DummyDevice()`` and arguments are set to their defaults (or ``None``)
instead: when the repository is scanned to build the list of
available experiments and when the dataset browser ``artiq_browser``
is used to open or run the analysis stage of an experiment. Do not
rely on being able to operate on devices or arguments in ``build()``.
Datasets are read-only in this method.
7 changes: 4 additions & 3 deletions artiq/master/worker_impl.py
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
from artiq.protocols import pipe_ipc, pyon
from artiq.protocols.packed_exceptions import raise_packed_exc
from artiq.tools import multiline_log_config, file_import
from artiq.master.worker_db import DeviceManager, DatasetManager
from artiq.master.worker_db import DeviceManager, DatasetManager, DummyDevice
from artiq.language.environment import (is_experiment, TraceArgumentManager,
ProcessArgumentManager)
from artiq.language.core import set_watchdog_factory, TerminationRequested
@@ -98,6 +98,7 @@ def set_run_info(self, rid, pipeline_name, expid, priority):
self.priority = priority

_check_pause = staticmethod(make_parent_action("scheduler_check_pause"))

def check_pause(self, rid=None) -> TBool:
if rid is None:
rid = self.rid
@@ -124,7 +125,7 @@ class ExamineDeviceMgr:
get_device_db = make_parent_action("get_device_db")

def get(name):
return None
return DummyDevice()


def examine(device_mgr, dataset_mgr, file):
@@ -140,7 +141,7 @@ def examine(device_mgr, dataset_mgr, file):
if name[-1] == ".":
name = name[:-1]
argument_mgr = TraceArgumentManager()
exp_inst = exp_class((device_mgr, dataset_mgr, argument_mgr))
exp_class((device_mgr, dataset_mgr, argument_mgr))
arginfo = OrderedDict(
(k, (proc.describe(), group))
for k, (proc, group) in argument_mgr.requested_args.items())