Exemplo n.º 1
0
    def test_add_pulse_separate_connection(self):
        pulse_sequence = PulseSequence()
        pulse1, = pulse_sequence.add(Pulse(duration=1))
        self.assertEqual(pulse1.t_start, 0)

        pulse2, = pulse_sequence.add(
            Pulse(duration=2, connection_label='output'))
        self.assertEqual(pulse2.t_start, 0)

        pulse3, = pulse_sequence.add(
            Pulse(duration=2, connection_label='output'))
        self.assertEqual(pulse3.t_start, 2)

        connection = SingleConnection(output_instrument='ins1',
                                      output_channel=Channel('ins1', 'ch1'),
                                      input_instrument='ins2',
                                      input_channel=Channel('ins2', 'ch1'))
        pulse4, = pulse_sequence.add(Pulse(duration=5, connection=connection))
        self.assertEqual(pulse4.t_start, 0)
        pulse5, = pulse_sequence.add(Pulse(duration=5, connection=connection))
        self.assertEqual(pulse5.t_start, 5)

        output_connection = SingleConnection(
            output_instrument='ins1',
            output_channel=Channel('ins1', 'ch1'),
            input_instrument='ins2',
            input_channel=Channel('ins2', 'ch1'),
            label='output')
        pulse6, = pulse_sequence.add(
            Pulse(duration=5, connection=output_connection))
        self.assertEqual(pulse6.t_start, 4)
Exemplo n.º 2
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        self._output_channels = {
            # Measured output ranged from -3V to 3 V @ 50 ohm Load.
            f'ch{k}': Channel(
                instrument_name=self.instrument_name(),
                name=f'ch{k}',
                id=k - 1,  # id is 0-based due to spinapi DLL
                #output=(-3.0, 3.0)
                output=True)
            for k in [1, 2]
        }

        self._channels = {
            **self._output_channels, 'software_trig_in':
            Channel(instrument_name=self.instrument_name(),
                    name='software_trig_in',
                    input_trigger=True),
            'trig_in':
            Channel(instrument_name=self.instrument_name(),
                    name='trig_in',
                    input_trigger=True,
                    invert=True)
        }  # Going from high to low triggers

        self.pulse_implementations = [
            SinePulseImplementation(pulse_requirements=[('amplitude', {
                'min': 0,
                'max': 1 / 0.6
            })])
        ]
Exemplo n.º 3
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name=instrument_name, **kwargs)

        # Setup channels
        self._output_channels = {
            f'pxi{k}': Channel(instrument_name=self.instrument_name(),
                               name=f'pxi{k}',
                               id=k)
            for k in range(8)
        }
        self._output_channels['trig_out'] = Channel(
            instrument_name=self.instrument_name(),
            name='trig_out',
            output_TTL=(0, 2))
        self._channels = self._output_channels

        self.pulse_implementations = [
            TriggerPulseImplementation(pulse_requirements=[('t_start', {
                'min': 0,
                'max': 0
            })])
        ]

        self.add_parameter('final_delay',
                           unit='s',
                           initial_value=None,
                           set_cmd=None)
        self.add_parameter('trigger_duration',
                           unit='s',
                           initial_value=100e-9,
                           set_cmd=None)
        self.repeat = True
Exemplo n.º 4
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        self._output_channels = {
            f'ch{ch}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{ch}', id=ch, output=True)
            for ch in self.instrument.channel_idxs}

        self._pxi_channels = {
            f'pxi{k}': Channel(instrument_name=self.instrument_name(),
                               name=f'pxi{k}', id=4000 + k,
                               input_trigger=True, output=True, input=True)
            for k in range(self.instrument.n_triggers)}

        self._channels = {
            **self._output_channels,
            **self._pxi_channels,
            'trig_in': Channel(instrument_name=self.instrument_name(),
                               name='trig_in', input_trigger=True,
                               input_TTL=(0, 5.0)),
            'trig_out': Channel(instrument_name=self.instrument_name(),
                                name='trig_out', output_TTL=(0, 3.3))}

        self.pulse_implementations = [
            # TODO fix sinepulseimplementation by using pulse_to_waveform_sequence
            SinePulseImplementation(
                pulse_requirements=[('frequency', {'min': 0, 'max': 200e6}),
                                    ('amplitude', {'max': 1.5})]),
            AWGPulseImplementation(
                pulse_requirements=[]),
            CombinationPulseImplementation(
                pulse_requirements=[]),
            DCPulseImplementation(
                pulse_requirements=[('amplitude', {'min': -1.5, 'max': 1.5})]),
            DCRampPulseImplementation(
                pulse_requirements=[]),
            TriggerPulseImplementation(
                pulse_requirements=[]),
            MarkerPulseImplementation(
                pulse_requirements=[])
        ]

        self.add_parameter('channel_selection',
                           vals=vals.Lists(),
                           get_cmd=self._get_active_channel_names)

        self.add_parameter('default_sampling_rates', set_cmd=None,
                           initial_value=[500e6] * len(self.instrument.channel_idxs))

        self.add_parameter('trigger_mode',
                           set_cmd=None,
                           initial_value='software',
                           vals=vals.Enum('none', 'hardware', 'software'),
                           docstring='Selects the method to run through the AWG queue.')

        self.trigger_thread = None
        self.waveforms = None
        self.waveform_queue = None
        self.started = False
Exemplo n.º 5
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)
        self._output_channels = {
            f'ch{k}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{k}',
                              id=k,
                              output=True)
            for k in [1, 2]
        }

        self._channels = {
            **self._output_channels, 'trig_in':
            Channel(instrument_name=self.instrument_name(),
                    name='trig_in',
                    input_trigger=True)
        }

        self.pulse_implementations = [
            DCPulseImplementation(pulse_requirements=[('amplitude', {
                'min': -1,
                'max': 1
            })]),
            SinePulseImplementation(pulse_requirements=[('frequency', {
                'max': 500e6
            }), ('amplitude', {
                'min': -1,
                'max': 1
            })])
        ]

        self.add_parameter(
            'pulse_final_delay',
            unit='s',
            set_cmd=None,
            initial_value=.1e-6,
            docstring='Time subtracted from each waveform to ensure '
            'that it is finished once next trigger arrives.')
        self.add_parameter('trigger_in_duration',
                           unit='s',
                           set_cmd=None,
                           initial_value=.1e-6)
        self.add_parameter('active_channels',
                           set_cmd=None,
                           vals=Lists(Enum('ch1', 'ch2')))
        self.add_parameter('sampling_rate',
                           unit='1/s',
                           initial_value=1e9,
                           set_cmd=None,
                           vals=Numbers(max_value=1e9))

        self.waveforms = {}
        self.waveform_filenames = {}
        self.sequence = {}

        # Create silq folder to place waveforms and sequences in
        self.instrument.change_folder('/silq', create_if_necessary=True)
        # Delete all files in folder
        self.instrument.delete_all_files()
Exemplo n.º 6
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        self._output_channels = {
            f'ch{k}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{k}',
                              id=k,
                              output=True)
            for k in [1, 2, 3, 4]
        }

        self._channels = {
            **self._output_channels, 'trig_in':
            Channel(instrument_name=self.instrument_name(),
                    name='trig_in',
                    input_trigger=True),
            'trig_out':
            Channel(instrument_name=self.instrument_name(),
                    name='trig_out',
                    output_TTL=(0, 3.3))
        }
        # TODO check Arbstudio output TTL high voltage

        self.pulse_implementations = [
            SinePulseImplementation(pulse_requirements=[('frequency', {
                'min': 1e6,
                'max': 125e6
            })]),
            DCPulseImplementation(),
            DCRampPulseImplementation(),
            MarkerPulseImplementation(),
            TriggerPulseImplementation()
        ]

        self.add_parameter('trigger_in_duration',
                           set_cmd=None,
                           unit='s',
                           initial_value=100e-9)
        self.add_parameter(
            'pulse_final_delay',
            set_cmd=None,
            unit='s',
            initial_value=1e-6,
            docstring='Final delay up to the end of pulses that '
            'have full waveforms, to ensure that the '
            'waveform is finished before the next '
            'trigger arrives. This does not count for '
            'pulses such as DCPulse, which only have '
            'four points')

        self.add_parameter('active_channels',
                           get_cmd=self._get_active_channels)
Exemplo n.º 7
0
    def test_transition_voltages(self):
        # To test transitions, pulses must be on the same connection
        channel_out = Channel('arbstudio', 'ch1', id=1, output=True)
        channel_in = Channel('device', 'input', id=1, output=True)
        c1 = SingleConnection(output_instrument='arbstudio',
                              output_channel=channel_out,
                              input_instrument='device',
                              input_channel=channel_in)
        pulses = [
            DCPulse(name='dc1',
                    amplitude=0,
                    duration=5,
                    t_start=0,
                    connection=c1),
            DCPulse(name='dc2',
                    amplitude=1,
                    duration=10,
                    t_start=5,
                    connection=c1),
            DCPulse(name='dc3',
                    amplitude=2,
                    duration=8,
                    t_start=15,
                    connection=c1),
            DCPulse(name='dc4',
                    amplitude=3,
                    duration=7,
                    t_start=12,
                    connection=c1)
        ]

        pulse_sequence = PulseSequence(pulses)

        self.assertRaises(TypeError, pulse_sequence.get_transition_voltages)
        self.assertRaises(TypeError,
                          pulse_sequence.get_transition_voltages,
                          connection=c1)
        self.assertRaises(TypeError,
                          pulse_sequence.get_transition_voltages,
                          t=5)

        transition_voltage = pulse_sequence.get_transition_voltages(
            pulse=pulses[1])
        self.assertTupleEqual(transition_voltage, (0, 1))

        transition_voltage = pulse_sequence.get_transition_voltages(
            connection=c1, t=5)
        self.assertTupleEqual(transition_voltage, (0, 1))

        transition_voltage = pulse_sequence.get_transition_voltages(
            connection=c1, t=15)
        self.assertTupleEqual(transition_voltage, (1, 2))
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        # Override untargeted pulse adding (measurement pulses can be added)
        self.pulse_sequence.allow_untargeted_pulses = True

        # Define instrument channels
        # - Two input channels (ch1 and ch2)
        # - One input trigger channel (trig_in)
        self._acquisition_channels = {
            f'ch{k}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{k}', id=k, input=True)
            for k in [1,2]
        }
        self._channels = {
            **self._acquisition_channels,
            'trig_in': Channel(instrument_name=self.instrument_name(),
                               name='trig_in', input_trigger=True)
        }

        self.add_parameter(name='acquisition_channels',
                           set_cmd=None,
                           initial_value=[],
                           vals=vals.Anything(),
                           docstring='Names of acquisition channels '
                                     '[chA, chB, etc.]. Set by the layout')

        self.add_parameter(name='samples',
                           set_cmd=None,
                           initial_value=1,
                           docstring='Number of times to acquire the pulse '
                                     'sequence.')

        self.add_parameter(name='sample_rate',
                           set_cmd=None,
                           initial_value=1,
                           docstring='Number of times to acquire the pulse '
                                     'sequence.')

        # Noise factor used when generating traces
        self.noise_factor = 0.6


        self.blip_probability = 0.45  # Probability for fake blips during read pulse
        self.blip_start = 0.25  # Maximum fraction for blip to start
        self.blip_duration = 0.25  # Maximum duration for a blip
        self.blip_read_amplitude = 0.3  # Maximum read amplitude

        self.pulse_traces = {}
Exemplo n.º 9
0
    def test_get_pulses_connection(self):
        connection = SingleConnection(output_instrument='ins1',
                                      output_channel=Channel('ins1', 'ch1'),
                                      input_instrument='ins2',
                                      input_channel=Channel('ins1', 'ch1'),
                                      label='connection')
        pulse_sequence = PulseSequence()
        pulse1, pulse2 = pulse_sequence.add(
            Pulse('pulse1', duration=1, connection=connection),
            Pulse('pulse1', duration=2))

        retrieved_pulse = pulse_sequence.get_pulse(connection=connection)
        self.assertEqual(retrieved_pulse, pulse1)

        retrieved_pulse = pulse_sequence.get_pulse(
            name='pulse1', connection_label='connection')
        self.assertEqual(retrieved_pulse, pulse1)

        pulse2.connection_label = 'connection'
        self.assertEqual(len(pulse_sequence.get_pulses(connection=connection)),
                         2)
Exemplo n.º 10
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name=instrument_name, **kwargs)

        # Setup channels
        self._output_channels = {
            f'ch{k}': Channel(self.instrument_name(), name=f'ch{k}', id=k)
            for k in range(4)
        }

        self._input_channels = {
            f'pxi{k}': Channel(self.instrument_name(),
                               name=f'pxi{k}',
                               input=True)
            for k in range(4)
        }
        self._input_channels['trig_in'] = Channel(self.instrument_name(),
                                                  name=f'trig_in',
                                                  input=True)

        self._channels = {**self._output_channels, **self._input_channels}

        self.pulse_implementations = [
            DCPulseImplementation(),
            SinePulseImplementation(),
            FrequencyRampPulseImplementation(),
            MarkerPulseImplementation()
        ]

        self.add_parameter('use_trig_in',
                           initial_value=True,
                           set_cmd=None,
                           docstring="Whether to use trig_in for triggering."
                           "All DDS channels listen simultaneosly to"
                           "trig_in, while the pxi channels can "
                           "trigger individual dds channels")

        self.add_parameter('trigger_in_duration',
                           initial_value=.1e-6,
                           set_cmd=None,
                           docstring="Duration for a trigger input")
Exemplo n.º 11
0
    def __init__(self, instrument_name, channels=(1, 2, 3, 4), **kwargs):
        super().__init__(instrument_name, **kwargs)

        self._output_channels = {
            # Measured output TTL is half of 3.3V
            f'ch{k}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{k}',
                              id=k - 1,
                              output_TTL=(0, 3.3 / 2))
            for k in channels
        }
        self._channels = {
            **self._output_channels, 'software_trig_in':
            Channel(instrument_name=self.instrument_name(),
                    name='software_trig_in',
                    input_trigger=True)
        }

        self.pulse_implementations = [
            TriggerPulseImplementation(),
            MarkerPulseImplementation()
        ]
Exemplo n.º 12
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        # Define instrument channels
        # - Two output channels (ch1 and ch2)
        # - One input trigger channel (trig_in)
        self._output_channels = {
            f'ch{k}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{k}', id=k, output=True)
            for k in [1,2]
        }
        self._channels = {
            **self._output_channels,
            'trig_in': Channel(instrument_name=self.instrument_name(),
                               name='trig_in', input_trigger=True)
        }

        self.pulse_implementations = [
            DCPulseImplementation(pulse_requirements=[('amplitude', {'min': -1,
                                                                     'max': 1})]),
            SinePulseImplementation(pulse_requirements=[('frequency', {'max': 500e6}),
                                                        ('amplitude', {'min': -1,
                                                                       'max': 1})])
        ]
Exemplo n.º 13
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        # Define instrument channels
        # - Two outputchannels (ch1 and ch2)
        self._output_channels = {
            f'ch{k}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{k}',
                              id=k,
                              input=True)
            for k in [1, 2]
        }
        self._channels = self._output_channels

        self.pulse_implementations = [
            TriggerPulseImplementation(),
        ]
Exemplo n.º 14
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)
        self.pulse_sequence.allow_untargeted_pulses = True
        self.pulse_sequence.allow_pulse_overlap = True

        # Initialize channels
        self._acquisition_channels = {
            f'ch{k}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{k}',
                              id=k,
                              input=True)
            for k in self.instrument.channel_idxs
        }

        self._pxi_channels = {
            f'pxi{k}': Channel(instrument_name=self.instrument_name(),
                               name=f'pxi{k}',
                               id=4000 + k,
                               input_trigger=True,
                               output=True,
                               input=True)
            for k in range(self.instrument.n_triggers)
        }

        self._channels = {
            **self._acquisition_channels,
            **self._pxi_channels,
            'trig_in':
            Channel(instrument_name=self.instrument_name(),
                    name='trig_in',
                    input=True),
        }

        self.add_parameter(name='acquisition_controller',
                           set_cmd=None,
                           snapshot_value=False,
                           docstring='Acquisition controller for acquiring '
                           'data with SD digitizer. '
                           'Must be acquisition controller object.')

        self.add_parameter(name='acquisition_channels',
                           initial_value=[],
                           set_cmd=None,
                           vals=vals.Lists(),
                           docstring='Names of acquisition channels '
                           '[chA, chB, etc.]. Set by the layout')

        self.add_parameter('sample_rate',
                           vals=vals.Numbers(),
                           set_cmd=None,
                           docstring='Acquisition sampling rate (Hz)')

        self.add_parameter('samples',
                           vals=vals.Numbers(),
                           set_cmd=None,
                           docstring='Number of times to acquire the pulse '
                           'sequence.')

        self.add_parameter(
            'points_per_trace',
            get_cmd=lambda: self.acquisition_controller().samples_per_trace(),
            docstring='Number of points in a trace.')

        self.add_parameter('channel_selection',
                           set_cmd=None,
                           docstring='Active channel indices to acquire. '
                           'Zero-based index (chA -> 0, etc.). '
                           'Set during setup and should not be set'
                           'manually.')

        self.add_parameter(
            'minimum_timeout_interval',
            unit='s',
            vals=vals.Numbers(),
            initial_value=5,
            set_cmd=None,
            docstring='Minimum value for timeout when acquiring '
            'data. If 2.1 * pulse_sequence.duration '
            'is lower than this value, it will be '
            'used instead')

        self.add_parameter(
            'trigger_in_duration',
            unit='s',
            vals=vals.Numbers(),
            initial_value=15e-6,
            set_cmd=None,
            docstring="Duration for a receiving trigger signal. "
            "This is passed the the interface that is "
            "sending the triggers to this instrument.")

        self.add_parameter('capture_full_trace',
                           initial_value=False,
                           vals=vals.Bool(),
                           set_cmd=None,
                           docstring='Capture from t=0 to end of pulse '
                           'sequence. False by default, in which '
                           'case start and stop times correspond to '
                           'min(t_start) and max(t_stop) of all '
                           'pulses with the flag acquire=True, '
                           'respectively.')
        # dict of raw unsegmented traces {ch_name: ch_traces}
        self.traces = {}
        # Segmented traces per pulse, {pulse_name: {channel_name: {ch_pulse_traces}}
        self.pulse_traces = {}

        # Set up the driver to a known default state
        self.initialize_driver()
Exemplo n.º 15
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        self._input_channels = {
            "I": Channel(instrument_name=self.instrument_name(), name="I", input=True),
            "Q": Channel(instrument_name=self.instrument_name(), name="Q", input=True),
            "pulse_mod": Channel(
                instrument_name=self.instrument_name(), name="pulse_mod", input=True
            ),
        }

        self._output_channels = {
            "RF_out": Channel(
                instrument_name=self.instrument_name(), name="RF_out", output=True
            )
        }

        self._channels = {
            **self._input_channels,
            **self._output_channels,
            "sync": Channel(
                instrument_name=self.instrument_name(), name="sync", output=True
            ),
        }

        self.pulse_implementations = [
            SinePulseImplementation(
                pulse_requirements=[
                    ("frequency", {"min": 1e6, "max": 40e9}),
                    ("power", {"min": -120, "max": 25}),
                    ("duration", {"min": 100e-9}),
                ]
            ),
            FrequencyRampPulseImplementation(
                pulse_requirements=[
                    ("frequency_start", {"min": 1e6, "max": 40e9}),
                    ("frequency_stop", {"min": 1e6, "max": 40e9}),
                    ("power", {"min": -120, "max": 25}),
                    ("duration", {"min": 100e-9}),
                ]
            ),
        ]

        self.envelope_padding = Parameter(
            "envelope_padding",
            unit="s",
            set_cmd=None,
            initial_value=0,
            vals=vals.Numbers(min_value=0, max_value=10e-3),
            docstring="Padding for any pulses that use IQ modulation. "
            "This is to ensure that any IQ pulses such as sine waves "
            "are applied a bit before the pulse starts. The marker pulse "
            "used for pulse modulation does not use any envelope padding.",
        )
        self.marker_amplitude = Parameter(
            unit="V",
            set_cmd=None,
            initial_value=1.5,
            docstring="Amplitude of marker pulse used for gating",
        )
        self.fix_frequency = Parameter(
            set_cmd=None,
            initial_value=False,
            vals=vals.Bool(),
            docstring="Whether to fix frequency to current value, or to "
            "dynamically choose frequency during setup",
        )
        self.frequency_carrier_choice = Parameter(
            set_cmd=None,
            initial_value="center",
            vals=vals.MultiType(vals.Enum("min", "center", "max"), vals.Numbers()),
            docstring="The choice for the microwave frequency, This is used if "
            "pulses with multiple frequencies are used, or if frequency "
            "modulation is needed. Ignored if fix_frequency = True. "
            'Can be either "max", "min", or "center", or a '
            "number which is the offset from the center",
        )
        self.frequency = Parameter(
            unit="Hz", set_cmd=None, initial_value=self.instrument.frequency()
        )
        self.power = Parameter(
            unit="dBm",
            set_cmd=None,
            initial_value=self.instrument.power(),
            docstring="Power that the microwave source will be set to. "
            "Set to equal the maximum power of the pulses",
        )
        self.IQ_modulation = Parameter(
            initial_value=None,
            vals=vals.Bool(),
            docstring="Whether to use IQ modulation. Cannot be directly set, but "
            "is set internally if there are pulses with multiple "
            "frequencies, self.fix_frequency() is True, or "
            "self.force_IQ_modulation() is True.",
        )
        self.IQ_channels = Parameter(
            initial_value='IQ',
            vals=vals.Enum('IQ', 'I', 'Q'),
            set_cmd=None,
            docstring="Which channels to use for IQ modulation."
                      "Double-sideband modulation is used if only 'I' or 'Q' "
                      "is chosen, while single-sideband modulation is used when"
                      "'IQ' is chosen."
        )
        self.force_IQ_modulation = Parameter(
            initial_value=False,
            vals=vals.Bool(),
            set_cmd=None,
            docstring="Whether to force IQ modulation.",
        )

        self.marker_per_pulse = Parameter(
            initial_value=True,
            vals=vals.Bool(),
            set_cmd=None,
            docstring='Use a separate marker per pulse. If False, a single '
                      'marker pulse is requested for the first pulse to the last '
                      'pulse. In this case, envelope padding will be added to '
                      'either side of the single marker pulse.'
        )

        # Add parameters that are not set via setup
        self.additional_settings = ParameterNode()
        for parameter_name in [
            "phase",
            "maximum_power",
            "IQ_impairment",
            "I_leakage",
            "Q_leakage",
            "Q_offset",
            "IQ_ratio",
            "IQ_wideband",
            "IQ_crestfactor",
            "reference_oscillator_source",
            "reference_oscillator_output_frequency",
            "reference_oscillator_external_frequency",
        ]:
            parameter = getattr(self.instrument, parameter_name)
            setattr(self.additional_settings, parameter_name, parameter)
Exemplo n.º 16
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        # Initialize channels
        self._input_channels = {
            'ext1': Channel(instrument_name=self.instrument_name(),
                            name='ext1', input=True),
            'ext2': Channel(instrument_name=self.instrument_name(),
                            name='ext2', input=True),
            'I': Channel(instrument_name=self.instrument_name(),
                            name='I', input=True),
            'Q': Channel(instrument_name=self.instrument_name(),
                            name='Q', input=True)
        }
        self._output_channels = {
            'RF_out': Channel(instrument_name=self.instrument_name(),
                              name='RF_out', output=True),
        }

        self._channels = {
            **self._input_channels,
            **self._output_channels,
            'trig_in': Channel(instrument_name=self.instrument_name(),
                               name='trig_in', input=True),
            'pattern_trig_in': Channel(instrument_name=self.instrument_name(),
                                       name='pattern_trig_in', input=True)
        }

        self.pulse_implementations = [
            SinePulseImplementation(
                pulse_requirements=[('frequency', {'min': 250e3, 'max': 44e9})]
            ),
            FrequencyRampPulseImplementation(
                pulse_requirements=[
                    ('frequency_start', {'min': 250e3, 'max': 44e9}),
                    ('frequency_stop', {'min': 250e3, 'max': 44e9})]
            )
        ]

        self.add_parameter('envelope_padding',
                           unit='s',
                           set_cmd=None,
                           initial_value=0,
                           vals=vals.Numbers(min_value=0, max_value=10e-3),
                           docstring="Padding for any pulses that use either "
                                     "IQ and/or FM modulation. This is to "
                                     "ensure that any such pulses start before "
                                     "the gate marker pulse, and end afterwards. "
                                     "This is ignored for chirp pulses where "
                                     "FM_mode = 'IQ'.")
        self.add_parameter('marker_amplitude',
                           unit='V',
                           set_cmd=None,
                           initial_value=1.5,
                           docstring="Amplitude of marker pulse used for gating")
        self.add_parameter('modulation_channel',
                           set_cmd=None,
                           initial_value='ext1',
                           vals=vals.Enum(*self._input_channels),
                           docstring="Channel to use for FM.")
        self.add_parameter('fix_frequency',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring="Whether to fix frequency to current "
                                     "value, or to dynamically choose frequency"
                                     " during setup")
        self.add_parameter('fix_frequency_deviation',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring="Whether to fix frequency_deviation to "
                                     "current value, or to dynamically choose "
                                     "deviation during setup")
        self.add_parameter('frequency_carrier_choice',
                           set_cmd=None,
                           initial_value='center',
                           vals=vals.MultiType(vals.Enum('min', 'center', 'max'),
                                           vals.Numbers()),
                           docstring='The choice for the microwave frequency, '
                                     'This is used if pulses with multiple '
                                     'frequencies are used, or if frequency '
                                     'modulation is needed. Ignored if '
                                     'fix_frequency = True. Can be either "max",'
                                     '"min", or "center", or a number which is '
                                     'the offset from the center')
        self.add_parameter('frequency',
                           unit='Hz',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('frequency_deviation',
                           unit='Hz',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('IQ_modulation',
                           initial_value=None,
                           vals=vals.Enum('on', 'off'),
                           docstring='Whether to use IQ modulation. This '
                                     'cannot be directly set, but is determined '
                                     'by FM_mode and whether pulses have '
                                     'frequency_sideband not None')
        self.add_parameter('FM_mode',
                           set_cmd=None,
                           initial_value='ramp',
                           vals=vals.Enum('ramp', 'IQ'),
                           docstring="Type of frequency modulation used. "
                                     "Can be either 'ramp' in which case the "
                                     "internal FM is used by converting a DC "
                                     "amplitude from an ext port, or 'IQ', in "
                                     "which case the internal FM is turned off.")
Exemplo n.º 17
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        # Initialize channels
        self._input_channels = {
            'ext1': Channel(instrument_name=self.instrument_name(),
                            name='ext1', input=True),
            'ext2': Channel(instrument_name=self.instrument_name(),
                            name='ext2', input=True),
            'int1': Channel(instrument_name=self.instrument_name(),
                            name='int1', input=True),
            'int2': Channel(instrument_name=self.instrument_name(),
                            name='int2', input=True),
            'I': Channel(instrument_name=self.instrument_name(),
                         name='I', input=True),
            'Q': Channel(instrument_name=self.instrument_name(),
                         name='Q', input=True)
        }
        self._output_channels = {
            'RF_out': Channel(instrument_name=self.instrument_name(),
                              name='RF_out', output=True),
        }

        self._channels = {
            **self._input_channels,
            **self._output_channels,
            'trig_in': Channel(instrument_name=self.instrument_name(),
                               name='trig_in', input=True),
            'pattern_trig_in': Channel(instrument_name=self.instrument_name(),
                                       name='pattern_trig_in', input=True)
        }

        self.pulse_implementations = [
            SinePulseImplementation(
                pulse_requirements=[('frequency', {'min': 250e3, 'max': 44e9})]
            ),
            MultiSinePulseImplementation(),
            SingleWaveformPulseImplementation(),
            FrequencyRampPulseImplementation(
                pulse_requirements=[
                    ('frequency_start', {'min': 250e3, 'max': 44e9}),
                    ('frequency_stop', {'min': 250e3, 'max': 44e9})]
            )
        ]

        self.add_parameter('envelope_padding',
                           unit='s',
                           set_cmd=None,
                           initial_value=0,
                           vals=vals.Numbers(min_value=0, max_value=10e-3),
                           docstring="Padding for any pulses that use either "
                                     "IQ and/or FM modulation. This is to "
                                     "ensure that any such pulses start before "
                                     "the gate marker pulse, and end afterwards. "
                                     "This is ignored for chirp pulses where "
                                     "FM_mode = 'IQ'.")
        self.envelope_IQ = Parameter(
            set_cmd=None,
            vals=vals.Bool(),
            initial_value=True,
            docstring="Apply the envelope padding to the IQ pulse instead of marker pulse."
                      "If True, the marker pulse length equals the pulse length, and the "
                      "I and Q pulses are extended by the envelope padding "
                      "before (after) the pulse start (stop) time. "
                      "If False, the marker pulse starts before (after) the pulse start (stop) "
                      "time, and the IQ pulses starts (stops) at the pulse start (stop) time."
                      "This means that there might be some leakage at the carrier frequency "
                      "when the IQ is zero, but the marker pulse is still high."
        )
        self.add_parameter('I_phase_correction',
                           unit='deg',
                           set_cmd=None,
                           initial_value=0,
                           docstring="Additional phase added to I pulse, which compensates "
                                     "any phase mismatch between I and Q components. Only for "
                                     "FM_mode = 'IQ'.")
        self.add_parameter('Q_phase_correction',
                           unit='deg',
                           set_cmd=None,
                           initial_value=0,
                           docstring="Additional phase added to Q pulse, which compensates "
                                     "any phase mismatch between Q and I components. Only for "
                                     "FM_mode = 'IQ'.")
        self.add_parameter('I_amplitude_correction',
                           unit='V',
                           set_cmd=None,
                           initial_value=0,
                           vals=vals.Numbers(min_value=-1, max_value=0),
                           docstring="Amplitude correction added to the amplitude of I pulse"
                                     "to compensate for any mismatch in amplitude/power "
                                     "between I and Q components. The correction is restricted "
                                     "in value between -1V to 0V to ensure the I/Q inputs do not "
                                     "receive signals above 1V. Only for FM_mode = 'IQ'.")
        self.add_parameter('Q_amplitude_correction',
                           unit='V',
                           set_cmd=None,
                           initial_value=0,
                           vals=vals.Numbers(min_value=-1, max_value=0),
                           docstring="Amplitude correction added to the amplitude of Q pulse"
                                     "to compensate for any mismatch in amplitude/power "
                                     "between Q and I components. The correction is restricted "
                                     "in value between -1V to 0V to ensure the I/Q inputs do not "
                                     "receive signals above 1V. Only for FM_mode = 'IQ'.")
        self.add_parameter('marker_amplitude',
                           unit='V',
                           set_cmd=None,
                           initial_value=1.5,
                           docstring="Amplitude of marker pulse used for gating")
        self.add_parameter('modulation_channel',
                           set_cmd=None,
                           initial_value='ext1',
                           vals=vals.Enum(*self._input_channels),
                           docstring="Channel to use for FM.")
        self.add_parameter('fix_frequency',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring="Whether to fix frequency to current "
                                     "value, or to dynamically choose frequency"
                                     " during setup")
        self.add_parameter('fix_frequency_deviation',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring="Whether to fix frequency_deviation to "
                                     "current value, or to dynamically choose "
                                     "deviation during setup")
        self.add_parameter('frequency_carrier_choice',
                           set_cmd=None,
                           initial_value='center',
                           vals=vals.MultiType(vals.Enum('min', 'center', 'max'),
                                               vals.Numbers()),
                           docstring='The choice for the microwave frequency, '
                                     'This is used if pulses with multiple '
                                     'frequencies are used, or if frequency '
                                     'modulation is needed. Ignored if '
                                     'fix_frequency = True. Can be either "max",'
                                     '"min", or "center", or a number which is '
                                     'the offset from the center')
        self.add_parameter('frequency',
                           unit='Hz',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('frequency_deviation',
                           unit='Hz',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('power',
                           unit='dBm',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('IQ_modulation',
                           initial_value=None,
                           vals=vals.Enum('on', 'off'),
                           docstring='Whether to use IQ modulation. This '
                                     'cannot be directly set, but is determined '
                                     'by FM_mode and whether pulses have '
                                     'frequency_sideband not None.')
        self.add_parameter('IQ_channels',
                           initial_value='IQ',
                           vals=vals.Enum('IQ', 'I', 'Q'),
                           set_cmd=None,
                           docstring="Which channels to use for IQ modulation."
                                     "Double-sideband modulation is used if only 'I' or 'Q' "
                                     "is chosen, while single-sideband modulation is used when "
                                     "'IQ' is chosen.")
        self.add_parameter('force_IQ',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring='Force IQ modulation to be enabled, even when'
                                     'outputting only a single frequency.')
        self.add_parameter('FM_mode',
                           set_cmd=None,
                           initial_value='ramp',
                           vals=vals.Enum('ramp', 'IQ'),
                           docstring="Type of frequency modulation used. "
                                     "Can be either 'ramp' in which case the "
                                     "internal FM is used by converting a DC "
                                     "amplitude from an ext port, or 'IQ', in "
                                     "which case the internal FM is turned off.")
Exemplo n.º 18
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)
        self.pulse_sequence.allow_targeted_pulses = True
        self.pulse_sequence.allow_untargeted_pulses = False
        self.pulse_sequence.allow_pulse_overlap = False

        self._clk_freq = int(100e6)

        self.pulse_implementations = [
            TriggerPulseImplementation(pulse_requirements=[])
        ]

        self._data_channels = {
            f'trace_{k}': Channel(instrument_name=self.instrument_name(),
                                  name=f'trace_{k}',
                                  id=k,
                                  output=False,
                                  input=True)
            for k in range(8)
        }

        self._pxi_channels = {
            'pxi{}'.format(k): Channel(instrument_name=self.instrument_name(),
                                       name='pxi{}'.format(k),
                                       id=4000 + k,
                                       input_trigger=True,
                                       output=True,
                                       input=True)
            for k in range(8)
        }

        self._channels = {
            **self._data_channels,
            **self._pxi_channels,
        }

        self.add_parameter('blip_threshold',
                           parameter_class=ManualParameter,
                           vals=vals.Numbers(-3, 3),
                           unit='V',
                           docstring='The blip threshold in volts.')

        self.add_parameter(
            'full_scale_range',
            parameter_class=ManualParameter,
            vals=vals.Numbers(-3, 3),
            unit='V',
            docstring='The full scale range of the trace channel in volts.')

        self.add_parameter(
            'update_time',
            parameter_class=ManualParameter,
            vals=vals.Numbers(),
            unit='s',
            docstring=
            'The length of time in seconds after a blip required to perform the '
            'Bayesian update.')

        self.add_parameter(
            'timeout',
            parameter_class=ManualParameter,
            vals=vals.Numbers(),
            unit='s',
            docstring=
            'The duration since the Bayesian update starts from where you cancel the '
            'Bayesian update and continue with the experiment.')

        self.add_parameter(
            'trace_select',
            parameter_class=ManualParameter,
            vals=vals.Ints(0, 7),
            docstring='The channel you want to select from 0 to 7.')

        self.add_parameter(
            'pxi_channel',
            parameter_class=ManualParameter,
            vals=vals.Ints(4000, 4007),
            docstring='The PXI channel the trigger will be output on.')
Exemplo n.º 19
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        self._output_channels = {
            f'ch{k}': Channel(instrument_name=self.instrument_name(),
                              name=f'ch{k}',
                              id=k,
                              output=True)
            for k in [1, 2, 3, 4]
        }

        self._channels = {
            **self._output_channels, 'trig_in':
            Channel(instrument_name=self.instrument_name(),
                    name='trig_in',
                    input_trigger=True),
            'trig_out':
            Channel(instrument_name=self.instrument_name(),
                    name='trig_out',
                    output_TTL=(0, 3.3))
        }
        # TODO check Arbstudio output TTL high voltage

        self.pulse_implementations = [
            SinePulseImplementation(pulse_requirements=[('frequency', {
                'min': -125e6,
                'max': 125e6
            })]),
            MultiSinePulseImplementation(),
            SingleWaveformPulseImplementation(),
            FrequencyRampPulseImplementation(),
            DCPulseImplementation(),
            DCRampPulseImplementation(),
            MarkerPulseImplementation(),
            TriggerPulseImplementation()
        ]

        self.trigger_in_duration = Parameter(
            set_cmd=None,
            unit='s',
            initial_value=100e-9,
            docstring="Required duration of a trigger pulse, to be requested "
            "from the interface that triggers the Arbstudio")
        self.pulse_final_delay = Parameter(
            set_cmd=None,
            unit='s',
            initial_value=1e-6,
            docstring='The waveform created for pulses are shortened by this '
            'delay to ensure that the waveform is finished before '
            'the next trigger arrives. '
            'Without this delay, trigger pulses may arrive before '
            'the waveform has finished, in which case the trigger '
            'pulse is ignored. This delay is not used for pulses '
            'such as DCPulse, which only have four waveform points.')
        self.force_upload_waveform = Parameter(
            set_cmd=None,
            initial_value=False,
            docstring="Upload waveforms during setup even if they are identical "
            "to the already uploaded waveforms")

        self.active_channels = Parameter()

        self.waveforms = {}
        self.sequences = {}
Exemplo n.º 20
0
    def __init__(self,
                 instrument_name: str,
                 acquisition_controller_names: List[str] = [],
                 default_settings={},
                 **kwargs):
        # TODO: Change acquisition_controller_names to acquisition_controllers
        super().__init__(instrument_name, **kwargs)
        # Override untargeted pulse adding (measurement pulses can be added)
        self.pulse_sequence.allow_untargeted_pulses = True

        default_settings = {
            'channel_range': 2,
            'coupling': 'DC',
            **default_settings
        }

        # Define channels
        self._acquisition_channels = {
            'ch' + idx: Channel(instrument_name=self.instrument_name(),
                                name='ch' + idx,
                                id=idx,
                                input=True)
            for idx in ['A', 'B', 'C', 'D']
        }
        self._aux_channels = {
            'aux' + idx: Channel(instrument_name=self.instrument_name(),
                                 name='aux' + idx,
                                 input_TTL=True,
                                 output_TTL=(0, 5))
            for idx in ['1', '2']
        }
        self._channels = {
            **self._acquisition_channels,
            **self._aux_channels, 'trig_in':
            Channel(instrument_name=self.instrument_name(),
                    name='trig_in',
                    id='trig_in',
                    input_trigger=True),
            'software_trig_out':
            Channel(instrument_name=self.instrument_name(),
                    name='software_trig_out')
        }

        self.pulse_implementations = [
            SteeredInitializationImplementation(pulse_requirements=[]),
            TriggerWaitPulseImplementation(pulse_requirements=[])
        ]

        # Organize acquisition controllers
        self.acquisition_controllers = {}
        for acquisition_controller_name in acquisition_controller_names:
            self.add_acquisition_controller(acquisition_controller_name)

        # Obtain a list of all valid ATS configuration settings
        self._configuration_settings_names = sorted(
            list(inspect.signature(AlazarTech_ATS.config).parameters.keys()))
        # Obtain a list of all valid ATS acquisition settings
        self._acquisition_settings_names = sorted(
            list(inspect.signature(AlazarTech_ATS.acquire).parameters.keys()))
        self._settings_names = sorted(self._acquisition_settings_names +
                                      self._configuration_settings_names)

        self.add_parameter(name='default_settings',
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=default_settings,
                           docstring='Default settings to use when setting up '
                           'ATS for a pulse sequence')
        initial_configuration_settings = {
            k: v
            for k, v in default_settings.items()
            if k in self._configuration_settings_names
        }
        self.add_parameter(
            name='configuration_settings',
            get_cmd=None,
            set_cmd=None,
            vals=vals.Dict(allowed_keys=self._configuration_settings_names),
            initial_value=initial_configuration_settings)
        initial_acquisition_settings = {
            k: v
            for k, v in default_settings.items()
            if k in self._acquisition_settings_names
        }
        self.add_parameter(
            name='acquisition_settings',
            get_cmd=None,
            set_cmd=None,
            vals=vals.Dict(allowed_keys=self._acquisition_settings_names),
            initial_value=initial_acquisition_settings)

        self.add_parameter(name="acquisition",
                           parameter_class=ATSAcquisitionParameter)

        self.add_parameter(name='default_acquisition_controller',
                           set_cmd=None,
                           initial_value='None',
                           vals=vals.Enum(
                               None, 'None',
                               *self.acquisition_controllers.keys()))

        self.add_parameter(name='acquisition_controller',
                           set_cmd=None,
                           vals=vals.Enum(
                               'None', *self.acquisition_controllers.keys()))

        # Names of acquisition channels [chA, chB, etc.]
        self.add_parameter(name='acquisition_channels',
                           set_cmd=None,
                           initial_value=[],
                           vals=vals.Anything(),
                           docstring='Names of acquisition channels '
                           '[chA, chB, etc.]. Set by the layout')

        self.add_parameter(name='samples',
                           set_cmd=None,
                           initial_value=1,
                           docstring='Number of times to acquire the pulse '
                           'sequence.')

        self.add_parameter(
            'points_per_trace',
            get_cmd=lambda: self._acquisition_controller.samples_per_trace(),
            docstring='Number of points in a trace.')

        self.add_parameter(name='trigger_channel',
                           set_cmd=None,
                           initial_value='trig_in',
                           vals=vals.Enum('trig_in', 'disable',
                                          *self._acquisition_channels.keys()))
        self.add_parameter(name='trigger_slope',
                           set_cmd=None,
                           vals=vals.Enum('positive', 'negative'))
        self.add_parameter(name='trigger_threshold',
                           unit='V',
                           set_cmd=None,
                           vals=vals.Numbers())
        self.add_parameter(
            name='sample_rate',
            unit='samples/sec',
            get_cmd=partial(self.setting, 'sample_rate'),
            set_cmd=lambda x: self.default_settings().update(sample_rate=x),
            vals=vals.Numbers(),
            docstring='Acquisition sampling rate (Hz)')

        self.add_parameter('capture_full_trace',
                           initial_value=False,
                           vals=vals.Bool(),
                           set_cmd=None,
                           docstring='Capture from t=0 to end of pulse '
                           'sequence. False by default, in which '
                           'case start and stop times correspond to '
                           'min(t_start) and max(t_stop) of all '
                           'pulses with the flag acquire=True, '
                           'respectively.')

        self.traces = {}
        self.pulse_traces = {}
Exemplo n.º 21
0
    def __init__(self, instrument_name, max_amplitude=1.5, **kwargs):
        assert max_amplitude <= 1.5

        super().__init__(instrument_name, **kwargs)

        self._output_channels = {
            f"ch{k}": Channel(instrument_name=self.instrument_name(),
                              name=f"ch{k}",
                              id=k,
                              output=True)
            for k in [1, 2]
        }

        # TODO add marker outputs
        self._channels = {
            **self._output_channels,
            "trig_in":
            Channel(
                instrument_name=self.instrument_name(),
                name="trig_in",
                input_trigger=True,
            ),
            "event_in":
            Channel(
                instrument_name=self.instrument_name(),
                name="event_in",
                input_trigger=True,
            ),
            "sync":
            Channel(instrument_name=self.instrument_name(),
                    name="sync",
                    output=True),
        }

        self.pulse_implementations = [
            DCPulseImplementation(pulse_requirements=[
                ("amplitude", {
                    "max": max_amplitude
                }),
                ("duration", {
                    "min": 100e-9
                }),
            ]),
            SinePulseImplementation(pulse_requirements=[
                ("frequency", {
                    "min": -1.5e9,
                    "max": 1.5e9
                }),
                ("amplitude", {
                    "min": 0,
                    "max": max_amplitude
                }),
                ("duration", {
                    "min": 100e-9
                }),
            ]),
            FrequencyRampPulseImplementation(pulse_requirements=[
                ("frequency_start", {
                    "min": -1.5e9,
                    "max": 1.5e9
                }),
                ("frequency_stop", {
                    "min": -1.5e9,
                    "max": 1.5e9
                }),
                ("amplitude", {
                    "min": 0,
                    "max": max_amplitude
                }),
                ("duration", {
                    "min": 100e-9
                }),
            ]),
        ]

        self.add_parameter(
            "trigger_in_duration",
            parameter_class=ManualParameter,
            unit="s",
            initial_value=1e-6,
        )
        self.add_parameter(
            "active_channels",
            parameter_class=ManualParameter,
            initial_value=[],
            vals=vals.Lists(vals.Strings()),
        )

        self.instrument.ch1.clear_waveforms()
        self.instrument.ch2.clear_waveforms()

        self.waveforms = {}  # List of waveform arrays for each channel
        # Optional initial waveform for each channel. Used to set the first point
        # to equal the last voltage of the final pulse (see docstring for details)
        self.waveforms_initial = {}
        self.sequences = {}  # List of sequence instructions for each channel
        # offsets list of actual programmed sample points versus expected points
        self.point_offsets = {}
        self.max_point_offsets = {}  # Maximum absolute sample point offset
        self.point = {
        }  # Current sample point, incremented as sequence is programmed
        # Maximum tolerable absolute point offset before raising a warning
        self.point_offset_limit = 100

        # Add parameters that are not set via setup
        self.additional_settings = ParameterNode()
        for instrument_channel in self.instrument.channels:
            channel = ParameterNode(instrument_channel.name)
            setattr(self.additional_settings, instrument_channel.name, channel)

            channel.output_coupling = instrument_channel.output_coupling
            channel.sample_rate = instrument_channel.sample_rate