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: 070788a680ab
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: 95ee6a495124
Choose a head ref
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on Jan 14, 2015

  1. Copy the full SHA
    33283fe View commit details
  2. Copy the full SHA
    95ee6a4 View commit details
Showing with 180 additions and 12 deletions.
  1. +160 −0 artiq/gui/rt_results.py
  2. +5 −5 artiq/management/sync_struct.py
  3. +4 −4 artiq/master/rt_results.py
  4. +2 −2 frontend/artiq_client.py
  5. +8 −0 frontend/artiq_gui.py
  6. +1 −1 frontend/artiq_master.py
160 changes: 160 additions & 0 deletions artiq/gui/rt_results.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import asyncio
from collections import defaultdict

from gi.repository import Gtk
import cairoplot

from artiq.management.sync_struct import Subscriber
from artiq.gui.tools import Window


class _PlotWindow(Window):
def __init__(self, set_names):
self.set_names = set_names
self.data = None

Window.__init__(self, title="/".join(set_names))
self.set_default_size(700, 500)

self.darea = Gtk.DrawingArea()
self.darea.set_size_request(100, 100)
self.darea.connect("draw", self.on_draw)
self.add(self.darea)

def delete(self):
self.close()


class XYWindow(_PlotWindow):
def on_draw(self, widget, ctx):
if self.data is not None:
cairoplot.scatter_plot(
ctx,
data=self.filter_data(),
width=widget.get_allocated_width(),
height=widget.get_allocated_height(),
border=20, axis=True, grid=True,
dots=1, discrete=True,
series_colors=[(0.0, 0.0, 0.0)],
background="white"
)

def filter_data(self):
return [
self.data[self.set_names[0]],
self.data[self.set_names[1]],
]

def set_data(self, data):
self.data = data
# The two axes are not updated simultaneously.
# Redraw only after receiving a new point for each.
x, y = self.filter_data()
if len(x) == len(y):
self.darea.queue_draw()


def _create_view(set_names, view_description):
r = XYWindow(set_names)
r.show_all()
return r


class _Group:
def __init__(self, init):
# data key -> list of views using it
self.views = defaultdict(list)
# original data
self.data = dict()
for k, v in init.items():
self[k] = v

def all_views(self):
r = set()
for view_list in self.views.values():
for view in view_list:
r.add(view)
return r

def delete(self):
for view in self.all_views():
view.delete()

def __getitem__(self, key):
if key == "data":
return self.data
else:
raise KeyError

def __setitem__(self, key, value):
if key == "description":
self.delete()
self.views = defaultdict(list)
for set_names, view_description in value.items():
if not isinstance(set_names, tuple):
set_names = (set_names, )
view = _create_view(set_names, view_description)
view.set_data(self.data)
for set_name in set_names:
self.views[set_name].append(view)
elif key == "data":
self.data = value
for view in self.all_views():
view.set_data(self.data)
else:
raise KeyError

def on_data_modified(self, key):
for view in self.views[key]:
view.set_data(self.data)


class _Groups:
def __init__(self, init):
self.groups = dict()
for k, v in init.items():
self[k] = v

def delete(self):
for s in self.groups.values():
s.delete()

def __getitem__(self, key):
return self.groups[key]

def __setitem__(self, key, value):
if key in self.groups:
self.groups[key].delete()
self.groups[key] = _Group(value)

def __delitem__(self, key):
self.groups[key].delete()
del self.groups[key]


class RTResults:
def __init__(self):
self.current_groups = None

@asyncio.coroutine
def sub_connect(self, host, port):
self.sets_subscriber = Subscriber("rt_results",
self.init_groups, self.on_mod)
yield from self.sets_subscriber.connect(host, port)

@asyncio.coroutine
def sub_close(self):
yield from self.sets_subscriber.close()

def init_groups(self, init):
if self.current_groups is not None:
self.current_groups.delete()
self.current_groups = _Groups(init)
return self.current_groups

def on_mod(self, mod):
if mod["action"] != "init" and len(mod["path"]) >= 3:
path = mod["path"]
group = self.current_groups[path[0]]
if path[1] == "data":
group.on_data_modified(path[2])
10 changes: 5 additions & 5 deletions artiq/management/sync_struct.py
Original file line number Diff line number Diff line change
@@ -66,15 +66,15 @@ def _receive_cr(self):
line = yield from self._reader.readline()
if not line:
return
obj = pyon.decode(line.decode())
mod = pyon.decode(line.decode())

if obj["action"] == "init":
target = self.target_builder(obj["struct"])
if mod["action"] == "init":
target = self.target_builder(mod["struct"])
else:
process_mod(target, obj)
process_mod(target, mod)

if self.notify_cb is not None:
self.notify_cb()
self.notify_cb(mod)


class Notifier:
8 changes: 4 additions & 4 deletions artiq/master/rt_results.py
Original file line number Diff line number Diff line change
@@ -3,8 +3,8 @@

class RTResults:
def __init__(self):
self.sets = Notifier(dict())
self.current_set = "default"
self.groups = Notifier(dict())
self.current_group = "default"

def init(self, description):
data = dict()
@@ -14,11 +14,11 @@ def init(self, description):
data[e] = []
else:
data[rtr] = []
self.sets[self.current_set] = {
self.groups[self.current_group] = {
"description": description,
"data": data
}

def update(self, mod):
target = self.sets[self.current_set]["data"]
target = self.groups[self.current_group]["data"]
process_mod(target, mod)
4 changes: 2 additions & 2 deletions frontend/artiq_client.py
Original file line number Diff line number Diff line change
@@ -201,7 +201,7 @@ def init_l(x):
l[:] = x
return l
subscriber = Subscriber(notifier_name, init_l,
lambda: display_fun(l))
lambda mod: display_fun(l))
_run_subscriber(args.server, args.port, subscriber)


@@ -212,7 +212,7 @@ def init_d(x):
d.update(x)
return d
subscriber = Subscriber(notifier_name, init_d,
lambda: display_fun(d))
lambda mod: display_fun(d))
_run_subscriber(args.server, args.port, subscriber)


8 changes: 8 additions & 0 deletions frontend/artiq_gui.py
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
from artiq.management.pc_rpc import AsyncioClient
from artiq.gui.scheduler import SchedulerWindow
from artiq.gui.parameters import ParametersWindow
from artiq.gui.rt_results import RTResults


def _get_args():
@@ -55,6 +56,13 @@ def main():
atexit.register(
lambda: loop.run_until_complete(parameters_win.sub_close()))

rtr = RTResults()
loop.run_until_complete(rtr.sub_connect(
args.server, args.port_notify))
atexit.register(
lambda: loop.run_until_complete(rtr.sub_close()))


loop.run_forever()

if __name__ == "__main__":
2 changes: 1 addition & 1 deletion frontend/artiq_master.py
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ def main():
"devices": ddb.data,
"parameters": pdb.data,
"parameters_simplehist": simplephist.history,
"rt_results": rtr.sets
"rt_results": rtr.groups
})
loop.run_until_complete(server_notify.start(
args.bind, args.port_notify))