def setup_rpc_connections(self): try: self.logger = Client("::1", 3289, "simulation_logger") except: self.logger = logging.getLogger("** SIMULATION **") self.logger.warning("Failed to connect to remote logger", exc_info=True) if not self.grapher: try: self.grapher = Client("::1", 3286, "rcg") except: self.logger.warning("Failed to connect to RCG grapher", exc_info=True) self.grapher = None if not self.visualizer: try: self.visualizer = Client("::1", 3289, "pulse_sequence_visualizer") pass except: self.logger.warning( "Failed to connect to pulse sequence visualizer", exc_info=True) self.visualizer = None
class WavemeterArtiqUpdater: """ Simple loop to push new values from the wavemeter server to ARTIQ datasets. Subscribes to a list of channels and appends their name to a common prefix to determine the target dataset. :param channels: list of channels to handle entries can be of the form <n>, 'ch<n>', 'T', or 'p' :param host_artiq: host running the ARTIQ master :param port_artiq: port of the ARTIQ master's RPC server :param host_wavemeter_pub: host of the wavemeter publisher :param port_wavemeter_pub: port of the wavemeter publisher :param dataset_name_prefix: prefix for the target dataset names :param event_loop: asyncio event loop for the subscribers (defaults to asyncio.get_event_loop()) """ def __init__(self, channels: List[Any], host_artiq: str = "::1", port_artiq: int = 3251, host_wavemeter_pub: str = "::1", port_wavemeter_pub: int = 3281, dataset_name_prefix: str = "wavemeter.", event_loop: Any = None): self._rpc_client = None self._loop = asyncio.get_event_loop() if event_loop is None else event_loop self.channels = [] for ch in channels: try: # accept integer (or string lacking the "ch" prefix) as channel argument self.channels.append("ch{}".format(int(ch))) except ValueError: self.channels.append(ch) self.channels = list(set(self.channels)) # remove duplicates self.host_artiq = host_artiq self.port_artiq = port_artiq self.host_wavemeter_pub = host_wavemeter_pub self.port_wavemeter_pub = port_wavemeter_pub self._wavemeter_clients = [] self.dataset_name_prefix = dataset_name_prefix def run(self): self._rpc_client = Client(self.host_artiq, self.port_artiq, "master_dataset_db") def callback_factory(client, dataset): def callback(): self._rpc_client.set(dataset, client.value) return callback for channel in self.channels: client = WavemeterClient(channel=channel, host=self.host_wavemeter_pub, port=self.port_wavemeter_pub, event_loop=self._loop) client._new_value_callback = callback_factory(client, self.dataset_name_prefix + channel) self._wavemeter_clients.append(client) try: self._loop.run_forever() finally: self._rpc_client.close_rpc() for cl in self._wavemeter_clients: cl.close_subscriber()
def main(): args = get_argparser().parse_args() action = args.action.replace("-", "_") if action == "show": if args.what == "schedule": _show_dict(args, "schedule", _show_schedule) elif args.what == "log": _show_log(args) elif args.what == "ccb": _show_ccb(args) elif args.what == "devices": _show_dict(args, "devices", _show_devices) elif args.what == "datasets": _show_dict(args, "datasets", _show_datasets) else: raise ValueError else: port = 3251 if args.port is None else args.port target_name = { "submit": "master_schedule", "delete": "master_schedule", "set_dataset": "master_dataset_db", "del_dataset": "master_dataset_db", "scan_devices": "master_device_db", "scan_repository": "master_experiment_db", "ls": "master_experiment_db" }[action] remote = Client(args.server, port, target_name) try: globals()["_action_" + action](remote, args) finally: remote.close_rpc()
def main(): args = get_argparser().parse_args() init_logger_from_args(args) next_poll_time = time.monotonic() while True: time.sleep(max(0, next_poll_time - time.monotonic())) next_poll_time += args.poll_time measurements = [] for server in args.server: try: client = RPCClient(server, 3251, timeout=args.timeout) lasers = client.get_laser_db() for laser in lasers: meas = client.get_freq(laser, age=args.poll_time, priority=3, get_osa_trace=False, blocking=True, mute=False, offset_mode=False) status, freq, _ = meas if status != WLMMeasurementStatus.OKAY: logger.info("{}: measurement error") continue f_ref = lasers[laser]["f_ref"] delta = freq - lasers[laser]["f_ref"] measurements.append({ "measurement": laser, "fields": { "freq": freq, "f_ref": f_ref, "detuning": delta } }) logger.info("{}: freq {} THz, f_ref {} THz, " "detuning {} MHz".format( laser, freq, f_ref, delta)) except OSError: logger.warning("Error querying server {}".format(server)) finally: client.close_rpc() if not measurements: continue try: influx = influxdb.InfluxDBClient(host=args.host_db, database=args.database, username=args.user_db, password=args.password_db) influx.write_points(measurements) finally: influx.close()
def run(self): self._rpc_client = Client(self.host_artiq, self.port_artiq, "master_dataset_db") def callback_factory(client, dataset): def callback(): self._rpc_client.set(dataset, client.value) return callback for channel in self.channels: client = WavemeterClient(channel=channel, host=self.host_wavemeter_pub, port=self.port_wavemeter_pub, event_loop=self._loop) client._new_value_callback = callback_factory(client, self.dataset_name_prefix + channel) self._wavemeter_clients.append(client) try: self._loop.run_forever() finally: self._rpc_client.close_rpc() for cl in self._wavemeter_clients: cl.close_subscriber()
def start_server(self, name, command, port, sleep=2, target_name=AutoTarget, timeout=1): if name in self.servers: raise ValueError("server `{}` already started".format(name)) proc = subprocess.Popen(shlex.split(command)) time.sleep(sleep) client = Client("localhost", port, target_name, timeout) self.servers[name] = proc, port, client return client
def __init__(self, args): pyqtgraph.PlotWidget.__init__(self) self.args = args self.curves = {} self.current_curve_x_start = {} self.current_curve_point_count = {} self.showGrid(x=True, y=True, alpha=0.75) self.setYRange(0, 1000) self.setXRange(0, 500) self.pens = { "with_866_on": pyqtgraph.mkPen((255, 0, 0), width=2), "with_866_off": pyqtgraph.mkPen((0, 0, 255), width=2), "diff_counts": pyqtgraph.mkPen((0, 255, 0), width=2) } self.z_values = { "with_866_on": 30, "with_866_off": 20, "diff_counts": 10 } legend = self.addLegend() legend.addItem(pyqtgraph.PlotDataItem(pen=self.pens["with_866_on"]), " 866 ON") legend.addItem(pyqtgraph.PlotDataItem(pen=self.pens["with_866_off"]), " 866 OFF") legend.addItem(pyqtgraph.PlotDataItem(pen=self.pens["diff_counts"]), " Diff") self.autoscroll = True self.setLimits(yMin=0, xMin=0) self.disableAutoRange() self.scene().sigMouseClicked.connect(self.mouse_clicked) self.getPlotItem().setClipToView(True) self.data_mgr = Client("::1", 3251, "master_dataset_db")
def main(): args = get_argparser().parse_args() if not args.action: args.target = None remote = Client(args.server, args.port, None) targets, description = remote.get_rpc_id() if args.action != "list-targets": if not args.target: remote.select_rpc_target(AutoTarget) else: remote.select_rpc_target(args.target) if args.action == "list-targets": list_targets(targets, description) elif args.action == "list-methods": list_methods(remote) elif args.action == "call": call_method(remote, args.method, args.args) elif args.action == "interactive" or not args.action: interactive(remote) else: print("Unrecognized action: {}".format(args.action))
class PMTPlot(pyqtgraph.PlotWidget): def __init__(self, args): pyqtgraph.PlotWidget.__init__(self) self.args = args self.curves = {} self.current_curve_x_start = {} self.current_curve_point_count = {} self.showGrid(x=True, y=True, alpha=0.75) self.setYRange(0, 1000) self.setXRange(0, 500) self.pens = { "with_866_on": pyqtgraph.mkPen((255, 0, 0), width=2), "with_866_off": pyqtgraph.mkPen((0, 0, 255), width=2), "diff_counts": pyqtgraph.mkPen((0, 255, 0), width=2) } self.z_values = { "with_866_on": 30, "with_866_off": 20, "diff_counts": 10 } legend = self.addLegend() legend.addItem(pyqtgraph.PlotDataItem(pen=self.pens["with_866_on"]), " 866 ON") legend.addItem(pyqtgraph.PlotDataItem(pen=self.pens["with_866_off"]), " 866 OFF") legend.addItem(pyqtgraph.PlotDataItem(pen=self.pens["diff_counts"]), " Diff") self.autoscroll = True self.setLimits(yMin=0, xMin=0) self.disableAutoRange() self.scene().sigMouseClicked.connect(self.mouse_clicked) self.getPlotItem().setClipToView(True) self.data_mgr = Client("::1", 3251, "master_dataset_db") def data_changed(self, data, mods, title): try: clear_pmt_plot = data[self.args.clear_pmt_plot][1] if clear_pmt_plot: self.clear() self.curves = dict() self.current_curve_x_start = dict() self.current_curve_point_count = dict() self.data_mgr.set("clear_pmt_plot", False) self.data_mgr.set("pmt_counts", []) self.data_mgr.set("pmt_counts_866_off", []) self.data_mgr.set("diff_counts", []) self.setYRange(0, 1000) self.setXRange(0, 500) return # don't want to plot twice except Exception as e: print(Exception) self.disableAutoRange() raw_data = {} try: raw_data["with_866_on"] = data[self.args.with_866_on][1][1:] raw_data["with_866_off"] = data[self.args.with_866_off][1][1:] raw_data["diff_counts"] = [] max_with_866_off = max(raw_data["with_866_off"], default=0) for i in range( min(len(raw_data["with_866_on"]), len(raw_data["with_866_off"]))): if max_with_866_off > 0: raw_data["diff_counts"].append(raw_data["with_866_on"][i] - raw_data["with_866_off"][i]) else: raw_data["diff_counts"].append(-1) pulsed = data[self.args.pulsed][1][0] except KeyError: return for curve_name in ["with_866_on", "diff_counts", "with_866_off"]: if not curve_name in raw_data.keys(): continue data_to_plot = raw_data[curve_name] num_points = len(data_to_plot) if not curve_name in self.curves.keys(): self.curves[curve_name] = [] if not curve_name in self.current_curve_point_count.keys(): self.current_curve_point_count[curve_name] = 0 if not curve_name in self.current_curve_x_start.keys(): self.current_curve_x_start[curve_name] = 0 if num_points == self.current_curve_point_count[curve_name]: # nothing new to plot for this curve continue if num_points < self.current_curve_point_count[curve_name]: # if this dataset has fewer points than the current curve, the dataset # must have been restarted, so we will simply begin a new curve. # update the x_start value for the new curve self.current_curve_x_start[ curve_name] += self.current_curve_point_count[curve_name] else: # we have more points, so the current curve needs to be updated. # remove the current curve so that we will recreate it. num_curves_now = len(self.curves[curve_name]) if num_curves_now > 0: latest_curve = self.curves[curve_name][-1] self.removeItem(latest_curve) self.curves[curve_name].pop(-1) num_curves_now -= 1 self.current_curve_point_count[curve_name] = num_points # for curves with all negative values, don't use any pen to plot them. # this will happen, e.g., if we are running the PMT in continuous mode # rather than in pulsed mode -- the 866_off and diff curves will not # contain valid data. pen = self.pens[curve_name] if num_points > 0 and max(data_to_plot, default=0) < 0: pen = pyqtgraph.mkPen(None) x_start = self.current_curve_x_start[curve_name] x_end = x_start + num_points x = np.arange(x_start, x_end) curve = self.plot(x, data_to_plot, pen=pen, fillLevel=0) curve.setZValue(self.z_values[curve_name]) self.curves[curve_name].append(curve) if self.autoscroll: (xmin_cur, xmax_cur), _ = self.viewRange() max_x = 0 for curve_name in self.curves.keys(): for curve in self.curves[curve_name]: localxmax = curve.dataBounds(0)[-1] try: if localxmax > max_x: max_x = localxmax except TypeError: continue window_width = xmax_cur - xmin_cur if max_x > xmin_cur + window_width: shift = (xmax_cur - xmin_cur) / 2 xmin = xmin_cur + shift xmax = xmax_cur + shift limits = [xmin, xmax] self.setXRange(*limits) self.setTitle(title) def mouse_clicked(self, ev): if ev.double(): self.autoscroll = not self.autoscroll
class PMTControlDock(QtWidgets.QDockWidget): def __init__(self, acxn): QtWidgets.QDockWidget.__init__(self, "Manual Controls") self.setObjectName("pmt_control") self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) self.pv = None self.pm = None self.bb = None self.acxn = acxn self.setup_listeners() self.dset_ctl = Client("::1", 3251, "master_dataset_db") self.scheduler = Client("::1", 3251, "master_schedule") self.dataset_db = Client("::1", 3251, "master_dataset_db") self.rid = None self.pulsed = False self.expid_continuous = { "arguments": {}, "class_name": "pmt_collect_continuously", "file": "run_continuously/run_pmt_continuously.py", "log_level": 30, "repo_rev": None, "priority": 0 } self.expid_pulsed = { "arguments": {}, "class_name": "pmt_collect_pulsed", "file": "run_continuously/run_pmt_pulsed.py", "log_level": 30, "repo_rev": None, "priority": 0 } self.expid_ttl = { "class_name": "change_ttl", "file": "misc/manual_ttl_control.py", "log_level": 30, "repo_rev": None, "priority": 1 } self.expid_dds = { "arguments": {}, "class_name": "change_cw", "file": "misc/manual_dds_control.py", "log_level": 30, "repo_rev": None, "priority": 1 } self.expid_dc = { "arguments": {}, "class_name": "set_dopplercooling_and_statereadout", "file": "misc/set_dopplercooling_and_statereadout.py", "log_level": 30, "repo_rev": None, "priority": 2 } frame = QtWidgets.QFrame() layout = QtWidgets.QVBoxLayout() pmt_frame = self.create_pmt_frame() linetrigger_frame = self.create_linetrigger_frame() dds_frame = self.create_dds_frame() picomotor_frame = self.create_picomotor_frame() layout.addWidget(pmt_frame) layout.addWidget(dds_frame) layout.addWidget(linetrigger_frame) layout.addWidget(picomotor_frame) layout.setSpacing(50) layout.setContentsMargins(0, 50, 0, 50) frame.setLayout(layout) scroll = QtWidgets.QScrollArea() scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) scroll.setWidgetResizable(False) scroll.setWidget(frame) scroll.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) scroll.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) self.setWidget(scroll) self.connect_servers() def create_pmt_frame(self): pmtLabel = boldLabel("PMT") self.onButton = QtWidgets.QPushButton("On") self.onButton.setCheckable(True) self.onButton.clicked[bool].connect(self.set_state) self.setDCButton = QtWidgets.QPushButton("set") self.setDCButton.clicked.connect(self.set_dc_and_state_readout) self.clearPMTPlotButton = QtWidgets.QPushButton("clear") self.clearPMTPlotButton.clicked.connect(self.clear_pmt_plot) self.autoLoadButton = QtWidgets.QPushButton("On") self.autoLoadButton.setCheckable(True) self.autoLoadButton.clicked[bool].connect(self.toggle_autoload) self.autoLoadSpin = customIntSpinBox(0, (0, 1000000)) self.autoLoadCurrentSpin = customSpinBox(0, (0, 10), " A") self.countDisplay = QtWidgets.QLCDNumber() self.countDisplay.setSegmentStyle(2) self.countDisplay.display(0) self.timer = QtCore.QTimer() self.timer.timeout.connect(self.updateLCD) self.timer.start(250) self.countDisplay.setStyleSheet("background-color: lightGray;" "color: green;") self.unitsLabel = QtWidgets.QLabel("kcounts / s") self.durationLabel = QtWidgets.QLabel("Duration (ms): ") self.duration = QtWidgets.QLineEdit("100") try: with labrad.connection() as cxn: p = cxn.parametervault p.set_parameter(["PmtReadout", "duration", U(100, "ms")]) except: logger.error("Failed to initially connect to labrad.") self.duration.setDisabled(True) validator = QtGui.QDoubleValidator() self.duration.setValidator(validator) self.duration.returnPressed.connect(self.duration_changed) self.duration.setStyleSheet("QLineEdit { background-color: #c4df9b}" ) self.modeLabel = QtWidgets.QLabel("Mode: ") self.setMode = customComboBox(["continuous", "pulsed"]) self.setMode.currentIndexChanged.connect(self.set_mode) layout = QtWidgets.QGridLayout() frame = QtWidgets.QFrame() frame.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Sunken) frame.setLineWidth(2) frame.setMidLineWidth(3) layout.addWidget(pmtLabel, 0, 0, 1, 3) layout.addWidget(self.onButton, 1, 0) layout.addWidget(self.countDisplay, 1, 1) layout.addWidget(self.unitsLabel, 1, 2) layout.addWidget(self.durationLabel, 2, 0) layout.addWidget(self.duration, 2, 1, 1, 2) layout.addWidget(self.modeLabel, 3, 0) layout.addWidget(self.setMode, 3, 1, 1, 2) layout.addWidget(QtWidgets.QLabel("Autoload: "), 4, 0) layout.addWidget(self.autoLoadButton, 4, 1) layout.addWidget(self.autoLoadSpin, 4, 2) layout.addWidget(QtWidgets.QLabel("Current: "), 5, 0) layout.addWidget(self.autoLoadCurrentSpin, 5, 1) dcLabel = QtWidgets.QLabel("Set Doppler cooling and state readout: ") layout.addWidget(dcLabel, 6, 0, 1, 2) layout.addWidget(self.setDCButton, 6, 2) # clearLabel = QtWidgets.QLabel("Reset PMT plot: ") # layout.addWidget(clearLabel, 7, 0) # layout.addWidget(self.clearPMTPlotButton, 7, 1, 1, 2) frame.setLayout(layout) return frame def create_linetrigger_frame(self): linetriggerLabel = boldLabel("LINETRIGGER") self.linetriggerButton = QtWidgets.QPushButton("Off") self.linetriggerButton.setCheckable(True) self.linetriggerButton.setChecked(True) self.linetriggerButton.clicked[bool].connect(self.toggle_linetrigger) self.linetriggerLineEdit = QtWidgets.QLineEdit("0") self.linetriggerLineEdit.returnPressed.connect(self.linetrigger_duration_changed) layout = QtWidgets.QGridLayout() frame = QtWidgets.QFrame() frame.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Sunken) frame.setLineWidth(2) frame.setMidLineWidth(3) layout.addWidget(linetriggerLabel, 0, 0, 1, 3) layout.addWidget(self.linetriggerButton, 1, 0, 1, 3) layout.addWidget(QtWidgets.QLabel("Offset duration (us): "), 2, 0) layout.addWidget(self.linetriggerLineEdit, 2, 1, 1, 2) frame.setLayout(layout) return frame def create_picomotor_frame(self): layout = QtWidgets.QGridLayout() frame = QtWidgets.QFrame() frame.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Sunken) frame.setLineWidth(2) frame.setMidLineWidth(3) piezoLabel = boldLabel("PICOMOTOR") ctls = ["Local X", "Local Y", "Global X", "Global Y"] self.piezoStepSize = dict() self.piezoCurrentPos = dict() self.piezoLastPos = dict() layout.addWidget(piezoLabel, 0, 0, 1, 3) for i, ctl in enumerate(ctls): layout.addWidget(QtWidgets.QLabel(ctl + ": "), i + 1, 0) self.piezoStepSize[ctl] = customIntSpinBox(0, (0, 300)) self.piezoStepSize[ctl].setToolTip("Set step size.") self.piezoStepSize[ctl].setObjectName(ctl) self.piezoStepSize[ctl].setKeyboardTracking(False) self.piezoStepSize[ctl].valueChanged.connect(self.piezo_step_size_changed) self.piezoStepSize[ctl].setRange(0, 300) layout.addWidget(self.piezoStepSize[ctl], i + 1, 1) self.piezoCurrentPos[ctl] = QtWidgets.QSpinBox() self.piezoCurrentPos[ctl].setSingleStep(0) self.piezoCurrentPos[ctl].setToolTip("Current position.") self.piezoCurrentPos[ctl].setRange(-100000, 100000) self.piezoCurrentPos[ctl].setObjectName(str(i + 1)) self.piezoLastPos[i + 1] = 0 self.piezoCurrentPos[ctl].setKeyboardTracking(False) self.piezoCurrentPos[ctl].valueChanged.connect(self.piezo_changed) layout.addWidget(self.piezoCurrentPos[ctl], i + 1, 2) frame.setLayout(layout) return frame def create_dds_frame(self): layout = QtWidgets.QGridLayout() frame = QtWidgets.QFrame() frame.setFrameStyle(QtWidgets.QFrame.Panel | QtWidgets.QFrame.Sunken) frame.setLineWidth(2) frame.setMidLineWidth(3) ddsLabel = boldLabel("DDS Control") layout.addWidget(ddsLabel, 0, 0, 1, 2) home_dir = os.path.expanduser("~") dir_ = os.path.join(home_dir, "artiq-master/HardwareConfiguration.py") settings = run_path(dir_) dds_dict = settings["dds_config"] self.all_dds_specs = dict() self.dds_widgets = dict() try: cxn = labrad.connect() p = cxn.parametervault for (name, specs) in dds_dict.items(): try: params = p.get_parameter(["dds_cw_parameters", name]) freq, amp, state, att = params[1] except: freq = str(specs.default_freq) att = str(specs.default_att) amp = str(1.) state = str(0) p.new_parameter("dds_cw_parameters", name, ("cw_settings", [freq, amp, state, att])) self.all_dds_specs[name] = {"cpld": int(specs.urukul), "frequency": float(freq) * 1e6, "att": float(att), "state": bool(int(state)), "amplitude": float(amp)} for i, (name, specs) in enumerate(sorted(dds_dict.items())): widget = ddsControlWidget(name, specs, self.scheduler, self) layout.addWidget(widget, i // 2 + 1 , i % 2) self.dds_widgets[name] = widget frame.setLayout(layout) cxn.disconnect() except: logger.error("Failed to initially connect to labrad.") return frame def set_state(self, override=False): if override: flag = True else: flag = self.onButton.isChecked() if flag: if self.rid is None: if self.setMode.currentText() == "continuous": self.rid = self.scheduler.submit("main", self.expid_continuous, 0) else: self.rid = self.scheduler.submit("main", self.expid_pulsed, 0) self.onButton.setText("Off") else: if self.rid is None: return # Shouldn't happen else: self.scheduler.request_termination(self.rid) self.rid = None self.onButton.setText("On") def set_dc_and_state_readout(self): self.scheduler.submit("main", self.expid_dc, 2) def clear_pmt_plot(self): self.dataset_db.set("clear_pmt_plot", True) @inlineCallbacks def duration_changed(self, *args, **kwargs): # connect to parametervault here if self.pv is None: self.pv = yield self.acxn.get_server("ParameterVault") sender = self.sender() validator = sender.validator() state = validator.validate(sender.text(), 0)[0] if state == QtGui.QValidator.Acceptable: color = "#c4df9b" # green elif state == QtGui.QValidator.Intermediate: color = "#fff79a" # yellow else: color = "#f6989d" # red sender.setStyleSheet("QLineEdit { background-color: %s }" %color) try: min = 1e-3 # 1 us raw_duration = float(sender.text()) duration = raw_duration if raw_duration >= min else min yield self.pv.set_parameter(["PmtReadout", "duration", U(duration, "ms")]) a = yield self.pv.get_parameter(["PmtReadout", "duration"]) if self.rid is None: return else: self.scheduler.request_termination(self.rid) self.rid = None self.set_state(True) except ValueError: # Shouldn't happen yield print("") logger.warning("Problem trying to update duration", exc_info=True) def set_mode(self): txt = str(self.setMode.currentText()) if self.rid is None: self.pulsed = txt == "pulsed" elif txt == "continuous": if not self.pulsed: return else: self.pulsed = False self.scheduler.request_termination(self.rid) self.rid = self.scheduler.submit("main", self.expid_continuous, 0) else: if self.pulsed: return else: self.pulsed = True self.scheduler.request_termination(self.rid) self.rid = self.scheduler.submit("main", self.expid_pulsed, 0) def updateLCD(self): if not self.onButton.isChecked(): self.countDisplay.display(0) return try: raw_val = self.dset_ctl.get("pmt_counts")[-1] try: # duration in mseconds duration = float(self.duration.text()) except ValueError: # picked up a backspace or something logger.warning("Failed to update LCD", exc_info=True) return val = raw_val / duration # kcounts / second self.countDisplay.display(val) except KeyError: # dataset doesn't exist logger.info("dataset doesn't exist yet") self.countDisplay.display(0) except IndexError: # timer too fast pass @inlineCallbacks def toggle_linetrigger(self, *args): sender = self.sender() flag = sender.isChecked() if flag: sender.setText("Off") yield self.pv.set_parameter(["line_trigger_settings", "enabled", True]) else: sender.setText("On") yield self.pv.set_parameter(["line_trigger_settings", "enabled", False]) @inlineCallbacks def linetrigger_duration_changed(self, *args): value = float(self.sender().text()) yield self.pv.set_parameter(["line_trigger_settings", "offset_duration", value]) def piezo_step_size_changed(self): sender = self.sender() step = int(sender.value()) ctl = sender.objectName() self.piezoCurrentPos[ctl].setSingleStep(step) @inlineCallbacks def piezo_changed(self, *args): if self.pm is None: yield print("not connected to picomotor") sender = self.sender() piezo = int(sender.objectName()) current_pos = int(sender.value()) last_pos = self.piezoLastPos[piezo] self.piezoLastPos[piezo] = current_pos move = current_pos - last_pos yield self.pm.relative_move(piezo, move) @inlineCallbacks def toggle_autoload(self, *args): sender = self.autoLoadButton flag = sender.isChecked() if flag: try: self.check_pmt_data_length = len(self.dataset_db.get("pmt_counts")) except KeyError: sender.setChecked(False) return sender.setText("Off") self.expid_ttl.update({"arguments": {"device": "blue_PIs", "state": True}}) if not hasattr(self, "check_pmt_timer"): self.check_pmt_timer = QtCore.QTimer() self.check_pmt_timer.timeout.connect(self.check_pmt_counts) self.check_pmt_timer.start(100) yield self.bb.connect() yield self.bb.set_current(self.autoLoadCurrentSpin.value()) yield self.bb.on() else: sender.setText("On") if not hasattr(self, "check_pmt_timer"): return self.check_pmt_timer.stop() self.expid_ttl.update({"arguments": {"device": "blue_PIs", "state": False}}) yield self.bb.off() self.scheduler.submit("main", self.expid_ttl, priority=1) def check_pmt_counts(self): try: counts = self.dataset_db.get("pmt_counts")[self.check_pmt_data_length:] except KeyError: return if len(counts) == 0: return if max(counts) > int(self.autoLoadSpin.value()): self.autoLoadButton.setChecked(False) self.autoLoadButton.clicked.emit() def save_state(self): return {"ctl": {ctl: self.piezoStepSize[ctl].value() for ctl in self.piezoStepSize.keys()}, "offset": self.linetriggerLineEdit.text(), "autoload": self.autoLoadSpin.value(), "mode": self.setMode.currentText(), "ltrigger": self.linetriggerButton.isChecked(), "current": self.autoLoadCurrentSpin.value()} def restore_state(self, state): for ctl, value in state["ctl"].items(): self.piezoStepSize[ctl].setValue(value) self.piezoCurrentPos[ctl].setSingleStep(int(value)) self.linetriggerLineEdit.setText(state["offset"]) self.autoLoadSpin.setValue(int(state["autoload"])) self.setMode.setCurrentText(state["mode"]) self.linetriggerButton.setChecked(state["ltrigger"]) d = {False: "On", True: "Off"} self.linetriggerButton.setText(d[state["ltrigger"]]) self.autoLoadCurrentSpin.setValue(state["current"]) def setup_listeners(self): self.acxn.add_on_connect("ParameterVault", self.parameter_vault_connect) self.acxn.add_on_disconnect("ParameterVault", self.parameter_vault_disconnect) self.acxn.add_on_connect("picomotorserver", self.picomotor_connect) self.acxn.add_on_disconnect("picomotorserver", self.picomotor_disconnect) self.acxn.add_on_connect("barebonese3663a", self.barebones_connect) self.acxn.add_on_disconnect("barebonese3663a", self.barebones_disconnect) def parameter_vault_connect(self): self.duration.setDisabled(False) def parameter_vault_disconnect(self): self.duration.setDisabled(True) def picomotor_connect(self): for spinbox in self.piezoStepSize.values(): spinbox.setDisabled(False) for spinbox in self.piezoCurrentPos.values(): spinbox.setDisabled(False) def picomotor_disconnect(self): for spinbox in self.piezoStepSize.values(): spinbox.setDisabled(True) for spinbox in self.piezoCurrentPos.values(): spinbox.setDisabled(True) def barebones_connect(self): self.autoLoadCurrentSpin.setDisabled(False) def barebones_disconnect(self): self.autoLoadCurrentSpin.setDisabled(True) @inlineCallbacks def connect_servers(self): if self.pv is None: try: self.pv = yield self.acxn.get_server("ParameterVault") except: self.parameter_vault_disconnect() if self.pm is None: try: self.pm = yield self.acxn.get_server("picomotorserver") except: self.picomotor_disconnect() if self.bb is None: try: self.bb = yield self.acxn.get_server("barebonese3663a") except: self.barebones_disconnect()
def main(): # initialize application args = get_argparser().parse_args() widget_log_handler = log.init_log(args, "dashboard") # load any plugin modules first (to register argument_ui classes, etc.) if args.plugin_modules: for mod in args.plugin_modules: importlib.import_module(mod) if args.db_file is None: args.db_file = os.path.join( get_user_config_dir(), "artiq_dashboard_{server}_{port}.pyon".format( server=args.server.replace(":", "."), port=args.port_notify)) app = QtWidgets.QApplication(["ARTIQ Dashboard"]) loop = QEventLoop(app) asyncio.set_event_loop(loop) atexit.register(loop.close) smgr = state.StateManager(args.db_file) # create connections to master rpc_clients = dict() for target in "schedule", "experiment_db", "dataset_db", "device_db": client = AsyncioClient() loop.run_until_complete( client.connect_rpc(args.server, args.port_control, "master_" + target)) atexit.register(client.close_rpc) rpc_clients[target] = client config = Client(args.server, args.port_control, "master_config") try: server_name = config.get_name() finally: config.close_rpc() disconnect_reported = False def report_disconnect(): nonlocal disconnect_reported if not disconnect_reported: logging.error("connection to master lost, " "restart dashboard to reconnect") disconnect_reported = True sub_clients = dict() for notifier_name, modelf in (("explist", explorer.Model), ("explist_status", explorer.StatusUpdater), ("datasets", datasets.Model), ("schedule", schedule.Model)): subscriber = ModelSubscriber(notifier_name, modelf, report_disconnect) loop.run_until_complete( subscriber.connect(args.server, args.port_notify)) atexit_register_coroutine(subscriber.close) sub_clients[notifier_name] = subscriber broadcast_clients = dict() for target in "log", "ccb": client = Receiver(target, [], report_disconnect) loop.run_until_complete( client.connect(args.server, args.port_broadcast)) atexit_register_coroutine(client.close) broadcast_clients[target] = client # initialize main window main_window = MainWindow( args.server if server_name is None else server_name) smgr.register(main_window) mdi_area = MdiArea() mdi_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) main_window.setCentralWidget(mdi_area) # create UI components expmgr = experiments.ExperimentManager(main_window, sub_clients["datasets"], sub_clients["explist"], sub_clients["schedule"], rpc_clients["schedule"], rpc_clients["experiment_db"]) smgr.register(expmgr) d_shortcuts = shortcuts.ShortcutsDock(main_window, expmgr) smgr.register(d_shortcuts) d_explorer = explorer.ExplorerDock(expmgr, d_shortcuts, sub_clients["explist"], sub_clients["explist_status"], rpc_clients["schedule"], rpc_clients["experiment_db"], rpc_clients["device_db"]) smgr.register(d_explorer) d_datasets = datasets.DatasetsDock(sub_clients["datasets"], rpc_clients["dataset_db"]) smgr.register(d_datasets) d_applets = applets_ccb.AppletsCCBDock(main_window, sub_clients["datasets"], extra_substitutes={ "server": args.server, "port_notify": args.port_notify, "port_control": args.port_control, }) atexit_register_coroutine(d_applets.stop) smgr.register(d_applets) broadcast_clients["ccb"].notify_cbs.append(d_applets.ccb_notify) d_ttl_dds = moninj.MonInj(rpc_clients["schedule"]) loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify)) atexit_register_coroutine(d_ttl_dds.stop) d_schedule = schedule.ScheduleDock(rpc_clients["schedule"], sub_clients["schedule"]) smgr.register(d_schedule) logmgr = log.LogDockManager(main_window) smgr.register(logmgr) broadcast_clients["log"].notify_cbs.append(logmgr.append_message) widget_log_handler.callback = logmgr.append_message # lay out docks right_docks = [ d_explorer, d_shortcuts, d_ttl_dds.ttl_dock, d_ttl_dds.dds_dock, d_ttl_dds.dac_dock, d_datasets, d_applets ] main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, right_docks[0]) for d1, d2 in zip(right_docks, right_docks[1:]): main_window.tabifyDockWidget(d1, d2) main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_schedule) # load/initialize state if os.name == "nt": # HACK: show the main window before creating applets. # Otherwise, the windows of those applets that are in detached # QDockWidgets fail to be embedded. main_window.show() smgr.load() smgr.start() atexit_register_coroutine(smgr.stop) # work around for https://github.com/m-labs/artiq/issues/1307 d_ttl_dds.ttl_dock.show() d_ttl_dds.dds_dock.show() # create first log dock if not already in state d_log0 = logmgr.first_log_dock() if d_log0 is not None: main_window.tabifyDockWidget(d_schedule, d_log0) if server_name is not None: server_description = server_name + " ({})".format(args.server) else: server_description = args.server logging.info("ARTIQ dashboard version: %s", artiq_version) logging.info("ARTIQ dashboard connected to moninj_proxy (%s)", server_description) # run main_window.show() loop.run_until_complete(main_window.exit_request.wait())
def main(): args = get_argparser().parse_args() init_logger_from_args(args) servers = { idx: { "host": ip, "notify": 3250, "control": 3251 } for idx, ip in enumerate(args.server)} while True: measurements = [] for _, server in servers.items(): try: client = RPCClient(server["host"], server["control"]) lasers = client.get_laser_db() for laser in lasers: meas = client.get_freq(laser, age=args.poll_time, priority=3, get_osa_trace=False, blocking=True, mute=False, offset_mode=False) status, freq, _ = meas if status != WLMMeasurementStatus.OKAY: logger.info("{}: measurement error") continue f_ref = lasers[laser]["f_ref"] delta = freq - lasers[laser]["f_ref"] measurements.append({ "measurement": laser, "fields": { "freq": freq, "f_ref": f_ref, "detuning": delta } }) logger.info("{}: freq {} THz, f_ref {} THz, " "detuning {} MHz".format(laser, freq, f_ref, delta)) except OSError: logger.warning("Error querying server {}".format(server)) finally: client.close_rpc() if measurements == []: time.sleep(args.poll_time) continue try: influx = influxdb.InfluxDBClient( host="10.255.6.4", database=args.database, username="******", password="******") influx.write_points(measurements) finally: influx.close() time.sleep(args.poll_time)
def __init__(self, acxn): QtWidgets.QDockWidget.__init__(self, "Manual Controls") self.setObjectName("pmt_control") self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) self.pv = None self.pm = None self.bb = None self.acxn = acxn self.setup_listeners() self.dset_ctl = Client("::1", 3251, "master_dataset_db") self.scheduler = Client("::1", 3251, "master_schedule") self.dataset_db = Client("::1", 3251, "master_dataset_db") self.rid = None self.pulsed = False self.expid_continuous = { "arguments": {}, "class_name": "pmt_collect_continuously", "file": "run_continuously/run_pmt_continuously.py", "log_level": 30, "repo_rev": None, "priority": 0 } self.expid_pulsed = { "arguments": {}, "class_name": "pmt_collect_pulsed", "file": "run_continuously/run_pmt_pulsed.py", "log_level": 30, "repo_rev": None, "priority": 0 } self.expid_ttl = { "class_name": "change_ttl", "file": "misc/manual_ttl_control.py", "log_level": 30, "repo_rev": None, "priority": 1 } self.expid_dds = { "arguments": {}, "class_name": "change_cw", "file": "misc/manual_dds_control.py", "log_level": 30, "repo_rev": None, "priority": 1 } self.expid_dc = { "arguments": {}, "class_name": "set_dopplercooling_and_statereadout", "file": "misc/set_dopplercooling_and_statereadout.py", "log_level": 30, "repo_rev": None, "priority": 2 } frame = QtWidgets.QFrame() layout = QtWidgets.QVBoxLayout() pmt_frame = self.create_pmt_frame() linetrigger_frame = self.create_linetrigger_frame() dds_frame = self.create_dds_frame() picomotor_frame = self.create_picomotor_frame() layout.addWidget(pmt_frame) layout.addWidget(dds_frame) layout.addWidget(linetrigger_frame) layout.addWidget(picomotor_frame) layout.setSpacing(50) layout.setContentsMargins(0, 50, 0, 50) frame.setLayout(layout) scroll = QtWidgets.QScrollArea() scroll.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) scroll.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) scroll.setWidgetResizable(False) scroll.setWidget(frame) scroll.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) scroll.setSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.MinimumExpanding) self.setWidget(scroll) self.connect_servers()
class PulseSequence: scan_params = dict() def __init__(self): self.p = None self.set_subsequence = dict() self.run_after = dict() self.selected_scan = dict() self.time_manager = None self.parameter_dict = None self.simulated_pulses = None self.core = _FakeCore() self.data = edict() self.scheduler = SimulationScheduler() self.rcg_tabs = dict() self.grapher = None self.visualizer = None self.logger = None self.setup_rpc_connections() self.sequence_name = type(self).__name__ self.frequency_scan_sequence_names = [ "Spectrum", "CalibAllLines", "CalibSideband" ] self.rcg_tabs[self.sequence_name] = dict() self.start_time = datetime.now() self.timestamp = self.start_time.strftime("%H%M_%S") self.dir = os.path.join(os.path.expanduser("~"), "data", "simulation", datetime.now().strftime("%Y-%m-%d"), self.sequence_name) os.makedirs(self.dir, exist_ok=True) os.chdir(self.dir) def set_submission_arguments(self, submission_arguments): self.submission_arguments = submission_arguments def write_line(self, output_file, line): # writes a line to both the file and the logger (if uncommented) output_file.write(line + "\n") #self.logger.info(line) def load_parameters(self): if not self.p: self.p = self.load_parameter_vault() self.parameter_dict = {} # add accessed params to parameter_dict for collection_name in self.p: for param_name in self.p[collection_name]: self.parameter_dict[ collection_name + "." + param_name] = self.p[collection_name][param_name] # update trap frequencies in member variables self.trap_frequency_names = list() self.trap_frequency_values = list() for name, value in self.p.TrapFrequencies.items(): self.trap_frequency_names.append(name) self.trap_frequency_values.append(value) def write_parameters_for_scan(self, scan_name): if not self.p: self.load_parameters() # add scan params to parameter_dict self.parameter_dict["Scan.sequence_name"] = self.sequence_name self.parameter_dict["Scan.scan_name"] = scan_name self.parameter_dict["Scan.parameter_name"] = self.scan_parameter_name for k, v in self.scan_settings.items(): self.parameter_dict["Scan." + k] = v # write all the parameters to a file filename = self.timestamp + "_params_" + scan_name + ".txt" with open(filename, "w") as param_file: self.write_line(param_file, str(self.parameter_dict)) print("Parameters written to " + os.path.join(self.dir, filename)) def report_pulse(self, dds, time_switched_on, time_switched_off): simulated_pulse = { "dds_name": dds.name, "time_on": time_switched_on, "time_off": time_switched_off, "freq": dds.freq, "amp": dds.amplitude, "att": dds.att, "phase": dds.phase, } self.simulated_pulses.append(simulated_pulse) def combine_laser_pulses(self): # First, post-process the simulated_pulses to combine pulses that belong # to the same laser tone, e.g. 729G and SP_729G or SP_729G_bichro # for each pulse with dds_name == SP_foo # for each overlapping pulse with dds_name == foo # create a new pulse with dds_name == foo # amp: product # att: sum # freq: sum - 80*MHz # phase: sum # time_off: min # time_on: max self.combined_laser_pulses = [] for pulse in self.simulated_pulses: if pulse["dds_name"].startswith("SP_"): pulse["processed"] = True for other_pulse in self.simulated_pulses: # pulse is a single-pass, e.g. SP_729G or SP_729G_bichro # looking for other_pulse to be the double-pass 729G laser_name = pulse["dds_name"][3:] if laser_name.startswith(other_pulse["dds_name"]): other_pulse["processed"] = True combined_time_on = max(pulse["time_on"], other_pulse["time_on"]) combined_time_off = min(pulse["time_off"], other_pulse["time_off"]) if combined_time_on < combined_time_off: new_pulse = { "dds_name": laser_name, "time_on": combined_time_on, "time_off": combined_time_off, "freq": pulse["freq"] + other_pulse["freq"] - 80e6, "amp": pulse["amp"] * other_pulse["amp"], "att": pulse["att"] + other_pulse["att"], "phase": pulse["phase"] + other_pulse["phase"], } self.combined_laser_pulses.append(new_pulse) self.combined_laser_pulses.extend([ pulse for pulse in self.simulated_pulses if "processed" not in pulse ]) def simulate_with_ion_sim(self): try: return self.julia_simulation_function(self.parameter_dict, self.combined_laser_pulses, self.num_ions, self.current_b_field) except: self.logger.error("Error running IonSim simulation: " + traceback.format_exc()) raise def simulate(self): self.load_parameters() self.setup_carriers() self.setup_dds() self.N = int(self.p.StateReadout.repeat_each_measurement) self.num_ions = int(self.p.IonsOnCamera.ion_number) # Import the Julia simulation function try: path_to_simulate_jl = os.path.join( os.path.dirname(os.path.abspath(__file__)), "simulate.jl") from julia import Main Main.include(path_to_simulate_jl) self.julia_simulation_function = Main.simulate_with_ion_sim except: self.logger.error("Error loading Julia file simulate.jl: " + traceback.format_exc()) raise run_initially_complete = False for scan_name in PulseSequence.scan_params: self.data[scan_name] = edict(x=[], y=[]) x_data = np.array([], dtype=float) y_data = {} # Look up the settings for the current scan. scan_selection = scan_name + "-Scan_Selection" if not scan_selection in self.submission_arguments: continue self.scan_parameter_name = self.submission_arguments[ scan_selection] self.scan_settings = self.submission_arguments[ scan_name + ":" + self.scan_parameter_name] self.selected_scan[scan_name] = self.scan_parameter_name # Output parameters to be used for the current scan. self.write_parameters_for_scan(scan_name) # Call run_initially, but only if this is the first scan. if not run_initially_complete: self.run_initially() run_initially_complete = True # Determine the list of scan points. variable_param_name = self.scan_parameter_name.replace(".", "_") scan_points = [self.get_variable_parameter(variable_param_name)] if self.scan_settings["ty"] == "RangeScan": scan_points = np.linspace(self.scan_settings["start"], self.scan_settings["stop"], self.scan_settings["npoints"]) # Iterate over the scan points and simulate one pulse sequence per point. for scan_idx, scan_point in enumerate(scan_points): # Reset the timer and stored pulse sequence. self.setup_time_manager() self.simulated_pulses = [] # Overwrite the scan parameter value with the current scan point. setattr(self, variable_param_name, scan_point) self.parameter_dict[self.scan_parameter_name] = scan_point # Set the current x value for plotting. May be overwritten inside a pulse sequence. self.current_x_value = scan_point # Initialize the sequence by calling set_subsequence. self.set_subsequence[scan_name]() # Run the pulse sequence function to generate the pulse sequence. current_sequence = getattr(self, scan_name) current_sequence() # Write the generated pulse sequences to a file. filename = self.timestamp + "_pulses_" + scan_name + "_" + str( scan_idx) + ".txt" with open(filename, "w") as pulses_file: self.write_line( pulses_file, json.dumps(self.simulated_pulses, sort_keys=True, indent=4)) print("Pulse sequence written to " + os.path.join(self.dir, filename)) # Post-process the pulses to combine single-pass and double-pass pulses # into laser pulses, and also write these to a file. self.combine_laser_pulses() filename = self.timestamp + "_lasers_" + scan_name + "_" + str( scan_idx) + ".txt" with open(filename, "w") as lasers_file: self.write_line( lasers_file, json.dumps(self.combined_laser_pulses, sort_keys=True, indent=4)) print("Laser sequence written to " + os.path.join(self.dir, filename)) # Call IonSim code to simulate the dynamics. print("Calling IonSim with num_ions=" + str(self.num_ions) + ", " + self.scan_parameter_name + "=" + str(scan_point)) result_data = self.simulate_with_ion_sim() # Guess the plot range. range_offset = self.current_x_value - scan_point range_guess = (scan_points[0] + range_offset, scan_points[-1] + range_offset) # Adjustment for absolute frequency scans, which should be displayed in MHz. if self.sequence_name in self.frequency_scan_sequence_names: self.current_x_value = self.current_x_value * 1e-6 range_guess = (range_guess[0] * 1e-6, range_guess[1] * 1e-6) # Record and plot the result. x_data = np.append(x_data, self.current_x_value) self.perform_state_readout(result_data, y_data) if self.grapher: for curve_name, curve_values in sorted(y_data.items()): plot_title = self.timestamp + " - " + scan_name + " - " + curve_name self.grapher.plot( x_data, curve_values, tab_name=PulseSequence.scan_params[scan_name][0] [0], plot_title=plot_title, append=True, file_="", range_guess=range_guess) # Add the results to self.data and output to file. self.data[scan_name]["x"] = x_data for y_name, y_data in y_data.items(): self.data[scan_name]["y"].append(y_data) filename = self.timestamp + "_results_" + scan_name + ".txt" with open(filename, "w") as results_file: self.write_line(results_file, str(self.data[scan_name])) print("Results written to " + os.path.join(self.dir, filename)) # Visualize the most recent pulse sequence. if self.visualizer: try: dds, ttl, channels = self.make_human_readable_pulses() self.visualizer.plot_simulated_pulses(dds, ttl, channels) except: self.logger.warning( "Failed to plot pulse sequence visualization:" + traceback.format_exc(), exc_info=True) if scan_name in self.run_after: try: self.run_after[scan_name]() except FitError: self.logger.error( "FitError encountered in run_after for " + scan_name, exc_info=True) raise try: self.run_finally() except FitError: self.logger.error("FitError encountered in run_finally", exc_info=True) raise self.logger.info(self.sequence_name + " complete! Timestamp " + self.timestamp + ", output files saved to " + self.dir) if self.grapher: try: self.grapher.close_rpc() except: pass if self.visualizer: try: self.visualizer.close_rpc() except: pass if self.logger: try: self.logger.close_rpc() except: pass def perform_state_readout(self, result_data, y_data): # Takes the data points contained in result_data and appends them # to the accumulated data stored in y_data, taking into account the # setting of the StateReadout.readout_mode parameter. def ensure_curve_exists(y_data, curve_name): if not curve_name in y_data: y_data[curve_name] = np.array([], dtype=float) readout_mode = self.parameter_dict["StateReadout.readout_mode"] if readout_mode in ["pmt", "pmtMLE", "pmt_parity", "pmt_states"]: # Curves are named num_dark:1, num_dark:2, ..., num_dark:self.num_ions for num_dark in range(1, self.num_ions + 1): curve_name = "num_dark:" + str(num_dark) ensure_curve_exists(y_data, curve_name) y_value = np.sum([ result_value for result_name, result_value in result_data.items() if result_name.count('D') == num_dark ]) y_data[curve_name] = np.append(y_data[curve_name], y_value) if readout_mode == "pmt_parity": # TODO: Add parity curve (pmt_parity is not currently implemented) pass elif readout_mode == "pmt_states": # TODO: Add states (pmt_states is not currently implemented) pass elif readout_mode in ["camera"]: # Curves are named dark_ion:0, dark_ion:1, ... for ion_idx in range(self.num_ions): curve_name = "dark_ion:" + str(ion_idx) ensure_curve_exists(y_data, curve_name) y_value = np.sum([ result_value for result_name, result_value in result_data.items() if result_name[ion_idx] == 'D' ]) y_data[curve_name] = np.append(y_data[curve_name], y_value) elif readout_mode in ["camera_states", "camera_parity"]: # Curves are named state:SS, state:SD, etc. for result_name, result_value in result_data.items(): curve_name = "state:" + str(result_name) ensure_curve_exists(y_data, curve_name) y_data[curve_name] = np.append(y_data[curve_name], result_value) if readout_mode == "camera_parity": # Add parity curve curve_name = "parity" ensure_curve_exists(y_data, curve_name) y_value = np.sum([ y_value * (-1)**curve_name.count('D') for curve_name, y_value in result_data.items() ]) y_data[curve_name] = np.append(y_data[curve_name], y_value) def make_human_readable_pulses(self): # Converts self.simulated_pulses into the "human readable" format expected # by the pulse sequence visualizer GUI. # Returns a tuple: (dds, ttl, channels) times = set() dds_names = set() for simulated_pulse in self.simulated_pulses: dds_names.add(simulated_pulse["dds_name"]) times.add(simulated_pulse["time_on"]) times.add(simulated_pulse["time_off"]) dds_names = sorted(dds_names) times = sorted(times) times = times + [times[-1] * 1.01] + [times[-1] * 1.02] raw_channels = [["AdvanceDDS", 0]] + [["unused" + str(i), i] for i in range(1, 32)] raw_ttl = [[time, [1] + [0] * 31] for time in times] def freq_and_amp(dds_name, time): freq = 0.0 amp = 0.0 for simulated_pulse in self.simulated_pulses: if dds_name == simulated_pulse[ "dds_name"] and time > simulated_pulse[ "time_on"] and time <= simulated_pulse["time_off"]: freq = simulated_pulse["freq"] / 1e6 amp = simulated_pulse["amp"] * (10**( -simulated_pulse["att"] / 20)) break return freq, amp raw_dds = [] for time in times[:-1]: for dds_name in dds_names: freq, amp = freq_and_amp(dds_name, time) raw_dds.append([dds_name, freq, amp]) return raw_dds, raw_ttl, raw_channels def setup_rpc_connections(self): try: self.logger = Client("::1", 3289, "simulation_logger") except: self.logger = logging.getLogger("** SIMULATION **") self.logger.warning("Failed to connect to remote logger", exc_info=True) if not self.grapher: try: self.grapher = Client("::1", 3286, "rcg") except: self.logger.warning("Failed to connect to RCG grapher", exc_info=True) self.grapher = None if not self.visualizer: try: self.visualizer = Client("::1", 3289, "pulse_sequence_visualizer") pass except: self.logger.warning( "Failed to connect to pulse sequence visualizer", exc_info=True) self.visualizer = None def setup_carriers(self): self.carrier_names = [ "S+1/2D-3/2", "S-1/2D-5/2", "S+1/2D-1/2", "S-1/2D-3/2", "S+1/2D+1/2", "S-1/2D-1/2", "S+1/2D+3/2", "S-1/2D+1/2", "S+1/2D+5/2", "S-1/2D+3/2" ] self.carrier_dict = {} for idx, name in enumerate(self.carrier_names): self.carrier_dict[name] = idx global_cxn = labrad.connect(dt_config.global_address, password=dt_config.global_password, tls_mode="off") sd_tracker = global_cxn.sd_tracker_global self.current_line_center = float( unitless(sd_tracker.get_current_center(dt_config.client_name))) current_lines = sd_tracker.get_current_lines(dt_config.client_name) _list = [0.] * 10 for carrier, frequency in current_lines: abs_freq = unitless(frequency) for i in range(10): if carrier == self.carrier_names[i]: # for simulation, express carrier frequencies relative to line center _list[i] = abs_freq - self.current_line_center break self.carrier_values = _list self.current_b_field = float( unitless( sd_tracker.get_current_b_local( dt_config.client_name)['gauss'])) def get_trap_frequency(self, name): freq = 0. for i in range(len(self.trap_frequency_names)): if self.trap_frequency_names[i] == name: freq = unitless(self.trap_frequency_values[i]) return freq return 0. def make_dds(self, name): return SimulatedDDS(name, self) def setup_dds(self): self.dds_729G = self.make_dds("729G") self.dds_729L1 = self.make_dds("729L1") self.dds_729L2 = self.make_dds("729L2") self.dds_SP_729G = self.make_dds("SP_729G") self.dds_SP_729L1 = self.make_dds("SP_729L1") self.dds_SP_729L2 = self.make_dds("SP_729L2") self.dds_SP_729G_bichro = self.make_dds("SP_729G_bichro") self.dds_SP_729L1_bichro = self.make_dds("SP_729L1_bichro") self.dds_SP_729L2_bichro = self.make_dds("SP_729L2_bichro") self.dds_397 = self.make_dds("397") self.dds_854 = self.make_dds("854") self.dds_866 = self.make_dds("866") def setup_time_manager(self): class _FakeTimeManager: def __init__(self): self.time = 0. def _noop(self, *args, **kwargs): pass def _take_time(self, duration): self.time += unitless(duration) def _get_time(self): return self.time enter_sequential = _noop enter_parallel = _noop exit = _noop set_time_mu = _noop get_time_mu = _get_time get_time = _get_time take_time_mu = _take_time take_time = _take_time self.time_manager = _FakeTimeManager() core_language.set_time_manager(self.time_manager) def get_729_dds(self, name="729G", id=0): if id == 0: self.dds_729 = self.dds_729G if name == "729G" else self.dds_729L1 if name == "729L1" else self.dds_729L2 self.dds_729_SP = self.dds_SP_729G if name == "729G" else self.dds_SP_729L1 if name == "729L1" else self.dds_SP_729L2 self.dds_729_SP_bichro = self.dds_SP_729G_bichro if name == "729G" else self.dds_SP_729L1_bichro if name == "729L1" else self.dds_SP_729L2_bichro elif id == 1: self.dds_7291 = self.dds_729G if name == "729G" else self.dds_729L1 if name == "729L1" else self.dds_729L2 self.dds_729_SP1 = self.dds_SP_729G if name == "729G" else self.dds_SP_729L1 if name == "729L1" else self.dds_SP_729L2 self.dds_729_SP_bichro1 = self.dds_SP_729G_bichro if name == "729G" else self.dds_SP_729L1_bichro if name == "729L1" else self.dds_SP_729L2_bichro elif id == 2: self.dds_729 = self.dds_729G self.dds_729_SP_line1 = self.dds_SP_729G self.dds_729_SP_line1_bichro = self.dds_SP_729G_bichro self.dds_729_SP_line2 = self.dds_SP_729L2 self.dds_729_SP_line2_bichro = self.dds_SP_729L2_bichro def make_random_list(self, n, mean, std, min=None, max=None): # # Returns a list of n values pulled from a Gaussian distribution # with the given mean and standard deviation, in the range [min, max]. # values = (std * np.random.randn(n) + mean).tolist() for i in range(len(values)): # make sure the values are between min and max if min is not None: values[i] = max(min, amps[i]) if max is not None: values[i] = min(max, amps[i]) return values def make_random_amplitudes(self, n, mean, std): # # Returns a list of n amplitudes pulled from a Gaussian distribution # with the given mean and standard deviation, in the range [0,1]. # return self.make_random_list(n, mean, std, min=0.0, max=1.0) def make_random_frequencies(self, n, mean, std): # # Returns a list of n frequencies pulled from a Gaussian distribution # with the given mean and standard deviation, in the range [0,]. # return self.make_random_list(n, mean, std, min=0.0) def generate_single_pass_noise_waveform(self, mean, std, freq_noise=False): pass def prepare_noisy_single_pass(self, freq_noise=False, id=0): pass def start_noisy_single_pass(self, phase_ref_time, freq_noise=False, freq_sp=WithUnit(80, 'MHz'), amp_sp=1.0, att_sp=8.0, phase_sp=0., use_bichro=False, freq_sp_bichro=WithUnit(80, 'MHz'), amp_sp_bichro=1.0, att_sp_bichro=8.0, phase_sp_bichro=0., id=0): # TODO: this doesn't add any noise right now. dds = self.dds_729_SP dds_bichro = self.dds_729_SP_bichro if id == 1: dds = self.dds_729_SP1 dds_bichro = self.dds_729_SP_bichro1 dds.set(freq_sp, amplitude=amp_sp, phase=phase_sp, ref_time_mu=phase_ref_time) dds.set_att(att_sp) dds.sw.on() if use_bichro: dds_bichro.set(freq_sp_bichro, amplitude=amp_sp_bichro, phase=phase_sp_bichro, ref_time_mu=phase_ref_time) dds_bichro.set_att(att_sp_bichro) dds_bichro.sw.on() def stop_noisy_single_pass(self, use_bichro=False, id=0): dds = self.dds_729_SP dds_bichro = self.dds_729_SP_bichro if id == 1: dds = self.dds_729_SP1 dds_bichro = self.dds_729_SP_bichro1 # Turn off the DDS outputs. dds.sw.off() if use_bichro: dds_bichro.sw.off() def prepare_pulse_with_amplitude_ramp(self, pulse_duration, ramp_duration, dds1_amp=0., use_dds2=False, dds2_amp=0.): self.pulse_duration = pulse_duration self.ramp_duration = ramp_duration self.dds1_amp = dds1_amp if use_dds2: self.dds2_amp = dds2_amp def execute_pulse_with_amplitude_ramp(self, dds1_att=8.0, dds1_freq=0., use_dds2=False, dds2_att=8.0, dds2_freq=0.): # TODO: currently this doesn't actually do any ramping self.dds_729.set(dds1_freq, self.dds1_amp) self.dds_729.set_att(dds1_att) self.dds_729.sw.on() if use_dds2: self.dds_7291.set(dds2_freq, self.dds2_amp) self.dds_7291.set_att(dds2_att) self.dds_7291.sw.on() self.time_manager.take_time(self.pulse_duration) self.dds_729.sw.off() if use_dds2: self.dds_7291.sw.off() def add_subsequence(self, subsequence): self._set_subsequence_defaults(subsequence) subsequence.run = subsequence.subsequence try: subsequence.add_child_subsequences(self) except AttributeError: pass return subsequence def _set_subsequence_defaults(self, subsequence): d = subsequence.__dict__ kwargs = dict() for key, value in d.items(): if type(value) == str: try: c, v = value.split(".") except AttributeError: continue except ValueError: continue try: pv_value = self.p[c][v] except KeyError: #TODO Ryan fix this - throw if a parameter isn't found #raise Exception("Failed to find parameter: " + value) continue try: pv_value = float(pv_value) except: pass kwargs[key] = pv_value for key, value in kwargs.items(): setattr(subsequence, key, value) def get_offset_frequency(self, name): return 0. def calc_frequency(self, line, detuning=0., sideband="", order=0., dds="", bound_param=""): freq = detuning abs_freq = 0. line_set = False sideband_set = True if sideband == "" else False for i in range(10): if line == self.carrier_names[i]: freq += self.carrier_values[i] line_set = True if sideband != "" and i <= len(self.trap_frequency_names) - 1: if sideband == self.trap_frequency_names[i]: freq += self.trap_frequency_values[i] * order sideband_set = True if line_set and sideband_set: abs_freq = freq break # Plot absolute frequencies for frequency scans. if self.sequence_name in self.frequency_scan_sequence_names: self.current_x_value = abs_freq + self.current_line_center return freq def get_variable_parameter(self, name): # All params are fixed in simulation mode for now return getattr(self, name) def load_parameter_vault(self): # Grab parametervault params: cxn = labrad.connect() p = cxn.parametervault collections = p.get_collections() D = dict() for collection in collections: d = dict() names = p.get_parameter_names(collection) for name in names: try: param = unitless(p.get_parameter([collection, name])) d[name] = param setattr(self, collection + "_" + name, param) except: # broken parameter continue D[collection] = d return edict(D) def run_initially(self): # individual pulse sequences should override this pass def sequence(self): # individual pulse sequences should override this raise NotImplementedError def run_finally(self): # individual pulse sequences should override this pass
def main(): # connect to labrad acxn = connection() acxn.connect() acxn.add_on_connect("ParameterVault", parameter_vault_connect) acxn.add_on_disconnect("ParameterVault", parameter_vault_disconnect) # connect to laser room labrad laser_room_acxn = connection() laser_room_acxn.connect(host=laser_room_ip_address, password=lase_room_password, tls_mode="off") # initialize application args = get_argparser().parse_args() widget_log_handler = log.init_log(args, "dashboard") if args.db_file is None: args.db_file = os.path.join( get_user_config_dir(), "artiq_dashboard_{server}_{port}.pyon".format( server=args.server.replace(":", "."), port=args.port_notify)) app = QtWidgets.QApplication(["ARTIQ Dashboard"]) loop = QEventLoop(app) asyncio.set_event_loop(loop) atexit.register(loop.close) smgr = state.StateManager(args.db_file) # create connections to master rpc_clients = dict() for target in "schedule", "experiment_db", "dataset_db": client = AsyncioClient() loop.run_until_complete( client.connect_rpc(args.server, args.port_control, "master_" + target)) atexit.register(client.close_rpc) rpc_clients[target] = client config = Client(args.server, args.port_control, "master_config") try: server_name = config.get_name() finally: config.close_rpc() disconnect_reported = False def report_disconnect(): nonlocal disconnect_reported if not disconnect_reported: logging.error("connection to master lost, " "restart dashboard to reconnect") disconnect_reported = True sub_clients = dict() for notifier_name, modelf in (("explist", explorer.Model), ("explist_status", explorer.StatusUpdater), ("datasets", datasets.Model), ("schedule", schedule.Model)): subscriber = ModelSubscriber(notifier_name, modelf, report_disconnect) loop.run_until_complete( subscriber.connect(args.server, args.port_notify)) atexit_register_coroutine(subscriber.close) sub_clients[notifier_name] = subscriber broadcast_clients = dict() for target in "log", "ccb": client = Receiver(target, [], report_disconnect) loop.run_until_complete( client.connect(args.server, args.port_broadcast)) atexit_register_coroutine(client.close) broadcast_clients[target] = client # initialize main window tabs = TabWidget() main_main_window = MainWindow( args.server if server_name is None else server_name) main_window = MainWindow( args.server if server_name is None else server_name) main_main_window.setCentralWidget(tabs) smgr.register(tabs) smgr.register(main_main_window) smgr.register(main_window, "sortoflikeamainwindowbutnotquite") mdi_area = MdiArea() mdi_area.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) mdi_area.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded) main_window.setCentralWidget(mdi_area) # create UI components expmgr = experiments.ExperimentManager(main_window, sub_clients["explist"], sub_clients["schedule"], rpc_clients["schedule"], rpc_clients["experiment_db"]) smgr.register(expmgr) # d_shortcuts = shortcuts.ShortcutsDock(main_window, expmgr) # smgr.register(d_shortcuts) d_pmt = pmt_control.PMTControlDock(acxn) smgr.register(d_pmt) d_parameter_editor = parameter_editor.ParameterEditorDock(acxn=acxn) smgr.register(d_parameter_editor) needs_parameter_vault.append(d_parameter_editor) d_explorer = explorer.ExplorerDock(expmgr, None, sub_clients["explist"], sub_clients["explist_status"], rpc_clients["schedule"], rpc_clients["experiment_db"]) smgr.register(d_explorer) d_datasets = datasets.DatasetsDock(sub_clients["datasets"], rpc_clients["dataset_db"]) smgr.register(d_datasets) d_applets = applets_ccb.AppletsCCBDock(main_window, sub_clients["datasets"]) atexit_register_coroutine(d_applets.stop) smgr.register(d_applets) broadcast_clients["ccb"].notify_cbs.append(d_applets.ccb_notify) d_ttl_dds = moninj.MonInj() loop.run_until_complete(d_ttl_dds.start(args.server, args.port_notify)) atexit_register_coroutine(d_ttl_dds.stop) d_schedule = schedule.ScheduleDock(rpc_clients["schedule"], sub_clients["schedule"]) smgr.register(d_schedule) logmgr = log.LogDockManager(main_window) smgr.register(logmgr) broadcast_clients["log"].notify_cbs.append(logmgr.append_message) widget_log_handler.callback = logmgr.append_message # lay out docks right_docks = [ d_explorer, d_pmt, d_parameter_editor, d_ttl_dds.ttl_dock, #d_ttl_dds.dds_dock, d_ttl_dds.dac_dock, d_datasets, d_applets ] main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, right_docks[0]) for d1, d2 in zip(right_docks, right_docks[1:]): main_window.tabifyDockWidget(d1, d2) main_window.addDockWidget(QtCore.Qt.BottomDockWidgetArea, d_schedule) tabs.addTab(main_window, "Control") laser_room_tab = LaserRoomTab() smgr.register(laser_room_tab) tabs.addTab(laser_room_tab, "Laser Room") # temp_controller_tab = TempControllerTab() # smgr.register(temp_controller_tab) # tabs.addTab(temp_controller_tab, "Temperature Controller") histograms_tab = ReadoutHistograms(acxn, smgr) smgr.register(histograms_tab) needs_parameter_vault.append(histograms_tab) tabs.addTab(histograms_tab, "Readout") drift_tracker_tab = DriftTracker(laser_room_acxn) smgr.register(drift_tracker_tab) tabs.addTab(drift_tracker_tab, "Drift Tracker") pulse_sequence_tab = PulseSequenceTab() smgr.register(pulse_sequence_tab) tabs.addTab(pulse_sequence_tab, "Pulse Sequence") smgr.load() smgr.start() atexit_register_coroutine(smgr.stop) # load/initialize state if os.name == "nt": # HACK: show the main window before creating applets. # Otherwise, the windows of those applets that are in detached # QDockWidgets fail to be embedded. main_window.show() # work around for https://github.com/m-labs/artiq/issues/1307 d_ttl_dds.ttl_dock.show() d_ttl_dds.dds_dock.show() # create first log dock if not already in state d_log0 = logmgr.first_log_dock() if d_log0 is not None: main_window.tabifyDockWidget(d_schedule, d_log0) if server_name is not None: server_description = server_name + " ({})".format(args.server) else: server_description = args.server logging.info("ARTIQ dashboard %s connected to %s", artiq_version, server_description) main_main_window.show() loop.run_until_complete(main_main_window.exit_request.wait())
class CameraReadoutDock(QtWidgets.QDockWidget): def __init__(self, acxn): QtWidgets.QDockWidget.__init__(self, "Camera Readout") self.acxn = acxn self.setObjectName("CameraReadoutHistogram") self.setFeatures(QtWidgets.QDockWidget.DockWidgetMovable | QtWidgets.QDockWidget.DockWidgetFloatable) self.image = None self.image_region = None self.run_time = None self.main_widget = QtWidgets.QWidget() self.setWidget(self.main_widget) self.make_GUI() self.connect_GUI() self.connect_asyncio_server() def connect_asyncio_server(self): self.loop = asyncio.get_event_loop() self.asyncio_server = Server( {"camera_reference_image": self.RemotePlotting(self)}, None, True) self.task = self.loop.create_task( self.asyncio_server.start("::1", 3288)) class RemotePlotting: def __init__(self, plt): self.plt = plt def plot(self, image, image_region, run_time=None): self.plt.image = image self.plt.image_region = image_region if run_time is None: self.run_time = dt.now().strftime("%Y%m%d_%H%M.%S") try: cxn = labrad.connect() p = cxn.parametervault except: logger.error("Couldn't connect to parametervault", exc_info=True) N = int(p.get_parameter("IonsOnCamera", "ion_number")) x_axis = np.arange(image_region[2], image_region[3] + 1, image_region[0]) y_axis = np.arange(image_region[4], image_region[5] + 1, image_region[1]) xx, yy = np.meshgrid(x_axis, y_axis) fitter = ion_state_detector(N) result, params = fitter.guess_parameters_and_fit(xx, yy, image) p.set_parameter("IonsOnCamera", "fit_background_level", params["background_level"].value) p.set_parameter("IonsOnCamera", "fit_amplitude", params["amplitude"].value) p.set_parameter("IonsOnCamera", "fit_rotation_angle", params["rotation_angle"].value) p.set_parameter("IonsOnCamera", "fit_center_horizontal", params["center_x"].value) p.set_parameter("IonsOnCamera", "fit_center_vertical", params["center_y"].value) p.set_parameter("IonsOnCamera", "fit_spacing", params["spacing"].value) p.set_parameter("IonsOnCamera", "fit_sigma", params["sigma"].value) self.plt.ax.clear() with suppress(Exception): self.plt.cb.remove() I = self.plt.ax.imshow(image, cmap="cividis", interpolation="spline16", extent=[ x_axis.min(), x_axis.max(), y_axis.max(), y_axis.min() ]) self.plt.cb = self.plt.fig.colorbar(I, fraction=0.046, pad=0.04) x_axis_fit = np.linspace(x_axis.min(), x_axis.max(), x_axis.size * 10) y_axis_fit = np.linspace(y_axis.min(), y_axis.max(), y_axis.size * 10) xx, yy = np.meshgrid(x_axis_fit, y_axis_fit) fit = fitter.ion_model(params, xx, yy) self.plt.ax.contour(x_axis_fit, y_axis_fit, fit, 3, colors=[(1., .49, 0., .75)]) if result is not None: # print(lmfit.fit_report(result, show_correl=False)) results_text = lmfit.fit_report(result, show_correl=False) param_results = results_text.split("\n")[-7:] for i, param_result in enumerate(param_results): param_result = param_result.split("(")[0] param_result = param_result.replace(" +/- ", "(")[:-1] param_result = param_result.split(".") param_result1 = param_result[1].split("(") param_result[1] = param_result1[0][:3] + "(" try: param_result[2] = param_result[2][:3] except IndexError: pass param_result = ".".join(param_result) param_result += ")" param_results[i] = param_result results_text = "\n".join(param_results) results_text += "\n chi_red = {:.2f}".format(result.redchi) results_text += "\n runtime = " + str(self.run_time) self.plt.ax.annotate(results_text, (0.5, 0.75), xycoords="axes fraction", color=(1., .49, 0., 1.)) self.plt.canvas.draw() self.plt.ax.relim() self.plt.ax.autoscale(enable=True, axis="both") cxn.disconnect() def enable_button(self): self.plt.reference_image_button.setDisabled(False) def closeEvent(self, event): self.task.cancel() self.loop.create_task(self.asyncio_server.stop()) super(CameraReadoutDock, self).closeEvent(event) def make_GUI(self): layout = QtWidgets.QGridLayout() self.fig = Figure(figsize=(10, 10), tight_layout=True) self.fig.patch.set_facecolor((.97, .96, .96)) self.canvas = FigureCanvasQTAgg(self.fig) self.canvas.setParent(self) # self.canvas.setMinimumSize(800, 800) self.ax = self.fig.add_subplot(111) self.ax.set_facecolor((.97, .96, .96)) self.ax.tick_params(top=False, bottom=False, left=False, right=False, labeltop=True, labelbottom=True, labelleft=True, labelright=False) self.mpl_toolbar = NavigationToolbar2QT(self.canvas, self) self.canvas.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding) self.ax.tick_params(axis="both", direction="in") self.reference_image_button = QtWidgets.QPushButton("reference image") try: cxn = labrad.connect() p = cxn.parametervault except: pass accessed_params = set() parameters = p.get_parameter_names("IonsOnCamera") for parameter in parameters: accessed_params.update({"IonsOnCamera." + parameter}) d_accessed_parameter_editor = ParameterEditorDock( acxn=None, name="Camera Options", accessed_params=accessed_params) d_accessed_parameter_editor.setFeatures( QtGui.QDockWidget.NoDockWidgetFeatures) d_accessed_parameter_editor.setTitleBarWidget(QtGui.QWidget()) d_accessed_parameter_editor.table.setMaximumWidth(390) layout.addWidget(self.mpl_toolbar, 0, 0, 1, 1) layout.addWidget(self.reference_image_button, 0, 2, 1, 1) layout.addWidget(d_accessed_parameter_editor, 1, 0, 1, 1) layout.addWidget(self.canvas, 1, 1, 1, 2) self.main_widget.setLayout(layout) def connect_GUI(self): self.scheduler = Client("::1", 3251, "master_schedule") self.reference_image_button.clicked.connect(self.get_reference_image) def get_reference_image(self): self.reference_image_button.setDisabled(True) expid = { "arguments": {}, "class_name": "ReferenceImage", "file": "misc/reference_image.py", "log_level": 30, "repo_rev": None, "priority": 2 } self.scheduler.submit("main", expid, 2) def save_state(self): return { "image": self.image, "image_region": self.image_region, "run_time": self.run_time } def restore_state(self, state): if state["image"] is not None and state["image_region"] is not None: r = self.RemotePlotting(self) r.plot(state["image"], state["image_region"], run_time=state["run_time"])
def connect_GUI(self): self.scheduler = Client("::1", 3251, "master_schedule") self.reference_image_button.clicked.connect(self.get_reference_image)