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: a6a476593e3c
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: 14cf244c0a94
Choose a head ref
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on Jun 5, 2015

  1. Copy the full SHA
    9f90795 View commit details
  2. Copy the full SHA
    14cf244 View commit details
Showing with 209 additions and 24 deletions.
  1. +23 −6 artiq/frontend/artiq_gui.py
  2. +1 −1 artiq/gui/explorer.py
  3. +167 −0 artiq/gui/moninj.py
  4. +1 −1 artiq/gui/parameters.py
  5. +2 −16 artiq/master/scheduler.py
  6. +15 −0 artiq/tools.py
29 changes: 23 additions & 6 deletions artiq/frontend/artiq_gui.py
Original file line number Diff line number Diff line change
@@ -11,10 +11,12 @@

from artiq.protocols.file_db import FlatFileDB
from artiq.protocols.pc_rpc import AsyncioClient
from artiq.protocols.sync_struct import Subscriber
from artiq.gui.explorer import ExplorerDock
from artiq.gui.moninj import MonInjTTLDock, MonInjDDSDock
from artiq.gui.parameters import ParametersDock
from artiq.gui.log import LogDock
from artiq.gui.schedule import ScheduleDock
from artiq.gui.log import LogDock


def get_argparser():
@@ -59,26 +61,41 @@ def main():
win.setWindowTitle("ARTIQ")

d_explorer = ExplorerDock(status_bar, schedule_ctl)
area.addDock(d_explorer, "top")
loop.run_until_complete(d_explorer.sub_connect(
args.server, args.port_notify))
atexit.register(lambda: loop.run_until_complete(d_explorer.sub_close()))

d_ttl = MonInjTTLDock()
loop.run_until_complete(d_ttl.start())
atexit.register(lambda: loop.run_until_complete(d_ttl.stop()))
d_dds = MonInjDDSDock()
devices_sub = Subscriber("devices",
[d_ttl.init_devices, d_dds.init_devices])
loop.run_until_complete(
devices_sub.connect(args.server, args.port_notify))
atexit.register(
lambda: loop.run_until_complete(devices_sub.close()))

area.addDock(d_dds, "top")
area.addDock(d_ttl, "above", d_dds)
area.addDock(d_explorer, "above", d_ttl)

d_params = ParametersDock()
area.addDock(d_params, "right", d_explorer)
loop.run_until_complete(d_params.sub_connect(
args.server, args.port_notify))
atexit.register(lambda: loop.run_until_complete(d_params.sub_close()))

d_log = LogDock()
area.addDock(d_log, "bottom")

d_schedule = ScheduleDock(schedule_ctl)
area.addDock(d_schedule, "above", d_log)
loop.run_until_complete(d_schedule.sub_connect(
args.server, args.port_notify))
atexit.register(lambda: loop.run_until_complete(d_schedule.sub_close()))

d_log = LogDock()

area.addDock(d_log, "bottom")
area.addDock(d_schedule, "above", d_log)

win.show()
loop.run_forever()

2 changes: 1 addition & 1 deletion artiq/gui/explorer.py
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ def convert(self, k, v, column):

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

self.status_bar = status_bar
self.schedule_ctl = schedule_ctl
167 changes: 167 additions & 0 deletions artiq/gui/moninj.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import asyncio
import logging
import socket
import struct
from operator import itemgetter

from quamash import QtGui, QtCore
from pyqtgraph import dockarea

from artiq.tools import TaskObject


logger = logging.getLogger(__name__)


class _TTLWidget(QtGui.QFrame):
def __init__(self, force_out, name):
self.force_out = force_out

QtGui.QFrame.__init__(self)

self.setFrameShape(QtGui.QFrame.Panel)
self.setFrameShadow(QtGui.QFrame.Raised)

grid = QtGui.QGridLayout()
self.setLayout(grid)
label = QtGui.QLabel(name)
label.setAlignment(QtCore.Qt.AlignCenter)
grid.addWidget(label, 1, 1)

self._direction = QtGui.QLabel()
self._value = QtGui.QLabel()
self._direction.setAlignment(QtCore.Qt.AlignCenter)
self._value.setAlignment(QtCore.Qt.AlignCenter)
self.set_value(0, False, False)
grid.addWidget(self._direction, 2, 1)
grid.addWidget(self._value, 3, 1, 6, 1)

def set_value(self, value, oe, override):
value = "1" if value else "0"
if override:
value = "<b>" + value + "</b>"
color = " color=\"red\""
else:
color = ""
self._value.setText("<font size=\"9\"{}>{}</font>".format(
color, value))
oe = oe or self.force_out
direction = "OUT" if oe else "IN"
self._direction.setText("<font size=\"1\">" + direction + "</font>")


class _DeviceManager:
def __init__(self, init):
self.ddb = dict()
self.ttl_cb = lambda: None
self.ttl_widgets = dict()
for k, v in init.items():
self[k] = v

def __setitem__(self, k, v):
self.ddb[k] = v
if k in self.ttl_widgets:
del self[k]
if not isinstance(v, dict):
return
try:
if v["type"] == "local" and v["module"] == "artiq.coredevice.ttl":
channel = v["arguments"]["channel"]
force_out = v["class"] == "TTLOut"
self.ttl_widgets[channel] = _TTLWidget(force_out, k)
self.ttl_cb()
except KeyError:
pass

def __delitem__(self, k):
del self.ddb[k]
if k in self.ttl_widgets:
del self.ttl_widgets[k]
self.ttl_cb()

def get_core_addr(self):
try:
comm = self.ddb["comm"]
while isinstance(comm, str):
comm = self.ddb[comm]
return comm["arguments"]["host"]
except KeyError:
return None


class MonInjTTLDock(dockarea.Dock, TaskObject):
def __init__(self):
dockarea.Dock.__init__(self, "TTL", size=(1500, 500))
self.dm = _DeviceManager(dict())
self.transport = None

self.grid = QtGui.QGridLayout()
gridw = QtGui.QWidget()
gridw.setLayout(self.grid)
self.addWidget(gridw)

@asyncio.coroutine
def start(self):
loop = asyncio.get_event_loop()
yield from loop.create_datagram_endpoint(lambda: self,
family=socket.AF_INET)
TaskObject.start(self)

@asyncio.coroutine
def stop(self):
yield from TaskObject.stop(self)
if self.transport is not None:
self.transport.close()
self.transport = None

def connection_made(self, transport):
self.transport = transport

def datagram_received(self, data, addr):
ttl_levels, ttl_oes = struct.unpack(">QQ", data)
for channel, w in self.dm.ttl_widgets.items():
w.set_value(ttl_levels & (1 << channel),
ttl_oes & (1 << channel),
False)

def error_received(self, exc):
logger.warning("datagram endpoint error")

def connection_lost(self, exc):
self.transport = None

@asyncio.coroutine
def _do(self):
while True:
yield from asyncio.sleep(0.2)
ca = self.dm.get_core_addr()
if ca is None:
logger.warning("could not find core device address")
elif self.transport is None:
logger.warning("datagram endpoint not available")
else:
# MONINJ_REQ_MONITOR
self.transport.sendto(b"\x01", (ca, 3250))

def layout_ttl_widgets(self):
w = self.grid.itemAt(0)
while w is not None:
self.grid.removeItem(w)
w = self.grid.itemAt(0)
for i, (_, w) in enumerate(sorted(self.dm.ttl_widgets.items(),
key=itemgetter(0))):
self.grid.addWidget(w, i // 4, i % 4)

def init_devices(self, d):
self.dm = _DeviceManager(d)
self.dm.ttl_cb = self.layout_ttl_widgets
self.layout_ttl_widgets()
return self.dm


class MonInjDDSDock(dockarea.Dock):
def __init__(self):
dockarea.Dock.__init__(self, "DDS", size=(1500, 500))

def init_devices(self, d):
return d
2 changes: 1 addition & 1 deletion artiq/gui/parameters.py
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ def convert(self, k, v, column):

class ParametersDock(dockarea.Dock):
def __init__(self):
dockarea.Dock.__init__(self, "Parameters", size=(500, 300))
dockarea.Dock.__init__(self, "Parameters", size=(400, 300))

self.table = QtGui.QTableView()
self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
18 changes: 2 additions & 16 deletions artiq/master/scheduler.py
Original file line number Diff line number Diff line change
@@ -4,7 +4,8 @@
from time import time

from artiq.master.worker import Worker
from artiq.tools import asyncio_wait_or_cancel, asyncio_queue_peek, WaitSet
from artiq.tools import (asyncio_wait_or_cancel, asyncio_queue_peek,
TaskObject, WaitSet)
from artiq.protocols.sync_struct import Notifier


@@ -149,21 +150,6 @@ def delete(self, rid):
del self.runs[rid]


class TaskObject:
def start(self):
self.task = asyncio.async(self._do())

@asyncio.coroutine
def stop(self):
self.task.cancel()
yield from asyncio.wait([self.task])
del self.task

@asyncio.coroutine
def _do(self):
raise NotImplementedError


class PrepareStage(TaskObject):
def __init__(self, flush_tracker, delete_cb, pool, outq):
self.flush_tracker = flush_tracker
15 changes: 15 additions & 0 deletions artiq/tools.py
Original file line number Diff line number Diff line change
@@ -130,6 +130,21 @@ def asyncio_queue_peek(q):
raise asyncio.QueueEmpty


class TaskObject:
def start(self):
self.task = asyncio.async(self._do())

@asyncio.coroutine
def stop(self):
self.task.cancel()
yield from asyncio.wait([self.task])
del self.task

@asyncio.coroutine
def _do(self):
raise NotImplementedError


class WaitSet:
def __init__(self):
self._s = set()