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: 6b0e120d75f2
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: ef8b09d9bcdd
Choose a head ref
  • 5 commits
  • 9 files changed
  • 1 contributor

Commits on Jul 24, 2015

  1. Copy the full SHA
    7d81520 View commit details
  2. Copy the full SHA
    5b62b24 View commit details
  3. Copy the full SHA
    928775f View commit details
  4. Copy the full SHA
    f210e0d View commit details
  5. gui: add console

    sbourdeauducq committed Jul 24, 2015
    Copy the full SHA
    ef8b09d View commit details
15 changes: 14 additions & 1 deletion artiq/frontend/artiq_gui.py
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
from artiq.gui.parameters import ParametersDock
from artiq.gui.schedule import ScheduleDock
from artiq.gui.log import LogDock
from artiq.gui.console import ConsoleDock


data_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)),
@@ -109,7 +110,19 @@ def main():
args.server, args.port_notify))
atexit.register(lambda: loop.run_until_complete(d_log.sub_close()))

area.addDock(d_log, "bottom")
pdb = AsyncioClient()
loop.run_until_complete(pdb.connect_rpc(
args.server, args.port_control, "master_pdb"))
atexit.register(lambda: pdb.close_rpc())
def _get_parameter(k, v):
asyncio.async(pdb.set(k, v))
d_console = ConsoleDock(
d_params.get_parameter,
_get_parameter,
d_results.get_result)

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

win.show()
21 changes: 21 additions & 0 deletions artiq/gui/console.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from pyqtgraph import console, dockarea


_help = """
The following functions are available:
get_parameter(key)
set_parameter(key, value) [asynchronous update]
get_result(key) [real-time results only]
"""

class ConsoleDock(dockarea.Dock):
def __init__(self, get_parameter, set_parameter, get_result):
dockarea.Dock.__init__(self, "Console", size=(1000, 300))
ns = {
"get_parameter": get_parameter,
"set_parameter": set_parameter,
"get_result": get_result
}
c = console.ConsoleWidget(namespace=ns, text=_help)
self.addWidget(c)
4 changes: 2 additions & 2 deletions artiq/gui/explorer.py
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@

from artiq.protocols.sync_struct import Subscriber
from artiq.protocols import pyon
from artiq.gui.tools import DictSyncModel
from artiq.gui.tools import DictSyncModel, force_spinbox_value
from artiq.gui.scan import ScanController


@@ -73,7 +73,7 @@ def __init__(self, procdesc):
if procdesc["unit"]:
self.setSuffix(" " + procdesc["unit"])
if "default" in procdesc:
self.setValue(procdesc["default"])
force_spinbox_value(self, procdesc["default"])

def get_argument_value(self):
return self.value()
13 changes: 8 additions & 5 deletions artiq/gui/parameters.py
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ def __init__(self):

self.search = QtGui.QLineEdit()
self.search.setPlaceholderText("search...")
self.search.editingFinished.connect(self.search_parameters)
self.search.editingFinished.connect(self._search_parameters)
grid.addWidget(self.search, 0, 0)

self.table = QtGui.QTableView()
@@ -43,7 +43,10 @@ def __init__(self):
QtGui.QHeaderView.ResizeToContents)
grid.addWidget(self.table, 1, 0)

def search_parameters(self):
def get_parameter(self, key):
return self.table_model.backing_store[key]

def _search_parameters(self):
model = self.table.model()
parentIndex = model.index(0, 0)
numRows = model.rowCount(parentIndex)
@@ -66,6 +69,6 @@ def sub_close(self):
yield from self.subscriber.close()

def init_parameters_model(self, init):
table_model = ParametersModel(self.table, init)
self.table.setModel(table_model)
return table_model
self.table_model = ParametersModel(self.table, init)
self.table.setModel(self.table_model)
return self.table_model
3 changes: 3 additions & 0 deletions artiq/gui/results.py
Original file line number Diff line number Diff line change
@@ -55,6 +55,9 @@ def __init__(self, dialog_parent, dock_area):

self.displays = dict()

def get_result(self, key):
return self.table_model.backing_store[key]

@asyncio.coroutine
def sub_connect(self, host, port):
self.subscriber = Subscriber("rt_results", self.init_results_model,
14 changes: 8 additions & 6 deletions artiq/gui/scan.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from quamash import QtGui
from pyqtgraph import LayoutWidget

from artiq.gui.tools import force_spinbox_value


class _Range(LayoutWidget):
def __init__(self, global_min, global_max, global_step, unit):
@@ -33,9 +35,9 @@ def apply_properties(spinbox):
self.addWidget(self.npoints, 0, 5)

def set_values(self, min, max, npoints):
self.min.setValue(min)
self.max.setValue(max)
self.npoints.setValue(npoints)
force_spinbox_value(self.min, min)
force_spinbox_value(self.max, max)
force_spinbox_value(self.npoints, npoints)

def get_values(self):
return {
@@ -97,13 +99,13 @@ def __init__(self, procdesc):
d = procdesc["default"]
if d["ty"] == "NoScan":
self.noscan.setChecked(True)
self.v_noscan.setValue(d["value"])
force_spinbox_value(self.v_noscan, d["value"])
elif d["ty"] == "LinearScan":
self.linear.setChecked(True)
self.v_linear.set_values(d["min"], d["max"], d["step"])
self.v_linear.set_values(d["min"], d["max"], d["npoints"])
elif d["ty"] == "RandomScan":
self.random.setChecked(True)
self.v_random.set_values(d["min"], d["max"], d["step"])
self.v_random.set_values(d["min"], d["max"], d["npoints"])
elif d["ty"] == "ExplicitScan":
self.explicit.setChecked(True)
self.v_explicit.insert(" ".join(
8 changes: 8 additions & 0 deletions artiq/gui/tools.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
from quamash import QtCore


def force_spinbox_value(spinbox, value):
if spinbox.minimum() > value:
spinbox.setMinimum(value)
if spinbox.maximum() < value:
spinbox.setMaximum(value)
spinbox.setValue(value)


def short_format(v):
t = type(v)
if t is int or t is float:
35 changes: 8 additions & 27 deletions artiq/protocols/pc_rpc.py
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@
client passes a list as a parameter of an RPC method, and that method
``append()s`` an element to the list, the element is not appended to the
client's list.
"""

import socket
@@ -29,17 +28,13 @@

class RemoteError(Exception):
"""Raised when a RPC failed or raised an exception on the remote (server)
side.
"""
side."""
pass


class IncompatibleServer(Exception):
"""Raised by the client when attempting to connect to a server that does
not have the expected target.
"""
not have the expected target."""
pass


@@ -74,7 +69,6 @@ class Client:
Use ``None`` to skip selecting a target. The list of targets can then
be retrieved using ``get_rpc_id`` and then one can be selected later
using ``select_rpc_target``.
"""
def __init__(self, host, port, target_name):
self.__socket = socket.create_connection((host, port))
@@ -93,25 +87,20 @@ def __init__(self, host, port, target_name):

def select_rpc_target(self, target_name):
"""Selects a RPC target by name. This function should be called
exactly once if the object was created with ``target_name=None``.
"""
exactly once if the object was created with ``target_name=None``."""
if target_name not in self.__target_names:
raise IncompatibleServer
self.__socket.sendall((target_name + "\n").encode())

def get_rpc_id(self):
"""Returns a tuple (target_names, id_parameters) containing the
identification information of the server.
"""
identification information of the server."""
return (self.__target_names, self.__id_parameters)

def close_rpc(self):
"""Closes the connection to the RPC server.
No further method calls should be done after this method is called.
"""
self.__socket.close()

@@ -159,6 +148,8 @@ class AsyncioClient:
All RPC methods are coroutines.
Concurrent access from different asyncio tasks is supported; all calls
use a single lock.
"""
def __init__(self):
self.__lock = asyncio.Lock()
@@ -171,9 +162,7 @@ def __init__(self):
def connect_rpc(self, host, port, target_name):
"""Connects to the server. This cannot be done in __init__ because
this method is a coroutine. See ``Client`` for a description of the
parameters.
"""
parameters."""
self.__reader, self.__writer = \
yield from asyncio.open_connection(host, port)
try:
@@ -190,24 +179,20 @@ def connect_rpc(self, host, port, target_name):
def select_rpc_target(self, target_name):
"""Selects a RPC target by name. This function should be called
exactly once if the connection was created with ``target_name=None``.
"""
if target_name not in self.__target_names:
raise IncompatibleServer
self.__writer.write((target_name + "\n").encode())

def get_rpc_id(self):
"""Returns a tuple (target_names, id_parameters) containing the
identification information of the server.
"""
identification information of the server."""
return (self.__target_names, self.__id_parameters)

def close_rpc(self):
"""Closes the connection to the RPC server.
No further method calls should be done after this method is called.
"""
self.__writer.close()
self.__reader = None
@@ -261,7 +246,6 @@ class BestEffortClient:
connection attempt at object initialization.
:param retry: Amount of time to wait between retries when reconnecting
in the background.
"""
def __init__(self, host, port, target_name,
firstcon_timeout=0.5, retry=5.0):
@@ -322,7 +306,6 @@ def close_rpc(self):
"""Closes the connection to the RPC server.
No further method calls should be done after this method is called.
"""
if self.__conretry_thread is None:
if self.__socket is not None:
@@ -415,7 +398,6 @@ class Server(_AsyncioServer):
Clients select one of these objects using its name upon connection.
:param id_parameters: An optional human-readable string giving more
information about the parameters of the server.
"""
def __init__(self, targets, id_parameters=None):
_AsyncioServer.__init__(self)
@@ -485,7 +467,6 @@ def simple_server_loop(targets, host, port, id_parameters=None):
"""Runs a server until an exception is raised (e.g. the user hits Ctrl-C).
See ``Server`` for a description of the parameters.
"""
loop = asyncio.get_event_loop()
try:
12 changes: 5 additions & 7 deletions examples/master/repository/flopping_f_simulation.py
Original file line number Diff line number Diff line change
@@ -27,21 +27,19 @@ class FloppingF(EnvExperiment):
"""Flopping F simulation"""

def build(self):
self.attr_argument("npoints", FreeValue(100))
self.attr_argument("min_freq", FreeValue(1000))
self.attr_argument("max_freq", FreeValue(2000))
self.attr_argument("frequency_scan", Scannable(
default=LinearScan(1000, 2000, 100)))

self.attr_argument("F0", FreeValue(1500))
self.attr_argument("noise_amplitude", FreeValue(0.1))
self.attr_argument("F0", NumberValue(1500, min=1000, max=2000))
self.attr_argument("noise_amplitude", NumberValue(0.1, min=0, max=100))

self.frequency = self.set_result("flopping_f_frequency", [], True)
self.brightness = self.set_result("flopping_f_brightness", [], True)

self.attr_device("scheduler")

def run(self):
for i in range(self.npoints):
frequency = (self.max_freq-self.min_freq)*i/(self.npoints - 1) + self.min_freq
for frequency in self.frequency_scan:
brightness = model(frequency, self.F0) + self.noise_amplitude*random.random()
self.frequency.append(frequency)
self.brightness.append(brightness)