Пример #1
0
    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
Пример #2
0
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()
Пример #3
0
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()
Пример #4
0
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()
Пример #5
0
    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()
Пример #6
0
 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
Пример #7
0
    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")
Пример #8
0
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))
Пример #9
0
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
Пример #10
0
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()
Пример #11
0
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())
Пример #12
0
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)
Пример #13
0
    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()
Пример #14
0
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
Пример #15
0
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())
Пример #16
0
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"])
Пример #17
0
 def connect_GUI(self):
     self.scheduler = Client("::1", 3251, "master_schedule")
     self.reference_image_button.clicked.connect(self.get_reference_image)