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: 8f6c4451ac88
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: e45c089428f3
Choose a head ref
  • 2 commits
  • 9 files changed
  • 1 contributor

Commits on Sep 4, 2016

  1. Copy the full SHA
    549e09e View commit details
  2. Copy the full SHA
    e45c089 View commit details
6 changes: 6 additions & 0 deletions RELEASE_NOTES.rst
Original file line number Diff line number Diff line change
@@ -3,6 +3,12 @@
Release notes
=============

3.0 (unreleased)
----------------

* The --embed option of applets is replaced with the environment variable
ARTIQ_APPLET_EMBED.

2.0rc1
------

19 changes: 8 additions & 11 deletions artiq/applets/simple.py
Original file line number Diff line number Diff line change
@@ -94,10 +94,6 @@ def __init__(self, main_widget_class, cmd_description=None,
"--port", default=3250, type=int,
help="TCP port to connect to")

self.argparser.add_argument(
"--embed", default=None, help="embed into GUI",
metavar="IPC_ADDRESS")

self._arggroup_datasets = self.argparser.add_argument_group("datasets")

self.dataset_args = set()
@@ -114,6 +110,7 @@ def add_dataset(self, name, help=None, required=True):

def args_init(self):
self.args = self.argparser.parse_args()
self.embed = os.getenv("ARTIQ_APPLET_EMBED")
self.datasets = {getattr(self.args, arg.replace("-", "_"))
for arg in self.dataset_args}

@@ -123,17 +120,17 @@ def quamash_init(self):
asyncio.set_event_loop(self.loop)

def ipc_init(self):
if self.args.embed is not None:
self.ipc = AppletIPCClient(self.args.embed)
if self.embed is not None:
self.ipc = AppletIPCClient(self.embed)
self.loop.run_until_complete(self.ipc.connect())

def ipc_close(self):
if self.args.embed is not None:
if self.embed is not None:
self.ipc.close()

def create_main_widget(self):
self.main_widget = self.main_widget_class(self.args)
if self.args.embed is not None:
if self.embed is not None:
self.ipc.set_close_cb(self.main_widget.close)
if os.name == "nt":
# HACK: if the window has a frame, there will be garbage
@@ -166,7 +163,7 @@ def sub_init(self, data):
return data

def filter_mod(self, mod):
if self.args.embed is not None:
if self.embed is not None:
# the parent already filters for us
return True

@@ -201,7 +198,7 @@ def sub_mod(self, mod):
self.emit_data_changed(self.data, [mod])

def subscribe(self):
if self.args.embed is None:
if self.embed is None:
self.subscriber = Subscriber("datasets",
self.sub_init, self.sub_mod)
self.loop.run_until_complete(self.subscriber.connect(
@@ -210,7 +207,7 @@ def subscribe(self):
self.ipc.subscribe(self.datasets, self.sub_init, self.sub_mod)

def unsubscribe(self):
if self.args.embed is None:
if self.embed is None:
self.loop.run_until_complete(self.subscriber.close())

def run(self):
89 changes: 89 additions & 0 deletions artiq/dashboard/applets_ccb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import logging

from PyQt5 import QtCore, QtWidgets

from artiq.gui import applets


logger = logging.getLogger(__name__)


class AppletsCCBDock(applets.AppletsDock):
def __init__(self, *args, **kwargs):
applets.AppletsDock.__init__(self, *args, **kwargs)

sep = QtWidgets.QAction(self.table)
sep.setSeparator(True)
self.table.addAction(sep)
self.listen_action = QtWidgets.QAction(
"Listen to client control broadcasts", self.table)
self.listen_action.setCheckable(True)
self.table.addAction(self.listen_action)

def locate_applet(self, name, group, create_groups):
if group is None:
group = []
elif isinstance(group, str):
group = [group]

parent = self.table.invisibleRootItem()
for g in group:
new_parent = None
for i in range(parent.childCount()):
child = parent.child(i)
if child.ty == "group" and child.text(1) == g:
new_parent = child
break
if new_parent is None:
if create_groups:
new_parent = self.new_group(g, parent)
else:
return None, None
parent = new_parent

applet = None
for i in range(parent.childCount()):
child = parent.child(i)
if child.ty == "applet" and child.text(1) == name:
applet = child
break
return parent, applet

def ccb_create_applet(self, name, command_or_code, group=None, is_code=False):
if not self.listen_action.isChecked():
return
parent, applet = self.locate_applet(name, group, True)
if applet is None:
applet = self.new(name=name, command=command_or_code, parent=parent)
else:
applet.setText(2, command_or_code)
applet.setCheckState(0, QtCore.Qt.Checked)

def ccb_disable_applet(self, name, group=None):
if not self.listen_action.isChecked():
return
parent, applet = self.locate_applet(name, group, False)
if applet is not None:
applet.setCheckState(0, QtCore.Qt.Unchecked)

def ccb_notify(self, message):
try:
service = message["service"]
args = message["args"]
kwargs = message["kwargs"]
if service == "create_applet":
self.ccb_create_applet(*args, **kwargs)
elif service == "disable_applet":
self.ccb_disable_applet(*args, **kwargs)
except:
logger.error("failed to process CCB", exc_info=True)

def save_state(self):
return {
"applets": applets.AppletsDock.save_state(self),
"listen": self.listen_action.isChecked()
}

def restore_state(self, state):
applets.AppletsDock.restore_state(self, state["applets"])
self.listen_action.setChecked(state["listen"])
6 changes: 6 additions & 0 deletions artiq/examples/master/repository/flopping_f_simulation.py
Original file line number Diff line number Diff line change
@@ -29,6 +29,7 @@ def build(self):
0.1, min=0, max=100, step=0.01))

self.setattr_device("scheduler")
self.setattr_device("ccb")

def run(self):
l = len(self.frequency_scan)
@@ -41,6 +42,11 @@ def run(self):
self.set_dataset("flopping_f_fit", np.full(l, np.nan),
broadcast=True, save=False)

self.ccb.issue("create_applet", "flopping_f",
"${artiq_applet}plot_xy "
"flopping_f_brightness --x flopping_f_frequency "
"--fit flopping_f_fit")

for i, f in enumerate(self.frequency_scan):
m_brightness = model(f, self.F0) + self.noise_amplitude*random.random()
self.mutate_dataset("flopping_f_frequency", i, f)
20 changes: 12 additions & 8 deletions artiq/frontend/artiq_dashboard.py
Original file line number Diff line number Diff line change
@@ -15,9 +15,9 @@
from artiq.protocols.pc_rpc import AsyncioClient
from artiq.protocols.broadcast import Receiver
from artiq.gui.models import ModelSubscriber
from artiq.gui import state, applets, log
from artiq.gui import state, log
from artiq.dashboard import (experiments, shortcuts, explorer,
moninj, datasets, schedule)
moninj, datasets, schedule, applets_ccb)


def get_argparser():
@@ -119,10 +119,13 @@ def main():
atexit_register_coroutine(subscriber.close)
sub_clients[notifier_name] = subscriber

log_receiver = Receiver("log", [])
loop.run_until_complete(log_receiver.connect(
args.server, args.port_broadcast))
atexit_register_coroutine(log_receiver.close)
broadcast_clients = dict()
for target in "log", "ccb":
client = Receiver(target, [])
loop.run_until_complete(client.connect(
args.server, args.port_broadcast))
atexit_register_coroutine(client.close)
broadcast_clients[target] = client

# initialize main window
main_window = MainWindow(args.server)
@@ -152,9 +155,10 @@ def main():
rpc_clients["dataset_db"])
smgr.register(d_datasets)

d_applets = applets.AppletsDock(main_window, sub_clients["datasets"])
d_applets = applets_ccb.AppletsCCBDock(main_window, sub_clients["datasets"])
atexit_register_coroutine(d_applets.stop)
smgr.register(d_applets)
broadcast_clients["ccb"].notify_cbs.append(d_applets.ccb_notify)

d_ttl_dds = moninj.MonInj()
loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify))
@@ -166,7 +170,7 @@ def main():

logmgr = log.LogDockManager(main_window)
smgr.register(logmgr)
log_receiver.notify_cbs.append(logmgr.append_message)
broadcast_clients["log"].notify_cbs.append(logmgr.append_message)
widget_log_handler.callback = logmgr.append_message

# lay out docks
10 changes: 9 additions & 1 deletion artiq/frontend/artiq_master.py
Original file line number Diff line number Diff line change
@@ -69,6 +69,13 @@ def main():

log_forwarder.callback = (lambda msg:
server_broadcast.broadcast("log", msg))
def ccb_issue(service, *args, **kwargs):
msg = {
"service": service,
"args": args,
"kwargs": kwargs
}
server_broadcast.broadcast("ccb", msg)

device_db = DeviceDB(args.device_db)
dataset_db = DatasetDB(args.dataset_db)
@@ -96,7 +103,8 @@ def main():
"scheduler_delete": scheduler.delete,
"scheduler_request_termination": scheduler.request_termination,
"scheduler_get_status": scheduler.get_status,
"scheduler_check_pause": scheduler.check_pause
"scheduler_check_pause": scheduler.check_pause,
"ccb_issue": ccb_issue,
})
experiment_db.scan_repository_async()

9 changes: 8 additions & 1 deletion artiq/frontend/artiq_run.py
Original file line number Diff line number Diff line change
@@ -118,6 +118,12 @@ def pause(self):
pass


class DummyCCB:
def issue(self, service, *args, **kwargs):
logger.info("CCB for service '%s' (args %s, kwargs %s)",
service, args, kwargs)


def get_argparser(with_file=True):
parser = argparse.ArgumentParser(
description="Local experiment running tool")
@@ -183,7 +189,8 @@ def run(with_file=False):
init_logger(args)

device_mgr = DeviceManager(DeviceDB(args.device_db),
virtual_devices={"scheduler": DummyScheduler()})
virtual_devices={"scheduler": DummyScheduler(),
"ccb": DummyCCB()})
dataset_db = DatasetDB(args.dataset_db)
dataset_mgr = DatasetManager(dataset_db)

28 changes: 13 additions & 15 deletions artiq/gui/applets.py
Original file line number Diff line number Diff line change
@@ -118,17 +118,16 @@ async def start(self):
self.starting_stopping = True
try:
self.ipc = AppletIPCServer(self.datasets_sub)
if "$ipc_address" not in self.command:
logger.warning("IPC address missing from command for %s",
self.applet_name)
command_tpl = string.Template(self.command)
python = sys.executable.replace("\\", "\\\\")
command = command_tpl.safe_substitute(
python=sys.executable.replace("\\", "\\\\"),
ipc_address=self.ipc.get_address().replace("\\", "\\\\")
python=python,
artiq_applet=python + " -m artiq.applets."
)
logger.debug("starting command %s for %s", command, self.applet_name)
env = os.environ.copy()
env["PYTHONUNBUFFERED"] = "1"
env["ARTIQ_APPLET_EMBED"] = self.ipc.get_address()
try:
await self.ipc.create_subprocess(
*shlex.split(command),
@@ -194,20 +193,19 @@ async def restart(self):


_templates = [
("Big number", "$python -m artiq.applets.big_number "
"--embed $ipc_address NUMBER_DATASET"),
("Histogram", "$python -m artiq.applets.plot_hist "
"--embed $ipc_address COUNTS_DATASET "
("Big number", "${artiq_applet}big_number "
"NUMBER_DATASET"),
("Histogram", "${artiq_applet}plot_hist "
"COUNTS_DATASET "
"--x BIN_BOUNDARIES_DATASET"),
("XY", "$python -m artiq.applets.plot_xy "
"--embed $ipc_address Y_DATASET --x X_DATASET "
("XY", "${artiq_applet}plot_xy "
"Y_DATASET --x X_DATASET "
"--error ERROR_DATASET --fit FIT_DATASET"),
("XY + Histogram", "$python -m artiq.applets.plot_xy_hist "
"--embed $ipc_address X_DATASET "
("XY + Histogram", "${artiq_applet}plot_xy_hist "
"X_DATASET "
"HIST_BIN_BOUNDARIES_DATASET "
"HISTS_COUNTS_DATASET"),
("Image", "$python -m artiq.applets.image "
"--embed $ipc_address IMG_DATASET"),
("Image", "${artiq_applet}image IMG_DATASET"),
]


7 changes: 6 additions & 1 deletion artiq/master/worker_impl.py
Original file line number Diff line number Diff line change
@@ -106,6 +106,10 @@ def check_pause(self, rid=None) -> TBool:
return self._check_pause(rid)


class CCB:
issue = staticmethod(make_parent_action("ccb_issue"))


def get_exp(file, class_name):
module = file_import(file, prefix="artiq_worker_")
if class_name is None:
@@ -189,7 +193,8 @@ def main():
repository_path = None

device_mgr = DeviceManager(ParentDeviceDB,
virtual_devices={"scheduler": Scheduler()})
virtual_devices={"scheduler": Scheduler(),
"ccb": CCB()})
dataset_mgr = DatasetManager(ParentDatasetDB)

import_cache.install_hook()