Пример #1
0
    def add_manual_sweep(self, label, prompt, values, channel=None):
        param = FloatParameter()  # Create the parameter
        param.name = label

        def method(value):
            print(f'Manually set {label} to {value}, then press enter.')
            input()

        param.assign_method(method)
        self.add_sweep(param,
                       values)  # Create the requested sweep on this parameter
Пример #2
0
    def add_instrument_sweep(self,
                             instrument_name,
                             attribute,
                             values,
                             channel=None):
        param = FloatParameter()  # Create the parameter
        param.name = f"{instrument_name} {attribute} {channel}"
        instr = self._instruments[instrument_name]

        def method(value, channel=channel, instr=instr, prop=attribute):
            if channel:
                getattr(instr, "set_" + prop)(channel, value)
            else:
                getattr(instr, "set_" + prop)(value)

        param.assign_method(method)
        self.add_sweep(param,
                       values)  # Create the requested sweep on this parameter
Пример #3
0
    def load_parameter_sweeps(experiment):
        # Load the active sweeps from the sweep ordering
        for name in experiment.sweep_settings['sweepOrder']:
            par = experiment.sweep_settings['sweepDict'][name]
            # Treat segment sweeps separately since they are DataAxes rather than SweepAxes
            if par['x__class__'] != 'SegmentNum':
                # Here we create a parameter for experiment and associate it with the
                # relevant method in the instrument

                # Add a parameter to the experiment corresponding to the thing we want to sweep
                param = FloatParameter()
                param.name = name
                setattr(experiment, name, param)
                experiment._parameters[name] = param

                # Get the instrument
                instr = experiment._instruments[par['instr']]
                method_name = 'set_' + par['x__class__'].lower()
                points = np.linspace(par['start'], par['stop'], par['numPoints'])
                if hasattr(instr, method_name):
                    param.assign_method(getattr(instr, method_name)) # Couple the parameter to the instrument
                    experiment.add_sweep(param, points) # Create the requested sweep on this parameter
                else:
                    raise ValueError("The instrument {} has no method set_{}".format(name, par['x__class__'].lower()))
Пример #4
0
    def add_qubit_sweep(self, qubit, measure_or_control, attribute, values):
        """
        Add a *ParameterSweep* to the experiment. Users specify a qubit property that auspex
        will try to link back to the relevant instrument. For example::
            exp = QubitExpFactory.create(PulsedSpec(q1))
            self.add_qubit_sweep(q1, "measure", "frequency", np.linspace(6e9, 6.5e9, 500))
            self.run_sweeps()
        """
        param = FloatParameter()  # Create the parameter
        param.name = f"{qubit.label} {measure_or_control} {attribute}"

        if measure_or_control not in ["measure", "control"]:
            raise ValueError(
                f"Cannot add sweep for something other than measure or control properties of {qubit}"
            )

        if measure_or_control == "measure":
            logger.debug(f"Sweeping {qubit} measurement")
            thing = list(
                filter(lambda m: m.label == "M-" + qubit.label,
                       self.measurements))
            if len(thing) > 1:
                raise ValueError(
                    f"Found more than one measurement for {qubit}")
            thing = thing[0]
        elif measure_or_control == "control":
            logger.debug(f"Sweeping {qubit} control")
            thing = qubit
        if thing.phys_chan.generator and attribute == "frequency":
            # Mixed up to final frequency
            name = thing.phys_chan.generator.label
            instr = list(
                filter(lambda x: x.name == name,
                       self._instruments.values()))[0]
            method = None
        else:
            # Direct synthesis
            name, chan = thing.phys_chan.label.split("-")[0:2]
            instr = self._instruments[
                name]  #list(filter(lambda x: x.name == name, self._instruments.values()))[0]

            #special casing for APS2 channel amplitude sweeps... is there a better way to do this?
            if isinstance(
                    instr,
                    auspex.instruments.APS2) and attribute == "amplitude":
                chan = [1, 2]

            def method(value,
                       channel=chan,
                       instr=instr,
                       prop=attribute,
                       thing=thing):
                # e.g. keysight.set_amplitude("ch1", 0.5)
                try:
                    getattr(instr, "set_" + prop)(chan, value, thing)
                except:
                    getattr(instr, "set_" + prop)(chan, value)

            param.set_pair = (thing.phys_chan.label, attribute)

        if method:
            # Custom method
            param.assign_method(method)

        else:
            # Get method by name
            if hasattr(instr, "set_" + attribute):
                param.assign_method(getattr(
                    instr, "set_" +
                    attribute))  # Couple the parameter to the instrument
                param.add_post_push_hook(lambda: time.sleep(0.05))
            else:
                raise ValueError("The instrument {} has no method {}".format(
                    name, "set_" + attribute))
            param.set_pair = (instr.name, attribute)
        self.add_sweep(param,
                       values)  # Create the requested sweep on this parameter
Пример #5
0
    def load_parameter_sweeps(experiment, manual_sweep_params=None):
        """Create parameter sweeps (non-segment sweeps) from the settings. Users can provide
        either a space-separated pair of *instr_name method_name* (i.e. *Holzworth1 power*)
        or specify a qubit property that auspex will try to link back to the relevant instrument.
        (i.e. *q1 measure frequency* or *q2 control amplitude 1*). Auspex will create a *SweepAxis*
        for each parameter sweep, and add this axis to all output connectors. If a channel number (1 or 2) is specified, it only sets that channel in the pair"""
        if manual_sweep_params:
            sweeps = manual_sweep_params
            order = [list(sweeps.keys())[0]]
        else:
            sweeps = experiment.settings['sweeps']
            order = experiment.settings['sweepOrder']
        channels = experiment.settings['qubits']
        if 'edges' in experiment.settings:
            channels.update(experiment.settings['edges'])

        for name in order:
            par = sweeps[name]
            # Treat segment sweeps separately since they are DataAxes rather than SweepAxes
            if par['type'] != 'Segment':
                # Here we create a parameter for experiment and associate it with the
                # relevant method of the relevant experiment.

                # Add a parameter to the experiment corresponding to the thing we want to sweep
                if "unit" in par:
                    param = FloatParameter(unit=par["unit"])
                else:
                    param = FloatParameter()
                param.name = name
                setattr(experiment, name, param)
                experiment._parameters[name] = param

                # We might need to return a custom function rather than just a method_name
                method = None

                # Figure our what we are sweeping
                target_info = par["target"].split()
                if target_info[0] in channels:
                    # We are sweeping a qubit, so we must lookup the instrument
                    target = par["target"].split()
                    if target_info[0] in experiment.qubits:
                        name, meas_or_control, prop = target[:3]
                        isqubit = True
                    else:
                        name, prop = target[:2]
                        isqubit = False
                    if len(target) > 2 + isqubit:
                        ch_ind = target[2 + isqubit]
                    channel_params = channels[name][
                        meas_or_control] if isqubit else channels[name]
                    method_name = "set_{}".format(prop.lower())

                    # If sweeping frequency, we should allow for either mixed up signals or direct synthesis.
                    # Sweeping amplitude is always through the AWG channels.
                    if 'generator' in channel_params and prop.lower(
                    ) == "frequency":
                        name = channel_params['generator']
                        instr = experiment._instruments[name]
                    else:
                        # Construct a function that sets a per-channel property
                        name, chan = channel_params['AWG'].split()
                        if len(target) > 3:
                            chan = chan[int(ch_ind) - 1]
                        instr = experiment._instruments[name]

                        def method(value,
                                   channel=chan,
                                   instr=instr,
                                   prop=prop.lower()):
                            # e.g. keysight.set_amplitude("ch1", 0.5)
                            getattr(instr, "set_" + prop)(chan, value)

                elif target_info[0] in experiment._instruments:
                    # We are sweeping an instrument directly
                    # Get the instrument being swept, and find the relevant method
                    name, prop = par["target"].split()
                    instr = experiment._instruments[name]
                    method_name = 'set_' + prop.lower()

                # If there's a "points" property, use those directly. Otherwise, we
                # use numPoints or the step interval.
                if "points" in par:
                    points = par["points"]
                elif "numPoints" in par:
                    points = np.linspace(par['start'], par['stop'],
                                         par['numPoints'])
                elif "step" in par:
                    points = np.arange(par['start'], par['stop'], par['step'])

                if method:
                    # Custom method
                    param.assign_method(method)
                else:
                    # Get method by name
                    if hasattr(instr, method_name):
                        param.assign_method(
                            getattr(instr, method_name)
                        )  # Couple the parameter to the instrument
                    else:
                        raise ValueError(
                            "The instrument {} has no method {}".format(
                                name, method_name))
                param.instr_tree = [instr.name,
                                    prop]  #TODO: extend tree to endpoint
                experiment.add_sweep(
                    param,
                    points)  # Create the requested sweep on this parameter