Skip to content

Commit

Permalink
Merge with PhyNerd/Markers (Pull request labscript-suite#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisjbillington committed May 8, 2018
2 parents 21aef48 + 5ad225c commit 49d0d0b
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 2 deletions.
134 changes: 132 additions & 2 deletions __main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,26 @@ def set_win_appusermodel(window_id):
CHANNEL_MODEL__CHANNEL_INDEX = 0


def format_time(input_sec):
# inout is the time in sec
if input_sec >= 1:
return "{:.3g}s".format(input_sec)
elif input_sec >= 1e-3:
return "{:.3g}ms".format(input_sec * 1e3)
elif input_sec >= 1e-6:
return "{:.3g}us".format(input_sec * 1e6)
elif input_sec >= 1e-9:
return "{:.3g}ns".format(input_sec * 1e9)
elif input_sec >= 1e-12:
return "{:.3g}ps".format(input_sec * 1e12)
elif input_sec >= 1e-15:
return "{:.3g}fs".format(input_sec * 1e15)
elif input_sec >= 1e-18:
return "{:.3g}as".format(input_sec * 1e18)
else:
return str(input_sec) + "s"


def int_to_enum(enum_list, value):
"""stupid hack to work around the fact that PySide screws with the type of a variable when it goes into a model. Enums are converted to ints, which then
can't be interpreted by QColor correctly (for example)
Expand Down Expand Up @@ -208,6 +228,41 @@ def __init__(self, exp_config):
self._hidden_plot = (hidden_plot, hidden_plot_item)
self.ui.hidden_plot_layout.addWidget(hidden_plot)

time_axis_plot = pg.PlotWidget()
time_axis_plot.setMinimumHeight(120)
time_axis_plot.setMaximumHeight(120)
time_axis_plot.setLabel('bottom', 'Time', units='s')
time_axis_plot.showAxis('right', True)
time_axis_plot.setXLink('runviewer - time axis link')
time_axis_plot.setMouseEnabled(y=False)
time_axis_plot.getAxis('left').setTicks([]) # hide y ticks in the left & right side. only show time axis
time_axis_plot.getAxis('right').setTicks([])
time_axis_plot.setLabel('left', 'Slots')
time_axis_plot.scene().sigMouseMoved.connect(lambda pos: self.mouseMovedEvent(pos, time_axis_plot, "Slots"))
time_axis_plot_item = time_axis_plot.plot([0, 1], [0, 0], pen=(255, 255, 255))
self._time_axis_plot = (time_axis_plot, time_axis_plot_item)

self.all_markers = {}
self.all_marker_items = {}
markers_plot = pg.PlotWidget(name='runviewer - markers')
markers_plot.setMinimumHeight(120)
markers_plot.setMaximumHeight(120)
markers_plot.showAxis('top', False)
markers_plot.showAxis('bottom', False)
markers_plot.showAxis('left', True)
markers_plot.showAxis('right', True)
markers_plot.getAxis('left').setTicks([])
markers_plot.getAxis('right').setTicks([])
markers_plot.setLabel('left', 'Markers')
markers_plot.setXLink('runviewer - time axis link')
markers_plot.setMouseEnabled(y=False)
markers_plot.scene().sigMouseMoved.connect(lambda pos: self.mouseMovedEvent(pos, markers_plot, "Markers"))
markers_plot_item = markers_plot.plot([])
self._markers_plot = (markers_plot, markers_plot_item)

self.ui.verticalLayout_9.insertWidget(1,markers_plot)
self.ui.plot_layout.addWidget(time_axis_plot)

# add some icons
self.ui.add_shot.setIcon(QIcon(':/qtutils/fugue/plus'))
self.ui.remove_shots.setIcon(QIcon(':/qtutils/fugue/minus'))
Expand Down Expand Up @@ -242,6 +297,7 @@ def __init__(self, exp_config):
self.ui.enable_selected_shots.clicked.connect(self._enable_selected_shots)
self.ui.disable_selected_shots.clicked.connect(self._disable_selected_shots)
self.ui.add_shot.clicked.connect(self.on_add_shot)
self.ui.markers_comboBox.currentIndexChanged.connect(self._update_markers)
self.ui.remove_shots.clicked.connect(self.on_remove_shots)

self.ui.actionOpen_Shot.triggered.connect(self.on_add_shot)
Expand Down Expand Up @@ -281,6 +337,32 @@ def __init__(self, exp_config):
self._shots_to_process_thread.daemon = True
self._shots_to_process_thread.start()

def _update_markers(self, index):
for line, plot in self.all_marker_items.items():
plot.removeItem(line)
self.all_marker_items = {}

shot = self.ui.markers_comboBox.currentData()
self.all_markers = shot.markers if index > 0 else {}

times = sorted(list(self.all_markers.keys()))
for i, (t, m) in enumerate(sorted(self.all_markers.items())):
if i < len(times)-1:
delta_t = times[i+1] - t
else:
delta_t = shot.stop_time - t

color = m['color']
color = QColor(color[0], color[1], color[2])
label = m['label'].decode() if isinstance( m['label'], bytes) else str(m['label'])

line = self._markers_plot[0].addLine(x=t, pen=pg.mkPen(color=color, width=1.5, style=Qt.DashLine), label=label, labelOpts= {"color": color, "fill": QColor(255, 255, 255, 255), "rotateAxis":(1, 0), "anchors": [(0.5, 0),(0.5, 0)]} )
self.all_marker_items[line] = self._markers_plot[0]

line = self._time_axis_plot[0].addLine(x=t, pen=pg.mkPen(color=color, width=1.5, style=Qt.DashLine), label=format_time(delta_t), labelOpts= {"color": color, "fill": QColor(255, 255, 255, 255), "rotateAxis":(1, 0), "anchors": [(0.5, 0),(0.5, 0)]} )
self.all_marker_items[line] = self._time_axis_plot[0]

self.update_plots()

def mouseMovedEvent(self, position, ui, name):
if self.ui.toggle_tooltip.isChecked():
Expand Down Expand Up @@ -444,6 +526,10 @@ def on_shot_selection_changed(self, item):
icon = QIcon(pixmap)
colour_item.setData(lambda clist=self.shot_colour_delegate._colours, colour=colour: int_to_enum(clist, colour), Qt.UserRole)
colour_item.setData(icon, Qt.DecorationRole)
shot_combobox_index = self.ui.markers_comboBox.findData(item.data())
self.ui.markers_comboBox.model().item(shot_combobox_index).setEnabled(True)
if self.ui.markers_comboBox.currentIndex() == 0:
self.ui.markers_comboBox.setCurrentIndex(shot_combobox_index)
if item.data().shutter_times != {}:
check_shutter.setEnabled(True)
else:
Expand All @@ -452,6 +538,10 @@ def on_shot_selection_changed(self, item):
else:
# colour = None
# icon = None
shot_combobox_index = self.ui.markers_comboBox.findData(item.data())
self.ui.markers_comboBox.model().item(shot_combobox_index).setEnabled(False)
if shot_combobox_index == self.ui.markers_comboBox.currentIndex():
self.ui.markers_comboBox.setCurrentIndex(0)
colour_item.setEditable(False)
check_shutter.setEnabled(False)

Expand Down Expand Up @@ -505,6 +595,9 @@ def load_shot(self, filepath):
# path_item.setEditable(False)
# items.append(path_item)
self.shot_model.appendRow(items)
self.ui.markers_comboBox.addItem(os.path.basename(shot.path), shot)
shot_combobox_index = self.ui.markers_comboBox.findData(shot)
self.ui.markers_comboBox.model().item(shot_combobox_index).setEnabled(False)

# only do this if we are checking the shot we are adding
# self.update_channels_treeview()
Expand Down Expand Up @@ -547,6 +640,9 @@ def update_channels_treeview(self):
treeview_channels = set(treeview_channels_dict.keys())
deactivated_treeview_channels = set(deactivated_treeview_channels_dict.keys())

# speed up working with self.channel_model by blocking signals and later reenabeling them
self.channel_model.blockSignals(True)

# find list of channels to work with
channels_to_add = channels_set.difference(treeview_channels)
for channel in sorted(channels_to_add):
Expand Down Expand Up @@ -576,6 +672,9 @@ def update_channels_treeview(self):
item.setEnabled(False)
item.setSelectable(False)

self.channel_model.blockSignals(False)
self.channel_model.layoutChanged.emit()

# TODO: Also update entries in groups

self.update_plots()
Expand All @@ -591,6 +690,7 @@ def update_plots(self):
# self._hidden_plot[0].enableAutoRange(axis=pg.ViewBox.XAxis, enable=False)

# find stop time of longest ticked shot

largest_stop_time = 0
stop_time_set = False
for shot in ticked_shots.keys():
Expand Down Expand Up @@ -640,6 +740,12 @@ def update_plots(self):
# Add Shutter Markers of newly ticked Shots
self.add_shutter_markers(shot, channel, shutters_checked)

for t, m in self.all_markers.items():
color = m['color']
color = QColor(color[0], color[1], color[2])
line = self.plot_widgets[channel].addLine(x=t, pen=pg.mkPen(color=color, width=1.5, style=Qt.DashLine))
self.all_marker_items[line] = self.plot_widgets[channel]

# If no, create one
else:
self.create_plot(channel, ticked_shots)
Expand All @@ -657,10 +763,11 @@ def create_plot(self, channel, ticked_shots):
self.plot_widgets[channel].setMaximumHeight(200)
self.plot_widgets[channel].setLabel('bottom', 'Time', units='s')
self.plot_widgets[channel].showAxis('right', True)
self.plot_widgets[channel].showAxis('bottom', True)
self.plot_widgets[channel].setXLink('runviewer - time axis link')
self.plot_widgets[channel].sigXRangeChanged.connect(self.on_x_range_changed)
self.plot_widgets[channel].scene().sigMouseMoved.connect(lambda pos: self.mouseMovedEvent(pos, self.plot_widgets[channel], channel))
self.ui.plot_layout.addWidget(self.plot_widgets[channel])
self.ui.plot_layout.insertWidget(self.ui.plot_layout.count() - 1, self.plot_widgets[channel])
self.shutter_lines[channel] = {} # initialize Storage for shutter lines
self.plot_items.setdefault(channel, {})

Expand Down Expand Up @@ -1081,7 +1188,7 @@ def update_plot_positions(self):
self.plot_widgets[channel].show()
else:
self.plot_widgets[channel].hide()

self.ui.plot_layout.addWidget(self._time_axis_plot[0])

class Shot(object):
def __init__(self, path):
Expand All @@ -1091,6 +1198,8 @@ def __init__(self, path):
self._traces = None
# store list of channels
self._channels = None
# store list of markers
self._markers = None

# store list of shutter changes and callibrations
self._shutter_times = None
Expand Down Expand Up @@ -1130,14 +1239,29 @@ def _load(self):
self._channels = {}
if self._traces is None:
self._traces = {}
if self._markers is None:
self._markers = {}
if self._shutter_times is None:
self._shutter_times = {}

self._load_markers()
# Let's walk the connection table, starting with the master pseudoclock
master_pseudoclock_device = self.connection_table.find_by_name(self.master_pseudoclock_name)

self._load_device(master_pseudoclock_device)

def _load_markers(self):
with h5py.File(self.path, 'r') as file:
if "time_markers" in file:
for row in file["time_markers"]:
self._markers[row['time']] = {'color': row['color'].tolist()[0], 'label': row['label']}
elif "runviewer" in file:
for time, val in file["runviewer"]["markers"].attrs.items():
props = val.strip('{}}').rsplit(",", 1)
color = list(map(int, props[0].split(":")[1].strip(" ()").split(",")))
label = props[1].split(":")[1]
self._markers[float(time)] = {'color': color, 'label': label}

def add_trace(self, name, trace, parent_device_name, connection):
name = str(name)
self._channels[name] = {'device_name': parent_device_name, 'port': connection}
Expand Down Expand Up @@ -1204,6 +1328,12 @@ def clear_cache(self):
# clear cache variables to cut down on memory usage
pass

@property
def markers(self):
if self._markers is None:
self._load()
return self._markers

@property
def traces(self):
# if traces cached:
Expand Down
9 changes: 9 additions & 0 deletions main.ui
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,15 @@ QToolButton:hover:checked {
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="markers_comboBox">
<item>
<property name="text">
<string>Select Markers</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
Expand Down

0 comments on commit 49d0d0b

Please sign in to comment.