Beispiel #1
0
    def test_make_compatible_partial_unroll(self):
        wf1 = DummyWaveform(duration=1.5)
        wf2 = DummyWaveform(duration=2.0)

        program = Loop(children=[Loop(waveform=wf1, repetition_count=2),
                                 Loop(waveform=wf2)])

        _make_compatible(program, min_len=1, quantum=1, sample_rate=TimeType.from_float(1.))

        self.assertIsNone(program.waveform)
        self.assertEqual(len(program), 2)
        self.assertIsInstance(program[0].waveform, RepetitionWaveform)
        self.assertIs(program[0].waveform._body, wf1)
        self.assertEqual(program[0].waveform._repetition_count, 2)
        self.assertIs(program[1].waveform, wf2)

        program = Loop(children=[Loop(waveform=wf1, repetition_count=2),
                                 Loop(waveform=wf2)], repetition_count=2)
        _make_compatible(program, min_len=5, quantum=1, sample_rate=TimeType.from_float(1.))

        self.assertIsInstance(program.waveform, SequenceWaveform)
        self.assertEqual(list(program.children), [])
        self.assertEqual(program.repetition_count, 2)

        self.assertEqual(len(program.waveform._sequenced_waveforms), 2)
        self.assertIsInstance(program.waveform._sequenced_waveforms[0], RepetitionWaveform)
        self.assertIs(program.waveform._sequenced_waveforms[0]._body, wf1)
        self.assertEqual(program.waveform._sequenced_waveforms[0]._repetition_count, 2)
        self.assertIs(program.waveform._sequenced_waveforms[1], wf2)
Beispiel #2
0
    def test_make_compatible(self):
        program = Loop()
        pub_kwargs = dict(minimal_waveform_length=5,
                          waveform_quantum=10,
                          sample_rate=TimeType.from_float(1.))
        priv_kwargs = dict(min_len=5, quantum=10, sample_rate=TimeType.from_float(1.))

        with mock.patch('qupulse._program._loop._is_compatible',
                        return_value=_CompatibilityLevel.incompatible_too_short) as mocked:
            with self.assertRaisesRegex(ValueError, 'too short'):
                make_compatible(program, **pub_kwargs)
            mocked.assert_called_once_with(program, **priv_kwargs)

        with mock.patch('qupulse._program._loop._is_compatible',
                        return_value=_CompatibilityLevel.incompatible_fraction) as mocked:
            with self.assertRaisesRegex(ValueError, 'not an integer'):
                make_compatible(program, **pub_kwargs)
            mocked.assert_called_once_with(program, **priv_kwargs)

        with mock.patch('qupulse._program._loop._is_compatible',
                        return_value=_CompatibilityLevel.incompatible_quantum) as mocked:
            with self.assertRaisesRegex(ValueError, 'not a multiple of quantum'):
                make_compatible(program, **pub_kwargs)
            mocked.assert_called_once_with(program, **priv_kwargs)

        with mock.patch('qupulse._program._loop._is_compatible',
                        return_value=_CompatibilityLevel.action_required) as is_compat:
            with mock.patch('qupulse._program._loop._make_compatible') as make_compat:
                make_compatible(program, **pub_kwargs)

                is_compat.assert_called_once_with(program, **priv_kwargs)
                make_compat.assert_called_once_with(program, **priv_kwargs)
Beispiel #3
0
    def test_is_compatible_leaf(self):
        self.assertEqual(_is_compatible(Loop(waveform=DummyWaveform(duration=1.1), repetition_count=10),
                                        min_len=11, quantum=1, sample_rate=TimeType.from_float(1.)),
                         _CompatibilityLevel.action_required)

        self.assertEqual(_is_compatible(Loop(waveform=DummyWaveform(duration=1.1), repetition_count=10),
                                        min_len=11, quantum=1, sample_rate=TimeType.from_float(10.)),
                         _CompatibilityLevel.compatible)
Beispiel #4
0
    def test_get_sample_times_single_wf(self):
        sample_rate = TimeType(12, 10)
        wf = DummyWaveform(duration=TimeType(40, 12))

        expected_times = np.arange(4) / 1.2
        times, n_samples = get_sample_times(wf, sample_rate_in_GHz=sample_rate)

        np.testing.assert_equal(times, expected_times)
        np.testing.assert_equal(n_samples, np.asarray(4))
Beispiel #5
0
    def test_is_compatible_node(self):
        program = Loop(children=[Loop(waveform=DummyWaveform(duration=1.5), repetition_count=2),
                                 Loop(waveform=DummyWaveform(duration=2.0))])

        self.assertEqual(_is_compatible(program, min_len=1, quantum=1, sample_rate=TimeType.from_float(2.)),
                         _CompatibilityLevel.compatible)

        self.assertEqual(_is_compatible(program, min_len=1, quantum=1, sample_rate=TimeType.from_float(1.)),
                         _CompatibilityLevel.action_required)
Beispiel #6
0
    def test_evaluate_with_exact_rationals(self):
        expr = ExpressionScalar('1 / 3')
        self.assertEqual(TimeType.from_fraction(1, 3), expr.evaluate_with_exact_rationals({}))

        expr = ExpressionScalar('a * (1 / 3)')
        self.assertEqual(TimeType.from_fraction(2, 3), expr.evaluate_with_exact_rationals({'a': 2}))

        expr = ExpressionScalar('dot(a, b) * (1 / 3)')
        self.assertEqual(TimeType.from_fraction(10, 3),
                         expr.evaluate_with_exact_rationals({'a': [2, 2], 'b': [1, 4]}))
Beispiel #7
0
    def test_unsafe_get_subset_for_channels(self):
        dwf_1 = DummyWaveform(duration=2.2, defined_channels={'A', 'B', 'C'})
        dwf_2 = DummyWaveform(duration=3.3, defined_channels={'A', 'B', 'C'})

        wf = SequenceWaveform([dwf_1, dwf_2])

        subset = {'A', 'C'}
        sub_wf = wf.unsafe_get_subset_for_channels(subset)
        self.assertIsInstance(sub_wf, SequenceWaveform)

        self.assertEqual(len(sub_wf.compare_key), 2)
        self.assertEqual(sub_wf.compare_key[0].defined_channels, subset)
        self.assertEqual(sub_wf.compare_key[1].defined_channels, subset)

        self.assertEqual(sub_wf.compare_key[0].duration, TimeType.from_float(2.2))
        self.assertEqual(sub_wf.compare_key[1].duration, TimeType.from_float(3.3))
Beispiel #8
0
    def _get_measurement_windows(self) -> DefaultDict[str, np.ndarray]:
        temp_meas_windows = defaultdict(list)
        if self._measurements:
            for (mw_name, begin, length) in self._measurements:
                temp_meas_windows[mw_name].append((begin, length))

            for mw_name, begin_length_list in temp_meas_windows.items():
                temp_meas_windows[mw_name] = [np.asarray(begin_length_list, dtype=float)]

        # calculate duration together with meas windows in the same iteration
        if self.is_leaf():
            body_duration = float(self.body_duration)
        else:
            offset = TimeType(0)
            for child in self:
                for mw_name, begins_length_array in child._get_measurement_windows().items():
                    begins_length_array[:, 0] += float(offset)
                    temp_meas_windows[mw_name].append(begins_length_array)
                offset += child.duration

            body_duration = float(offset)

        # repeat and add repetition based offset
        for mw_name, begin_length_list in temp_meas_windows.items():
            temp_begin_length_array = np.concatenate(begin_length_list)

            begin_length_array = np.tile(temp_begin_length_array, (self.repetition_count, 1))

            shaped_begin_length_array = np.reshape(begin_length_array, (self.repetition_count, -1, 2))

            shaped_begin_length_array[:, :, 0] += (np.arange(self.repetition_count) * body_duration)[:, np.newaxis]

            temp_meas_windows[mw_name] = begin_length_array

        return temp_meas_windows
Beispiel #9
0
    def _upload(self, name: str,
                program: Loop,
                channels: Tuple[Optional[ChannelID], ...],
                markers: Tuple[Optional[ChannelID], ...],
                voltage_transformation: Tuple[Callable, ...],
                force: bool):
        assert self._idle_program_index

        if name in self._programs and not force:
            raise ProgramOverwriteException(name)

        # group markers in by channels
        markers = tuple(zip(markers[0::2], markers[1::2]))

        if self._amplitude_offset_handling == AWGAmplitudeOffsetHandling.IGNORE_OFFSET:
            offsets = None
        elif self._amplitude_offset_handling == AWGAmplitudeOffsetHandling.CONSIDER_OFFSET:
            offsets = self.device.get_offset()
        else:
            raise ValueError('{} is invalid as AWGAmplitudeOffsetHandling'.format(self._amplitude_offset_handling))

        tek_program = TektronixProgram(program, channels=channels, markers=markers,
                                       amplitudes=self.device.get_amplitude(),
                                       offsets=offsets,
                                       voltage_transformations=voltage_transformation,
                                       sample_rate=TimeType(self.sample_rate))

        self.logger.debug("Successfully parsed %s", name)

        if name in self._programs:
            self._unload(name)

        self._upload_parsed(name, tek_program)
Beispiel #10
0
    def setUp(self) -> None:
        self.channels = ('A', None, 'C')
        self.marker = (None, 'M')
        self.amplitudes = (1., 1., .5)
        self.offset = (0., .5, .0)
        self.voltage_transformations = (mock.Mock(wraps=lambda x: x),
                                        mock.Mock(wraps=lambda x: x),
                                        mock.Mock(wraps=lambda x: x))
        self.sample_rate = TimeType.from_float(1)

        N = 100
        t = np.arange(N)

        self.sampled = [
            dict(A=np.linspace(-.1, .1, num=N),
                 C=.1 * np.sin(t),
                 M=np.arange(N) % 2),
            dict(A=np.linspace(.1, -.1, num=N // 2),
                 C=.1 * np.cos(t[::2]),
                 M=np.arange(N // 2) % 3)
        ]
        self.waveforms = [
            wf for wf in (DummyWaveform(sample_output=sampled,
                                        duration=sampled['A'].size)
                          for sampled in self.sampled)
        ]
        self.loop = Loop(children=[Loop(waveform=wf)
                                   for wf in self.waveforms] * 2)
Beispiel #11
0
    def test_from_sequence(self):
        dwf = DummyWaveform(duration=1.1, defined_channels={'A'})

        self.assertIs(dwf, SequenceWaveform.from_sequence((dwf,)))

        swf1 = SequenceWaveform.from_sequence((dwf, dwf))
        swf2 = SequenceWaveform.from_sequence((swf1, dwf))

        assert_constant_consistent(self, swf1)
        assert_constant_consistent(self, swf2)

        self.assertEqual(3*(dwf,), swf2.sequenced_waveforms)

        cwf_2_a = ConstantWaveform(duration=1.1, amplitude=2.2, channel='A')
        cwf_3 = ConstantWaveform(duration=1.1, amplitude=3.3, channel='A')
        cwf_2_b = ConstantWaveform(duration=1.1, amplitude=2.2, channel='A')

        with mock.patch.object(ConstantWaveform, 'from_mapping', return_value=mock.sentinel) as from_mapping:
            new_constant = SequenceWaveform.from_sequence((cwf_2_a, cwf_2_b))
            self.assertIs(from_mapping.return_value, new_constant)
            from_mapping.assert_called_once_with(2*TimeType.from_float(1.1), {'A': 2.2})

        swf3 = SequenceWaveform.from_sequence((cwf_2_a, dwf))
        self.assertEqual((cwf_2_a, dwf), swf3.sequenced_waveforms)
        self.assertIsNone(swf3.constant_value('A'))
        assert_constant_consistent(self, swf3)

        swf3 = SequenceWaveform.from_sequence((cwf_2_a, cwf_3))
        self.assertEqual((cwf_2_a, cwf_3), swf3.sequenced_waveforms)
        self.assertIsNone(swf3.constant_value('A'))
        assert_constant_consistent(self, swf3)
Beispiel #12
0
 def set_measurement_mask(self, program_name, mask_name, begins,
                          lengths) -> Tuple[np.ndarray, np.ndarray]:
     sample_factor = TimeType(
         int(
             self.config.captureClockConfiguration.numeric_sample_rate(
                 self.card.model)), 10**9)
     return self._registered_programs[program_name].set_measurement_mask(
         mask_name, sample_factor, begins, lengths)
Beispiel #13
0
 def __init__(self,
              duration: float = 0,
              sample_output: Union[numpy.ndarray, dict] = None,
              defined_channels={'A'}) -> None:
     super().__init__()
     self.duration_ = TimeType.from_float(duration)
     self.sample_output = sample_output
     self.defined_channels_ = defined_channels
     self.sample_calls = []
Beispiel #14
0
    def arm_program(self, program_name: str) -> None:
        to_arm = self._registered_programs[program_name]
        if self.update_settings or self.__armed_program is not to_arm:
            config = self.config
            config.masks, config.operations, total_record_size = self._registered_programs[
                program_name].iter(self._make_mask)

            sample_factor = TimeType.from_fraction(
                self.config.captureClockConfiguration.numeric_sample_rate(
                    self.card.model), 10**9)

            if not config.operations:
                raise RuntimeError(
                    "No operations: Arming program without operations is an error as there will "
                    "be no result: %r" % program_name)

            elif not config.masks:
                raise RuntimeError(
                    "No masks although there are operations in program: %r" %
                    program_name)

            elif self._registered_programs[
                    program_name].sample_factor != sample_factor:
                raise RuntimeError(
                    "Masks were registered with a different sample rate {}!={}"
                    .format(
                        self._registered_programs[program_name].sample_factor,
                        sample_factor))

            assert total_record_size > 0

            minimum_record_size = self.__card.minimum_record_size
            total_record_size = ((
                (total_record_size - 1) // minimum_record_size) +
                                 1) * minimum_record_size

            if config.totalRecordSize == 0:
                config.totalRecordSize = total_record_size
            elif config.totalRecordSize < total_record_size:
                raise ValueError(
                    'specified total record size is smaller than needed {} < {}'
                    .format(config.totalRecordSize, total_record_size))

            old_aimed_buffer_size = config.aimedBufferSize

            # work around for measurments not working with one buffer
            if config.totalRecordSize < 5 * config.aimedBufferSize:
                config.aimedBufferSize = config.totalRecordSize // 5

            self.__card.applyConfiguration(config, True)

            # "Hide" work around from the user
            config.aimedBufferSize = old_aimed_buffer_size

            self.update_settings = False
            self.__armed_program = to_arm
        self.__card.startAcquisition(1)
Beispiel #15
0
 def __init__(self, duration: Union[float, TimeType]=0, sample_output: Union[numpy.ndarray, dict]=None, defined_channels=None) -> None:
     super().__init__(duration=duration if isinstance(duration, TimeType) else TimeType.from_float(duration))
     self.sample_output = sample_output
     if defined_channels is None:
         if isinstance(sample_output, dict):
             defined_channels = set(sample_output.keys())
         else:
             defined_channels = {'A'}
     self.defined_channels_ = defined_channels
     self.sample_calls = []
Beispiel #16
0
    def test_get_sample_times(self):
        sample_rate = TimeType.from_fraction(12, 10)
        wf1 = DummyWaveform(duration=TimeType.from_fraction(20, 12))
        wf2 = DummyWaveform(duration=TimeType.from_fraction(400000000001, 120000000000))
        wf3 = DummyWaveform(duration=TimeType.from_fraction(1, 10**15))

        expected_times = np.arange(4) / 1.2
        times, n_samples = get_sample_times([wf1, wf2], sample_rate_in_GHz=sample_rate)
        np.testing.assert_equal(expected_times, times)
        np.testing.assert_equal(n_samples, np.asarray([2, 4]))

        with self.assertRaises(AssertionError):
            get_sample_times([], sample_rate_in_GHz=sample_rate)

        with self.assertRaisesRegex(ValueError, "non integer length"):
            get_sample_times([wf1, wf2], sample_rate_in_GHz=sample_rate, tolerance=0.)

        with self.assertRaisesRegex(ValueError, "length <= zero"):
            get_sample_times([wf1, wf3], sample_rate_in_GHz=sample_rate)
Beispiel #17
0
    def register_measurement_windows(self,
                                     program_name: str,
                                     windows: Dict[str, Tuple[np.ndarray, np.ndarray]]) -> None:
        program = self._registered_programs[program_name]
        sample_factor = TimeType.from_fraction(int(self.config.captureClockConfiguration.numeric_sample_rate(self.card.model)),
                                 10 ** 9)
        program.clear_masks()

        for mask_name, (begins, lengths) in windows.items():
            program.set_measurement_mask(mask_name, sample_factor, begins, lengths)
Beispiel #18
0
 def body_duration(self) -> TimeType:
     if self._cached_body_duration is None:
         if self.is_leaf():
             if self.waveform:
                 self._cached_body_duration = self.waveform.duration
             else:
                 self._cached_body_duration = TimeType(0)
         else:
             self._cached_body_duration = sum(child.duration for child in self)
     return self._cached_body_duration
Beispiel #19
0
    def arm_program(self, program_name: str) -> None:
        logger.debug("Arming program %s on %r", program_name, self.__card)

        to_arm = self._registered_programs[program_name]
        if self.update_settings or self.__armed_program is not to_arm:
            logger.info("Arming %r by calling applyConfiguration. Update settings flag: %r",
                        self.__card, self.update_settings)

            config = copy.deepcopy(self.default_config)
            config.masks, config.operations, total_record_size = self._registered_programs[program_name].iter(
                self._make_mask)

            sample_rate = config.captureClockConfiguration.numeric_sample_rate(self.card.model)

            # sample rate in GHz
            sample_factor = TimeType.from_fraction(sample_rate, 10 ** 9)

            if not config.operations:
                raise RuntimeError("No operations: Arming program without operations is an error as there will "
                                   "be no result: %r" % program_name)

            elif not config.masks:
                raise RuntimeError("No masks although there are operations in program: %r" % program_name)

            elif self._registered_programs[program_name].sample_factor != sample_factor:
                raise RuntimeError("Masks were registered with a different sample rate {}!={}".format(
                    self._registered_programs[program_name].sample_factor, sample_factor))

            assert total_record_size > 0

            # extend the total record size to be a multiple of record_size_factor
            record_size_factor = self.record_size_factor
            total_record_size = (((total_record_size - 1) // record_size_factor) + 1) * record_size_factor

            if config.totalRecordSize == 0:
                config.totalRecordSize = total_record_size
            elif config.totalRecordSize < total_record_size:
                raise ValueError('specified total record size is smaller than needed {} < {}'.format(config.totalRecordSize,
                                                                                                     total_record_size))
            self.__card.applyConfiguration(config, True)
            self._current_config = config

            self.update_settings = False
            self.__armed_program = to_arm

        elif self.__armed_program is to_arm and self._remaining_auto_triggers > 0:
            self._remaining_auto_triggers -= 1
            logger.info("Relying on atsaverage auto-arm with %d auto triggers remaining after this one",
                        self._remaining_auto_triggers)
            return

        self.__card.startAcquisition(to_arm.auto_rearm_count)
        self._remaining_auto_triggers = to_arm.auto_rearm_count - 1
Beispiel #20
0
 def setUp(self) -> None:
     self._instr_props = None
     self.program_entry_kwargs = dict(
         amplitudes=(1., 1.),
         offsets=(0., 0.),
         voltage_transformations=(mock.Mock(wraps=lambda x: x),
                                  mock.Mock(wraps=lambda x: x)),
         sample_rate=TimeType.from_fraction(192, 1),
         mode=None)
     if tabor_control is not None:
         self._instr_props = tabor_control.util.model_properties_dict[
             'WX2184C'].copy()
    def test_build_waveform_time_type(self):
        from qupulse.utils.types import TimeType

        table = TablePulseTemplate({0: [(0, 0),
                                        ('foo', 'v', 'linear'),
                                        ('bar', 0, 'jump')]},
                                   parameter_constraints=['foo>1'],
                                   measurements=[('M', 'b', 'l'),
                                                 ('N', 1, 2)])

        parameters = {'v': 2.3,
                      'foo': TimeType.from_float(1.), 'bar': TimeType.from_float(4),
                      'b': TimeType.from_float(2), 'l': TimeType.from_float(1)}
        channel_mapping = {0: 'ch'}

        with self.assertRaises(ParameterConstraintViolation):
            table.build_waveform(parameters=parameters,
                                 channel_mapping=channel_mapping)

        parameters['foo'] = TimeType.from_float(1.1)
        waveform = table.build_waveform(parameters=parameters,
                                        channel_mapping=channel_mapping)

        self.assertIsInstance(waveform, TableWaveform)
        self.assertEqual(waveform._table,
                         ((0, 0, HoldInterpolationStrategy()),
                          (TimeType.from_float(1.1), 2.3, LinearInterpolationStrategy()),
                          (4, 0, JumpInterpolationStrategy())))
        self.assertEqual(waveform._channel_id,
                         'ch')
Beispiel #22
0
    def _get_measurement_windows(self) -> Mapping[str, np.ndarray]:
        """Private implementation of get_measurement_windows with a slightly different data format for easier tiling.

        Returns:
             A dictionary (measurement_name -> array) with begin == array[:, 0] and length == array[:, 1]
        """
        temp_meas_windows = defaultdict(list)
        if self._measurements:
            for (mw_name, begin, length) in self._measurements:
                temp_meas_windows[mw_name].append((begin, length))

            for mw_name, begin_length_list in temp_meas_windows.items():
                temp_meas_windows[mw_name] = [
                    np.asarray(begin_length_list, dtype=float)
                ]

        # calculate duration together with meas windows in the same iteration
        if self.is_leaf():
            body_duration = float(self.body_duration)
        else:
            offset = TimeType(0)
            for child in self:
                for mw_name, begins_length_array in child._get_measurement_windows(
                ).items():
                    begins_length_array[:, 0] += float(offset)
                    temp_meas_windows[mw_name].append(begins_length_array)
                offset += child.duration

            body_duration = float(offset)

        # this gives us regular dict behaviour of the returned object
        temp_meas_windows.default_factory = None

        # repeat and add repetition based offset
        for mw_name, begin_length_list in temp_meas_windows.items():
            temp_begin_length_array = np.concatenate(begin_length_list)

            begin_length_array = np.tile(temp_begin_length_array,
                                         (self.repetition_count, 1))

            shaped_begin_length_array = np.reshape(
                begin_length_array, (self.repetition_count, -1, 2))

            shaped_begin_length_array[:, :,
                                      0] += (np.arange(self.repetition_count) *
                                             body_duration)[:, np.newaxis]

            temp_meas_windows[mw_name] = begin_length_array

        # the cast is here because static type analysis struggles to detect that we replace _all_ values by ndarray in
        # the previous loop
        return cast(Mapping[str, np.ndarray], temp_meas_windows)
Beispiel #23
0
 def setUp(self) -> None:
     # we currently allow overlapping masks in AlazarProgram (It will throw an error on upload)
     # This probably will change in the future
     self.masks = {
         'unsorted': (np.array([1., 100, 13]), np.array([10., 999, 81])),
         'sorted': (np.array([30., 100, 1300]), np.array([10., 990, 811])),
         'overlapping': (np.array([30., 100, 300]), np.array([20., 900, 100]))
     }
     self.sample_factor = TimeType(10**8, 10**9)
     self.expected = {
         'unsorted': (np.array([0, 1, 10]).astype(np.uint64), np.array([1, 8, 99]).astype(np.uint64)),
         'sorted': (np.array([3, 10, 130]).astype(np.uint64), np.array([1, 99, 81]).astype(np.uint64)),
         'overlapping': (np.array([3, 10, 30]).astype(np.uint64), np.array([2, 90, 10]).astype(np.uint64))
     }
Beispiel #24
0
    def test_init_several_channels(self) -> None:
        dwf_a = DummyWaveform(duration=2.2, defined_channels={'A'})
        dwf_b = DummyWaveform(duration=2.2, defined_channels={'B'})
        dwf_c = DummyWaveform(duration=2.3, defined_channels={'C'})

        waveform = MultiChannelWaveform([dwf_a, dwf_b])
        self.assertEqual({'A', 'B'}, waveform.defined_channels)
        self.assertEqual(TimeType.from_float(2.2), waveform.duration)

        with self.assertRaises(ValueError):
            MultiChannelWaveform([dwf_a, dwf_c])
        with self.assertRaises(ValueError):
            MultiChannelWaveform([waveform, dwf_c])
        with self.assertRaises(ValueError):
            MultiChannelWaveform((dwf_a, dwf_a))

        dwf_c_valid = DummyWaveform(duration=2.2, defined_channels={'C'})
        waveform_flat = MultiChannelWaveform((waveform, dwf_c_valid))
        self.assertEqual(len(waveform_flat.compare_key), 3)
Beispiel #25
0
    def __init__(self, expression: ExpressionScalar, duration: float,
                 channel: ChannelID) -> None:
        """Creates a new FunctionWaveform instance.

        Args:
            expression: The function represented by this FunctionWaveform
                as a mathematical expression where 't' denotes the time variable. It must not have other variables
            duration: The duration of the waveform
            measurement_windows: A list of measurement windows
            channel: The channel this waveform is played on
        """
        super().__init__()
        if set(expression.variables) - set('t'):
            raise ValueError(
                'FunctionWaveforms may not depend on anything but "t"')

        self._expression = expression
        self._duration = TimeType.from_float(duration)
        self._channel_id = channel
Beispiel #26
0
    def test_make_compatible_complete_unroll(self):
        wf1 = DummyWaveform(duration=1.5)
        wf2 = DummyWaveform(duration=2.0)

        program = Loop(children=[Loop(waveform=wf1, repetition_count=2),
                                 Loop(waveform=wf2, repetition_count=1)], repetition_count=2)

        _make_compatible(program, min_len=5, quantum=10, sample_rate=TimeType.from_float(1.))

        self.assertIsInstance(program.waveform, RepetitionWaveform)
        self.assertEqual(program.children, [])
        self.assertEqual(program.repetition_count, 1)

        self.assertIsInstance(program.waveform, RepetitionWaveform)

        self.assertIsInstance(program.waveform._body, SequenceWaveform)
        body_wf = program.waveform._body
        self.assertEqual(len(body_wf._sequenced_waveforms), 2)
        self.assertIsInstance(body_wf._sequenced_waveforms[0], RepetitionWaveform)
        self.assertIs(body_wf._sequenced_waveforms[0]._body, wf1)
        self.assertEqual(body_wf._sequenced_waveforms[0]._repetition_count, 2)
        self.assertIs(body_wf._sequenced_waveforms[1], wf2)
Beispiel #27
0
    def test_init(self, mock_parse_program, mock_make_compatible):
        mock_parse_program.return_value = ('seq_el', 'wfs')

        mock_program = mock.MagicMock(spec=Loop)
        copied = mock.MagicMock(spec=Loop)
        channels = ('A', 'B', None, None)
        markers = (('A1', None), (None, None), (None, 'C2'), (None, None))
        sample_rate = TimeType(12)
        amplitudes = (1, 1, 1, 1)
        offsets = (0, 0, 0, 0)
        voltage_transformations = tuple(
            mock.Mock(wraps=lambda x: x) for _ in range(4))

        mock_program.copy_tree_structure.return_value = copied

        tek_program = TektronixProgram(
            program=mock_program,
            channels=channels,
            markers=markers,
            sample_rate=sample_rate,
            amplitudes=amplitudes,
            offsets=offsets,
            voltage_transformations=voltage_transformations)

        self.assertIs(tek_program._program, copied)
        copied.flatten_and_balance.assert_called_once_with(1)
        mock_make_compatible.assert_called_once_with(copied, 250, 1,
                                                     sample_rate / 10**9)
        mock_parse_program.assert_called_once_with(
            program=copied,
            channels=channels,
            markers=markers,
            sample_rate=sample_rate,
            amplitudes=amplitudes,
            offsets=offsets,
            voltage_transformations=voltage_transformations)
Beispiel #28
0
eval_sum = [
    (Sum(a_[i], (i, 0, Len(a) - 1)), {
        'a': np.array([1, 2, 3])
    }, 6),
]

eval_array_expression = [(np.array([a * c, b * c]), {
    'a': 2,
    'b': 3,
    'c': 4
}, np.array([8, 12]))]

eval_exact_rational = [
    (a * Rational('1/3'), {
        'a': 2
    }, TimeType.from_fraction(2, 3)),
    (a * Rational('1/3'), {
        'a': Rational(1, 5)
    }, TimeType.from_fraction(1, 15)),
    # TODO: this fails
    # (np.array([a, Rational(1, 3)]), {'a': 2}, np.array([2, TimeType.from_fraction(1, 3)]))
]


class TestCase(unittest.TestCase):
    def assertRaises(self, expected_exception, *args, **kwargs):
        if expected_exception is None:
            return contextlib.suppress()
        else:
            return super().assertRaises(expected_exception, *args, **kwargs)
Beispiel #29
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)
Beispiel #30
0
 def duration(self) -> TimeType:
     return TimeType.from_float(self._table[-1].t)