class FFTPlotter(QDialog): def __init__(self, update, t): super(FFTPlotter, self).__init__() self.populate() self.show_plot(update, t) def populate(self): self.setWindowTitle("FFT") self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) '''Changed nav toolbar''' self.layout = QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.nav) self.layout.addWidget(self.canvas) self.setLayout(self.layout) width = self.canvas.width() height = self.nav.height() + self.canvas.height() self.setFixedSize(width, height) def show_plot(self, update, t, trace='gnd'): self.canvas.ax.set_facecolor('xkcd:pinkish grey') for message_type, message in update.items(): value = message.get('cavity_probe_pico') if message_type == 'record' and value is not None: data, ts = get_cavity_data(value, trace) Pxx, freqs, t0 = show_fft(data, ts, t) self.setWindowTitle('FFT at time {} s'.format(t0)) self.canvas.ax.clear() self.canvas.ax.plot(freqs * 1e-6, Pxx, 'k') self.canvas.ax.set_xlim((0, 10)) self.canvas.ax.set_xlabel("Freq (MHz)") self.canvas.draw()
class CavityClockGui(QDialog): def __init__(self): super(CavityClockGui, self).__init__(None) self.update_id = np.random.randint(0, 2**31 - 1) self.expt = "Waiting for updates" self.data_path = None self.update = None #Specify analysis frameworks self.analysis_script = fits.do_gaussian_fit self.mode = lambda update, preset: None self.connect_to_labrad_cav() self.connect_to_labrad_clock() self.populate() #self.Plotter = LivePlotter(self) def populate(self): self.setWindowTitle("Clock + cavity gui") self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) #self.nav.addAction('Select analysis method') #self.nav.addAction('Launch live plotter', self.launch_plotter) self.layout = QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.nav) self.layout.addWidget(self.canvas) self.setLayout(self.layout) width = self.canvas.width() height = self.nav.height() + self.canvas.height() self.setFixedSize(width, height) self.add_subplot_buttons() # Labrad connection: @inlineCallbacks def connect_to_labrad_cav(self): #self.cxn = connect(name=self.name) self.cxn = connection() yield self.cxn.connect(name='cavity viewer') server = yield self.cxn.get_server('cavity_probe_pico') yield server.signal__update(self.update_id) yield server.addListener(listener=self.receive_update, source=None, ID=self.update_id) print('connected to cavity probe pico server') @inlineCallbacks def connect_to_labrad_clock(self): #self.cxn = connect(name=self.name) self.cxn = connection() yield self.cxn.connect(name='clock viewer') server = yield self.cxn.get_server('clock_pico') yield server.signal__update(self.update_id) yield server.addListener(listener=self.receive_update, source=None, ID=self.update_id) print('connected to clock pico server') def preserve_lim(self): all_ax = self.canvas.trace_axes + self.canvas.data_axes lims = np.zeros((len(all_ax), 4)) for i in np.arange(len(all_ax)): lims[i, 0:2] = all_ax[i].get_xlim() lims[i, 2:4] = all_ax[i].get_ylim() return lims def enforce_lim(self, lims, preset): all_ax = self.canvas.trace_axes + self.canvas.data_axes for i in np.arange(len(all_ax)): if preset[i]: all_ax[i].set_xlim(lims[i, 0:2]) current_y = all_ax[i].get_ylim() if current_y[1] > lims[i, 3]: lims[i, 3] = current_y[1] if current_y[0] < lims[i, 2]: lims[i, 2] = current_y[0] all_ax[i].set_ylim(lims[i, 2:4]) def save_fig(self, ax, fig, title): #https://stackoverflow.com/questions/4325733/save-a-subplot-in-matplotlib extent = ax.get_window_extent().transformed( fig.dpi_scale_trans.inverted()) extent_expanded = extent.expanded(1.5, 2) fig.savefig(title, bbox_inches=extent_expanded) def receive_update(self, c, update_json): update = json.loads(update_json) self.update = update this_expt, this_path = listeners.get_expt(update) if this_expt is not None and self.expt != this_expt: if (not self.expt.isnumeric()) and (self.data_path is not None): #Save data traces when expt ends folder_path = os.path.join(self.data_path, self.expt) np.save(os.path.join(folder_path, "processed_data_x"), self.canvas.data_x) np.save(os.path.join(folder_path, "processed_data_y"), self.canvas.data_y) self.save_fig(self.canvas.data_axes[0], self.canvas.fig, os.path.join(folder_path, 'fig_0.png')) self.save_fig(self.canvas.data_axes[1], self.canvas.fig, os.path.join(folder_path, 'fig_1.png')) print('Saved data in folder: ' + folder_path) if this_expt.isnumeric(): self.canvas.fig.suptitle(self.expt + " ended") self.expt = this_expt else: print(this_expt) self.canvas.reset_data() self.expt = this_expt self.data_path = this_path self.canvas.fig.suptitle(self.expt) self.canvas.lim_set = self.canvas.lim_default #Get current lims to prevent re-scaling lims = self.preserve_lim() preset = self.canvas.lim_set.copy() #!!Specify listeners for diff axes: #Comment/uncomment next lines to turn off/on pmt listeners: self.mode(update, preset) listeners.atom_number(update, self.canvas.data_axes[1], self.canvas.data_x[1], self.canvas.data_y[1], bad_points=self.canvas.bad_data, freq_domain=False) #Cavity single-tone traces: listeners.bare_cavity_single_tone(update, self.canvas.trace_axes[1], 'gnd') listeners.bare_cavity_single_tone(update, self.canvas.trace_axes[2], 'exc') #Cavity 2-tone probing clock operation: ''' try: returned, vrs_gnd = listeners.cavity_probe_two_tone(update, self.canvas.trace_axes[1]) self.canvas.lim_set[1] = returned or preset[1] print('fit one') returned, vrs_exc = listeners.cavity_probe_two_tone(update, self.canvas.trace_axes[2], 'exc') self.canvas.lim_set[2] = returned or preset[2] listeners.exc_frac_cavity(update, self.canvas.data_axes[1], self.canvas.data_x[1], self.canvas.data_y[1], vrs_gnd, vrs_exc, 'sequencer.clock_phase') except: print('cannot extract tones') ''' #Add back past lims to prevent rescaling self.enforce_lim(lims, preset) self.canvas.draw() #Different potential plotter configs def set_freq(self): def freq_update(update, preset): self.canvas.lim_set[0] = listeners.pmt_trace( update, self.canvas.trace_axes[0]) or preset[0] exc_called = listeners.exc_frac(update, self.canvas.data_axes[0], self.canvas.data_x[0], self.canvas.data_y[0]) return freq_update def set_time(self, time_name): def time_update(update, preset): self.canvas.lim_set[0] = listeners.pmt_trace( update, self.canvas.trace_axes[0]) or preset[0] exc_called = listeners.exc_frac(update, self.canvas.data_axes[0], self.canvas.data_x[0], self.canvas.data_y[0], time_domain=True, time_name=time_name) return time_update def set_phase(self): def phase_update(update, preset): self.canvas.lim_set[0] = listeners.pmt_trace( update, self.canvas.trace_axes[0]) or preset[0] exc_called = listeners.exc_frac(update, self.canvas.data_axes[0], self.canvas.data_x[0], self.canvas.data_y[0], time_domain=True, time_name='sequencer.clock_phase') return phase_update def set_shot(self): def shot_update(update, preset): bad_shot = self.canvas.bad_data[-1] self.canvas.lim_set[0] = listeners.pmt_trace( update, self.canvas.trace_axes[0]) or preset[0] exc_called = listeners.exc_frac(update, self.canvas.data_axes[0], self.canvas.data_x[0], self.canvas.data_y[0], freq_domain=False, n_avg=1, bad_shot=bad_shot) return shot_update #Add buttons to select config, fit methods def add_subplot_buttons(self): self.nav.addAction('Fit', self.do_fit) #Add fft client option to left cavity trace self.fft_left = QPushButton(self) self.fft_left.setText('FFT on click') self.fft_left.move(500, 380) self.fft_left.clicked.connect(self.show_fft) #Add dropdown for setting data x axis self.dropdown = QComboBox(self) self.labels = [ "Frequency", "Phase", "Dark time", "Pi time", "Shot num" ] self.fxns = [ self.set_freq(), self.set_phase(), self.set_time('sequencer.t_dark'), self.set_time('sequencer.t_pi'), self.set_shot() ] self.dropdown.addItems(self.labels) self.dropdown.currentIndexChanged.connect(self.select_mode) self.dropdown.move(870, 4) self.mode = self.fxns[0] #Add dropdown for setting analysis fxn self.fxn_drop = QComboBox(self) self.fit_labels = [ "Gaussian", "Inv. Gauss", "Phase fringe", "Local max", "Local min" ] self.fit_fxns = [ fits.do_gaussian_fit, fits.do_inverted_gaussian_fit, fits.do_phase_fit, fits.do_local_max, fits.do_local_min ] self.fxn_drop.addItems(self.fit_labels) self.analysis_script = self.fit_fxns[0] self.fxn_drop.move(1000, 4) self.fxn_drop.currentIndexChanged.connect(self.select_script) def select_mode(self): txt = self.dropdown.currentText() ix = self.dropdown.currentIndex() self.mode = self.fxns[ix] self.canvas.reset_data() print(txt) def select_script(self): ix = self.fxn_drop.currentIndex() self.analysis_script = self.fit_fxns[ix] def do_fit(self): self.analysis_script(self.canvas.data_axes[0], self.canvas.data_x[0], self.canvas.data_y[0]) def show_fft(self): self.mouse_listener = self.canvas.mpl_connect('button_press_event', self.process_click) def process_click(self, event): t_click = event.xdata self.canvas.mpl_disconnect(self.mouse_listener) self.FFTPlot = FFTPlotter(self.update, t_click) self.FFTPlot.show() def show_fft(self): self.mouse_listener = self.canvas.mpl_connect('button_press_event', self.process_click)
class PMTViewer(QtWidgets.QDialog): pmt_name = None data_dir = None def __init__(self, reactor, cxn=None): super(PMTViewer, self).__init__(None) self.reactor = reactor self.cxn = cxn print(self.data_dir) self.update_id = np.random.randint(0, 2**31 - 1) self.loading = False self.connect() @inlineCallbacks def connect(self): if self.cxn is None: self.cxn = connection() cname = 'pmt - {} - client'.format(self.pmt_name) yield self.cxn.connect(name=cname) self.populate() yield self.connect_signals() def populate(self): self.setWindowTitle(self.pmt_name) self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) self.layout = QtWidgets.QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.nav) self.layout.addWidget(self.canvas) self.setLayout(self.layout) width = self.canvas.width() height = self.nav.height() + self.canvas.height() + 20 self.setFixedSize(width, height) self.setWindowTitle('pmt_viewer') @inlineCallbacks def connect_signals(self): pmt_server = yield self.cxn.get_server('pmt') yield pmt_server.signal__update(self.update_id) yield pmt_server.addListener(listener=self.receive_update, source=None, ID=self.update_id) def receive_update(self, c, signal_json): signal = json.loads(signal_json) for message_type, message in signal.items(): # print(message_type, message) device_message = message.get(self.pmt_name) if (message_type == 'record') and (device_message is not None): self.replot(device_message) def replot(self, rel_data_path): abs_data_path = os.path.join(self.data_dir, rel_data_path) + '.hdf5' with h5py.File(abs_data_path, mode ='r') as h5f: gnd = h5f['gnd'] exc = h5f['exc'] bac = h5f['bac'] self.canvas.ax.clear() self.canvas.ax.plot(gnd, label='gnd') self.canvas.ax.plot(exc, label='exc') self.canvas.ax.plot(bac, label='bac') self.canvas.ax.legend() self.canvas.draw() def closeEvent(self, x): self.reactor.stop()
class AnalogVoltageEditor(QtWidgets.QDialog): sequence_parameters = {} def __init__(self, channel, sequence, cxn, reactor, parent=None): super(AnalogVoltageEditor, self).__init__(parent) self.channel = str(channel) self.sequence = sequence self.ramp_maker = RampMaker self.parent = parent self.cxn = cxn self.reactor = reactor self.conductor_update_id = np.random.randint(0, 2**31 - 1) self.loading = False self.connect() @inlineCallbacks def connect(self): # self.cxn = connection() # yield self.cxn.connect() yield self.get_sequence_parameters() self.populate() yield self.connect_signals() def populate(self): self.setWindowTitle(self.channel) self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) self.ramp_table = RampTable(self.ramp_maker) self.ramp_scroll = QtWidgets.QScrollArea() self.buttons = QtWidgets.QDialogButtonBox( QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel, QtCore.Qt.Horizontal, self) self.ramp_scroll.setWidget(self.ramp_table) self.ramp_scroll.setFixedHeight( self.ramp_table.height() + self.ramp_scroll.horizontalScrollBar().height() - 10) self.ramp_scroll.setWidgetResizable(True) self.buttons.button(QtWidgets.QDialogButtonBox.Ok).setDefault(False) self.layout = QtWidgets.QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.nav) self.layout.addWidget(self.canvas) self.layout.addWidget(self.ramp_scroll) self.layout.addWidget(self.buttons) self.setLayout(self.layout) width = self.canvas.width() height = self.nav.height() + self.canvas.height( ) + self.ramp_scroll.height() + 20 self.setFixedSize(width, height) self.set_columns() self.replot() @inlineCallbacks def connect_signals(self): # pyqt signals for c in self.ramp_table.cols: c.ramp_select.currentIndexChanged.connect(self.replot) for pw in c.parameter_widgets.values(): for pb in pw.pboxes.values(): pb.returnPressed.connect(self.replot) for i, c in enumerate(self.ramp_table.cols): c.add.clicked.connect(self.add_column(i)) c.dlt.clicked.connect(self.dlt_column(i)) self.buttons.accepted.connect(self.accept) self.buttons.rejected.connect(self.reject) # labrad signals conductor = yield self.cxn.get_server(self.parent.conductor_servername) yield conductor.signal__update(self.conductor_update_id) yield conductor.addListener(listener=self.receive_conductor_update, source=None, ID=self.conductor_update_id) @inlineCallbacks def get_sequence_parameters(self): conductor = yield self.cxn.get_server(self.parent.conductor_servername) parameter_names = get_sequence_parameters(self.sequence) request = { parameter_name.replace('*', 'sequencer.'): None for parameter_name in parameter_names } parameter_values_json = yield conductor.get_parameter_values( json.dumps(request)) parameter_values = json.loads(parameter_values_json) self.sequence_parameters = { name.replace('sequencer.', '*'): value for name, value in parameter_values.items() } def receive_conductor_update(self, c, signal_json): signal = json.loads(signal_json) for message_type, message in signal.items(): if message_type in [ 'set_parameter_values', 'get_parameter_values' ]: update = { name.replace('sequencer.', '*'): value for name, value in message.items() } self.sequence_parameters.update(update) self.replot() def set_columns(self): self.loading = True for c in self.ramp_table.cols: c.hide() for s, c in zip(self.sequence[self.channel], self.ramp_table.cols): ramp_type = s['type'] c.show() c.ramp_select.setCurrentIndex(c.ramp_select.findText(ramp_type)) for k in c.parameter_widgets[ramp_type].pboxes.keys(): c.parameter_widgets[ramp_type].pboxes[k].display( s[k]) # Plot Sequence in Analog Boxes self.loading = False self.replot() def add_column(self, i): def ac(): sequence = self.get_sequence() for c in sequence.keys(): if 'type' in sequence[c][i].keys(): a = {} dt = sequence[c][i]['dt'] vf = sequence[c][i]['vf'] a.update({'type': 's', 'dt': dt, 'vf': vf}) sequence[c].insert(i + 1, a) else: sequence[c].insert(i, sequence[c][i]) # sequence[c].insert(i, sequence[c][i]) self.set_sequence(sequence) return ac def dlt_column(self, i): def dc(): sequence = self.get_sequence() for c in sequence.keys(): sequence[c].pop(i) self.set_sequence(sequence) return dc def set_sequence(self, sequence): self.sequence = sequence self.set_columns() def get_plottable_sequence(self): sequence = self.ramp_table.get_channel_sequence() plottable_sequence = substitute_sequence_parameters( sequence, self.sequence_parameters) return self.ramp_maker(plottable_sequence).get_plottable() def get_sequence(self): channel_sequence = self.ramp_table.get_channel_sequence() self.sequence.update({self.channel: channel_sequence}) return self.sequence def replot(self, c=None): if not self.loading: T, V = self.get_plottable_sequence() self.canvas.make_figure(T, V) self.canvas.draw() def getEditedSequence(self): return self.get_sequence() def keyPressEvent(self, c): if QtWidgets.QApplication.keyboardModifiers( ) == QtCore.Qt.ControlModifier: if c.key() == QtCore.Qt.Key_Return: self.buttons.accepted.emit() if c.key() == QtCore.Qt.Key_Q: self.buttons.rejected.emit() else: QtWidgets.QWidget().keyPressEvent(c)
class CameraGui(QDialog): def set_vars(self): self.camera = 'vertical_mot' self.name = self.camera self.fluorescence_mode = True self.update_id = np.random.randint(0, 2**31 - 1) self.ROI = None self.no_lim = True def __init__(self): super(CameraGui, self).__init__(None) self.set_vars() self.connect_to_labrad() self.populate() self.Plotter = LivePlotter(self) def populate(self): self.setWindowTitle(self.name) self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) #select_cam = self.nav.addAction('&Select camera') #select_cam.addAction('horizontal mot') #select_cam.addAction('vertical mot (cavity)') self.nav.addAction('Launch live plotter', self.launch_plotter) self.layout = QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.nav) self.layout.addWidget(self.canvas) self.setLayout(self.layout) width = self.canvas.width() height = self.nav.height() + self.canvas.height() self.setFixedSize(width, height) #Labrad connection: @inlineCallbacks def connect_to_labrad(self): #self.cxn = connect(name=self.name) self.cxn = connection() yield self.cxn.connect(name='camera viewer') server = yield self.cxn.get_server('camera') yield server.signal__update(self.update_id) yield server.addListener(listener=self.receive_update, source=None, ID=self.update_id) print('connected') def receive_update(self, c, update_json): update = json.loads(update_json) for key, value in update.items(): if key == self.camera: if self.fluorescence_mode: if not (('exc' in value[0]) or ('background' in value[0])): print(value) if 'gnd' in value[0]: print(value[0]) str_end = '_fluorescence.png' keyword = 'mot_cavity_' split_str = value[0].partition(str_end) parse_name = split_str[0].partition(keyword) print(parse_name) beginning = parse_name[0] shot_num = int(parse_name[-1]) offset = 3 mod_shot = shot_num - offset new_path = beginning + keyword + str( mod_shot) + str_end print(new_path) self.file_to_show = new_path #value[0] else: self.file_to_show = value[0] print(self.file_to_show) time.sleep(.1) self.Plotter.show_window() self.show_window() def show_window(self): try: if not self.no_lim: xlim = self.canvas.ax.get_xlim() ylim = self.canvas.ax.get_ylim() #self.canvas.ax.clear() #MOVED to after attempt to load fig it.fig_gui_window_ROI(self.file_to_show, self.canvas.ax, self.ROI) if not self.no_lim: self.canvas.ax.set_xlim(xlim) self.canvas.ax.set_ylim(ylim) else: self.no_lim = False print(self.canvas.ax.get_xlim()) self.canvas.ax.set_title("{:.3e}".format(self.Plotter.title), color='w', y=.85, size=42) self.canvas.draw() print('redrawn') except: #self.no_lim = True print('Error loading file: not refreshed') def launch_plotter(self): self.Plotter.show()
class LivePlotter(QDialog): def set_class_vars(self): self.script = it.fig_plotter self.n_show = 30 self.live_data = np.full(self.n_show, None) def __init__(self, parent): super(LivePlotter, self).__init__() self.parent = parent self.set_class_vars() self.populate() def populate(self): self.setWindowTitle('Live plotter') self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) '''Changed nav toolbar''' self.nav.addAction('Reset optimizer', self.reset_opt) self.layout = QGridLayout() self.layout.setSpacing(0) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.nav) self.layout.addWidget(self.canvas) self.setLayout(self.layout) #self.canvas.ax.set_ylim((0, 5e-5)) #self.canvas.ax.set_xlim((0, .04)) width = self.canvas.width() height = self.nav.height() + self.canvas.height() + 20 self.setFixedSize(width, height) def reset_opt(self): self.live_data = np.full(self.n_show, None) def live_plot(self): #try: roi = self.get_ROI() this_shot = self.script(self.parent.file_to_show, roi) self.title = this_shot empty_data = np.where(self.live_data == None) if len(empty_data[0]) == 0: self.live_data[0:self.n_show - 1] = self.live_data[1:self.n_show] self.live_data[-1] = this_shot else: self.live_data[empty_data[0][0]] = this_shot #except AttributeError: # print('Not loaded') def get_ROI(self): xlim = self.parent.canvas.ax.get_xlim() ylim = self.parent.canvas.ax.get_ylim() ROI_exact = [xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0]] return [int(x) for x in ROI_exact] def show_window(self): self.live_plot() self.canvas.ax.clear() self.canvas.ax.plot(self.live_data, 'o') #self.canvas.ax.title(np.std(self.live_data)) self.canvas.draw()
class PDViewer(QtWidgets.QDialog): pd_name = None data_dir = None boxHeight = 50 boxWidth = 220 def __init__(self, reactor, cxn=None): super(PDViewer, self).__init__(None) self.reactor = reactor self.cxn = cxn print(self.data_dir) self.update_id = np.random.randint(0, 2**31 - 1) self.loading = False self.connect() @inlineCallbacks def connect(self): if self.cxn is None: self.cxn = connection() cname = 'pd - {} - client'.format(self.pd_name) yield self.cxn.connect(name=cname) self.populate() yield self.connect_signals() def populate(self): self.setWindowTitle(self.pd_name) self.canvas = MplCanvas() self.nav = NavigationToolbar(self.canvas, self) self.nameLabel1 = ClickableLabel('Parameter 1: ') self.nameLabel1.setFont(QtGui.QFont("Times", 18)) self.nameBox1 = QtWidgets.QLineEdit() self.nameBox1.setFixedSize(self.boxWidth, self.boxHeight) self.valueLabel1 = ClickableLabel('Value 1: ') self.valueLabel1.setFont(QtGui.QFont("Times", 18)) self.valueBox1 = NeatSpinBox() self.valueBox1.setFixedSize(self.boxWidth, self.boxHeight) self.nameLabel2 = ClickableLabel('Parameter 2: ') self.nameLabel2.setFont(QtGui.QFont("Times", 18)) self.nameBox2 = QtWidgets.QLineEdit() self.nameBox2.setFixedSize(self.boxWidth, self.boxHeight) self.valueLabel2 = ClickableLabel('Value 2: ') self.valueLabel2.setFont(QtGui.QFont("Times", 18)) self.valueBox2 = NeatSpinBox() self.valueBox2.setFixedSize(self.boxWidth, self.boxHeight) self.layout = QtWidgets.QGridLayout() self.layout.setSpacing(1) self.layout.setContentsMargins(2, 2, 2, 2) self.layout.addWidget(self.nav, 1, 0, 1, 5) self.layout.addWidget(self.canvas, 2, 0, 4, 4) self.layout.addWidget(self.nameLabel1, 7, 0, 1, 1, QtCore.Qt.AlignRight) self.layout.addWidget(self.nameBox1, 7, 1) self.layout.addWidget(self.valueLabel1, 7, 2, 1, 1, QtCore.Qt.AlignRight) self.layout.addWidget(self.valueBox1, 7, 3) # self.layout.addWidget(self.nameLabel2, 8, 0, 1, 1, # QtCore.Qt.AlignRight) # self.layout.addWidget(self.nameBox2, 8, 1) # self.layout.addWidget(self.valueLabel2, 8, 2, 1, 1, # QtCore.Qt.AlignRight) # self.layout.addWidget(self.valueBox2, 8, 3) self.setLayout(self.layout) width = self.canvas.width() + 20 height = self.nav.height() + self.canvas.height( ) + self.nameBox1.height() * 2 + 60 self.setFixedSize(width, height) self.setWindowTitle('pd_viewer') @inlineCallbacks def connect_signals(self): pd_server = yield self.cxn.get_server('pd') yield pd_server.signal__update(self.update_id) yield pd_server.addListener(listener=self.receive_update, source=None, ID=self.update_id) def receive_update(self, c, signal_json): signal = json.loads(signal_json) for message_type, message in signal.items(): device_message = message.get(self.pd_name) if (message_type == 'record') and (device_message is not None): print(message_type, message) self.replot(device_message) elif (message_type == 'loading_rate') and (device_message is not None): print(message_type, message) sample_rate = message.get('sample_rate') loading_rate, loss_rate, volt_to_number = process_signal( sample_rate, device_message, message_type) # self.GetParameter() # self.GetValue() self.replot_loading(sample_rate, device_message, loading_rate, loss_rate) def replot(self, rel_data_path): abs_data_path = os.path.join(self.data_dir, rel_data_path) + '.hdf5' save_data_path = os.path.join(self.data_dir, rel_data_path) + '.png' with h5py.File(abs_data_path) as h5f: exp = h5f['exp'] self.canvas.ax.clear() self.canvas.ax.plot(exp, label='exp') self.canvas.ax.legend() self.canvas.ax.set_xlabel('Points') self.canvas.ax.set_ylabel('Voltage [V]') self.canvas.fig.savefig(save_data_path) self.canvas.draw() def replot_loading(self, sample_rate, rel_data_path, loading_rate, loss_rate): abs_data_path = os.path.join(self.data_dir, rel_data_path) + '.hdf5' save_data_path = os.path.join(self.data_dir, rel_data_path) + '.png' with h5py.File(abs_data_path) as h5f: exp = h5f['exp'] self.canvas.ax.clear() x = np.linspace(0, len(exp) / sample_rate, len(exp)) self.canvas.ax.plot(x, exp, label='exp', c='black') self.canvas.ax.plot(x, fit_loading(x, loading_rate, loss_rate), label='fitted', c='red', linestyle='dashed') self.canvas.ax.legend() self.canvas.ax.set_xlabel('Time [s]') self.canvas.ax.set_ylabel('Voltage [V]') self.canvas.fig.savefig(save_data_path) self.canvas.draw() def closeEvent(self, x): self.reactor.stop()