Ejemplo n.º 1
0
    def initialize_idle_program(self):
        """Make sure we can arm the idle program which plays the idle waveform(default 0V) on all channels."""
        self.assert_synchronized()

        self.logger.info("Initializing idle progam")
        if self._idle_waveform in self._waveforms.by_data:
            self.logger.debug("Idle waveform found on device")
            idle_waveform_name = self._waveforms.by_data[self._idle_waveform].name
        else:
            self.logger.debug("Idle waveform not found on device")
            idle_waveform_name = self.idle_pulse_name(self._idle_waveform.size)
            self._upload_waveform(self._idle_waveform, idle_waveform_name)

        idle_sequence_element = tek_awg.SequenceEntry(entries=[idle_waveform_name] * self.device.n_channels,
                                                     wait=False,
                                                     loop_inf=True,
                                                     loop_count=None,
                                                     goto_ind=None,
                                                     goto_state=False,
                                                     jmp_type='OFF',
                                                     jmp_ind=None)
        try:
            self._idle_program_index = self._sequence_entries.index(idle_sequence_element) + 1
        except ValueError:
            idle_index, *_ = self._get_empty_sequence_positions(1)
            self.logger.debug("Idle sequence entry not found on device. Uploading it to %d", idle_index)
            self._upload_sequencing_element(idle_index, idle_sequence_element)

            self._idle_program_index = self._sequence_entries.index(idle_sequence_element) + 1
        else:
            self.logger.debug("Idle sequence entry found on device: %d", self._idle_program_index)
Ejemplo n.º 2
0
    def test_parse_program(self):
        ill_formed_program = Loop(children=[Loop(children=[Loop()])])

        with self.assertRaisesRegex(AssertionError, 'Invalid program depth'):
            parse_program(ill_formed_program, (), (), TimeType(), (), (), ())

        channels = ('A', 'B', None, None)
        markers = (('A1', None), (None, None), (None, 'C2'), (None, None))

        # we do test offset handling separately
        amplitudes = (1, 1, 1, 1)
        offsets = (0, 0, 0, 0)
        voltage_transformations = tuple(
            mock.Mock(wraps=lambda x: x) for _ in range(4))

        used_channels = {'A', 'B', 'A1', 'C2'}
        wf_defined_channels = used_channels & {'other'}

        sampled_6 = [
            np.zeros((6, )),
            np.arange(6) / 6,
            np.ones((6, )) * 0.42,
            np.array([0., .1, .2, 0., 1, 0]),
            np.array([1., .0, .0, 0., 0, 1])
        ]

        sampled_4 = [
            np.zeros((4, )),
            np.arange(-4, 0) / 4,
            np.ones((4, )) * 0.2,
            np.array([0., -.1, -.2, 0.]),
            np.array([0., 0, 0, 1.])
        ]

        sample_rate_in_GHz = TimeType.from_fraction(1, 2)

        # channel A is the same in wfs_6[1] and wfs_6[2]
        wfs_6 = [
            DummyWaveform(duration=12,
                          sample_output={
                              'A': sampled_6[0],
                              'B': sampled_6[0],
                              'A1': sampled_6[0],
                              'C2': sampled_6[0]
                          },
                          defined_channels=used_channels),
            DummyWaveform(duration=12,
                          sample_output={
                              'A': sampled_6[1],
                              'B': sampled_6[2],
                              'A1': sampled_6[3],
                              'C2': sampled_6[4]
                          },
                          defined_channels=used_channels),
            DummyWaveform(duration=12,
                          sample_output={
                              'A': sampled_6[1],
                              'B': sampled_6[0],
                              'A1': sampled_6[3],
                              'C2': sampled_6[2]
                          },
                          defined_channels=used_channels)
        ]
        wfs_4 = [
            DummyWaveform(duration=8,
                          sample_output={
                              'A': sampled_4[0],
                              'B': sampled_4[0],
                              'A1': sampled_4[2],
                              'C2': sampled_4[3]
                          },
                          defined_channels=used_channels),
            DummyWaveform(duration=8,
                          sample_output={
                              'A': sampled_4[1],
                              'B': sampled_4[2],
                              'A1': sampled_4[2],
                              'C2': sampled_4[3]
                          },
                          defined_channels=used_channels),
            DummyWaveform(duration=8,
                          sample_output={
                              'A': sampled_4[2],
                              'B': sampled_4[0],
                              'A1': sampled_4[2],
                              'C2': sampled_4[3]
                          },
                          defined_channels=used_channels)
        ]

        # unset is equal to sampled_n[0]
        binary_waveforms_6 = [(0, 0, 0), (0, 0, 0), (0, 0, 0), (1, 3, 0),
                              (2, 0, 0), (0, 0, 4), (1, 3, 0), (0, 0, 0),
                              (0, 0, 2)]

        binary_waveforms_4 = [(0, 2, 0), (0, 0, 0), (0, 0, 3), (1, 2, 0),
                              (2, 0, 0), (0, 0, 3), (2, 2, 0), (0, 0, 0),
                              (0, 0, 3)]

        n_bin_waveforms = len(set(binary_waveforms_6)) + len(
            set(binary_waveforms_4))

        tek_waveforms_6 = [
            tek_awg.Waveform(channel=voltage_to_uint16(sampled_6[ch], 1, 0,
                                                       14),
                             marker_1=sampled_6[m1],
                             marker_2=sampled_6[m2])
            for (ch, m1, m2) in binary_waveforms_6
        ]

        tek_waveforms_4 = [
            tek_awg.Waveform(channel=voltage_to_uint16(sampled_4[ch], 1, 0,
                                                       14),
                             marker_1=sampled_4[m1],
                             marker_2=sampled_4[m2])
            for (ch, m1, m2) in binary_waveforms_4
        ]

        tek_waveforms = set(tek_waveforms_4 + tek_waveforms_6)

        # equivalent of wfs_6
        tek_6 = [
            tek_waveforms_6[:3] + [6], tek_waveforms_6[3:6] + [6],
            tek_waveforms_6[6:] + [6]
        ]
        tek_4 = [
            tek_waveforms_4[:3] + [4], tek_waveforms_4[3:6] + [4],
            tek_waveforms_4[6:] + [4]
        ]

        program = [(wfs_6[0], 1), (wfs_4[0], 2), (wfs_6[0], 3), (wfs_6[1], 4),
                   (wfs_4[1], 5), (wfs_6[2], 6), (wfs_4[2], 7), (wfs_6[1], 8),
                   (wfs_6[2], 9)]

        expected_sequence_entries_wfs = [
            tek_6[0], tek_4[0], tek_6[0], tek_6[1], tek_4[1], tek_6[2],
            tek_4[2], tek_6[1], tek_6[2]
        ]

        expected_sequence_entries = tuple(
            tek_awg.SequenceEntry(entries=wfs, loop_count=idx + 1)
            for idx, wfs in enumerate(expected_sequence_entries_wfs))

        loop_program = Loop(children=[
            Loop(waveform=waveform, repetition_count=repetition_count)
            for waveform, repetition_count in program
        ])

        sequence_entries, waveforms = parse_program(
            program=loop_program,
            channels=channels,
            markers=markers,
            sample_rate=sample_rate_in_GHz * 10**9,
            amplitudes=amplitudes,
            voltage_transformations=voltage_transformations,
            offsets=offsets)

        waveform_set = set(waveforms)
        self.assertEqual(len(waveform_set), len(waveforms))
        self.assertIn(4, waveforms)
        self.assertIn(6, waveforms)

        waveform_set = waveform_set - {4, 6}
        self.assertEqual(len(waveform_set), n_bin_waveforms)
        self.assertEqual(tek_waveforms, waveform_set)

        self.assertEqual(len(sequence_entries), 9)
        self.assertEqual(expected_sequence_entries, sequence_entries)
Ejemplo n.º 3
0
    def _process_program(self, name: str, tek_program: TektronixProgram) -> Tuple[Sequence[tek_awg.SequenceEntry],
                                                                                  Mapping[tek_awg.Waveform, str]]:
        """Detect which waveforms are missing and create sequencing entries.
        This function does not communicate with the device.

        Args:
            name:
            tek_program:

        Returns:
            sequencing_elements: List of SequenceEntries
            waveforms_to_upload: Missing waveforms with names
        """
        waveforms_to_upload = dict()
        required_idle_pulses = dict()

        sequencing_elements = []
        for entries, *sequencing_info in tek_program.get_sequencing_elements():
            new_entries = []

            for entry in entries:
                if isinstance(entry, str):
                    # check that we know the waveform
                    wf_name = self._waveforms.by_name[entry].name

                elif isinstance(entry, tek_awg.Waveform):
                    if entry in self._waveforms.by_data:
                        wf_name = self._waveforms.by_data[entry].name

                    elif entry in waveforms_to_upload:
                        wf_name = waveforms_to_upload[entry]

                    else:
                        wf_name = name + '_' + str(abs(hash(entry)))
                        waveforms_to_upload[entry] = wf_name

                else:
                    assert entry - int(entry) == 0
                    entry = int(entry)

                    if entry in required_idle_pulses:
                        wf_name = required_idle_pulses[entry]

                    else:
                        wf_name = self.idle_pulse_name(entry)
                        wf_data = self.make_idle_waveform(entry)

                        if wf_data in self._waveforms.by_data:
                            wf_name = self._waveforms.by_data[wf_data].name

                        else:
                            # rename waveform to idle waveform for clarity
                            waveforms_to_upload[wf_data] = wf_name

                        required_idle_pulses[entry] = wf_name

                new_entries.append(wf_name)

            sequencing_elements.append(tek_awg.SequenceEntry(new_entries,
                                                            *sequencing_info))
        return sequencing_elements, waveforms_to_upload
Ejemplo n.º 4
0
def parse_program(program: Loop,
                  channels: Tuple[Optional[ChannelID], ...],
                  markers: Tuple[Tuple[Optional[ChannelID], Optional[ChannelID]], ...],
                  sample_rate: TimeType,
                  amplitudes: Tuple[float, ...],
                  voltage_transformations: Tuple[Callable, ...],
                  offsets: Tuple[float, ...] = None) -> Tuple[Sequence[tek_awg.SequenceEntry],
                                                              Sequence[tek_awg.Waveform]]:
    """Convert the program into a sequence of sequence table entries and a sequence of waveforms that can be uploaded
    to the device."""
    assert program.depth() == 1, ("Invalid program depth: %d" % program.depth())
    assert program.repetition_count == 1, ("Cannot repeat program a finite number of times (only once not %d)" %
                                           program.repetition_count)

    # For backward compatibility
    # EDIT: I think this is not needed? (Simon)
    if offsets is None:
        offsets = (0.,) * len(amplitudes)

    assert len(channels) == len(markers) == len(amplitudes) == len(voltage_transformations) == len(offsets)

    sequencing_elements = []

    ch_waveforms = {}
    bin_waveforms = {}

    sample_rate_in_GHz = sample_rate / 10**9

    time_array, n_samples = get_sample_times([loop.waveform for loop in program],
                                             sample_rate_in_GHz=sample_rate_in_GHz)

    channel_wise_kwargs = [dict(voltage_to_uint16_kwargs=dict(output_amplitude=amplitude,
                                                              output_offset=offset,
                                                              resolution=14),
                                voltage_transformation=voltage_trafo)
                           for amplitude, offset, voltage_trafo in zip(amplitudes, offsets, voltage_transformations)]

    # List of Tuple[positional channel tuple, set chs to sample]
    channel_infos = [((channel, marker_1, marker_2), {channel, marker_1, marker_2} - {None})
                     for channel, (marker_1, marker_2) in zip(channels, markers)]

    for n_sample, loop in zip(n_samples, program):

        entries = []

        for (positional_chs, chs_to_sample), kwargs in zip(channel_infos, channel_wise_kwargs):

            if not chs_to_sample:
                entries.append(n_sample)
                bin_waveforms[n_sample] = None

            else:
                ch_waveform = loop.waveform.get_subset_for_channels(chs_to_sample)

                if ch_waveform not in ch_waveforms:
                    bin_waveform = _make_binary_waveform(ch_waveform,
                                                         time_array[:n_sample],
                                                         *positional_chs, **kwargs)

                    if bin_waveform in bin_waveforms:
                        # use identical binary waveform already created to save memory
                        bin_waveform = ch_waveforms[bin_waveforms[bin_waveform]]
                    else:
                        bin_waveforms[bin_waveform] = ch_waveform

                    ch_waveforms[ch_waveform] = bin_waveform

                entries.append(ch_waveforms[ch_waveform])

        sequencing_elements.append(
            tek_awg.SequenceEntry(entries=entries,
                                  loop_count=loop.repetition_count)
        )
    return tuple(sequencing_elements), tuple(bin_waveforms.keys())