Beispiel #1
0
    def test_unsafe_sample(self):
        time = np.linspace(10, 20, num=25)
        ch_a = np.exp(time)
        ch_b = np.exp(-time)
        ch_c = np.sinh(time)
        ch_d = np.cosh(time)
        ch_e = np.arctan(time)

        sample_output = {'a': ch_a, 'b': ch_b}
        expected_call_data = sample_output

        transformed = {'c': ch_c, 'd': ch_d, 'e': ch_e}

        trafo = TransformationDummy(transformed=transformed, input_channels={'a', 'b'})
        inner_wf = DummyWaveform(duration=1.5, defined_channels={'a', 'b'}, sample_output=sample_output)
        trafo_wf = TransformingWaveform(inner_waveform=inner_wf, transformation=trafo)

        np.testing.assert_equal(ch_c, trafo_wf.unsafe_sample('c', time))
        np.testing.assert_equal(ch_d, trafo_wf.unsafe_sample('d', time))
        np.testing.assert_equal(ch_e, trafo_wf.unsafe_sample('e', time))

        output = np.empty_like(time)
        ch_d_out = trafo_wf.unsafe_sample('d', time, output_array=output)
        self.assertIs(output, ch_d_out)
        np.testing.assert_equal(ch_d_out, ch_d)

        call_list = TransformationDummy.__call__.call_args_list
        self.assertEqual(len(call_list), 1)

        (pos_args, kw_args), = call_list
        self.assertEqual(kw_args, {})

        c_time, c_data = pos_args
        np.testing.assert_equal((time, expected_call_data), pos_args)
Beispiel #2
0
    def test_get_subset_for_channels(self):
        output_channels = {'c', 'd', 'e'}

        trafo = TransformationDummy(output_channels=output_channels)

        inner_wf = DummyWaveform(duration=1.5, defined_channels={'a', 'b'})
        trafo_wf = TransformingWaveform(inner_waveform=inner_wf, transformation=trafo)

        subset_wf = trafo_wf.get_subset_for_channels({'c', 'd'})
        self.assertIsInstance(subset_wf, SubsetWaveform)
        self.assertIs(subset_wf.inner_waveform, trafo_wf)
        self.assertEqual(subset_wf.defined_channels, {'c', 'd'})
Beispiel #3
0
    def _internal_create_program(
            self, *, scope: Scope, measurement_mapping: Dict[str,
                                                             Optional[str]],
            channel_mapping: Dict[ChannelID, Optional[ChannelID]],
            global_transformation: Optional[Transformation],
            to_single_waveform: Set[Union[str, 'PulseTemplate']],
            parent_loop: Loop) -> None:
        """Parameter constraints are validated in build_waveform because build_waveform is guaranteed to be called
        during sequencing"""
        ### current behavior (same as previously): only adds EXEC Loop and measurements if a waveform exists.
        ### measurements are directly added to parent_loop (to reflect behavior of Sequencer + MultiChannelProgram)
        assert not scope.get_volatile_parameters().keys(
        ) & self.parameter_names, "AtomicPT cannot be volatile"

        waveform = self.build_waveform(parameters=scope,
                                       channel_mapping=channel_mapping)
        if waveform:
            measurements = self.get_measurement_windows(
                parameters=scope, measurement_mapping=measurement_mapping)

            if global_transformation:
                waveform = TransformingWaveform(waveform,
                                                global_transformation)

            parent_loop.add_measurements(measurements=measurements)
            parent_loop.append_child(waveform=waveform)
Beispiel #4
0
    def test_build_waveform(self):
        pt = DummyPulseTemplate(defined_channels={'a'})

        parameters = dict(x=5., y=5.7)
        channel_mapping = dict(a='u', b='v')

        inner_wf = mock.Mock(spec=DummyWaveform)
        trafo = mock.Mock(spec=IdentityTransformation())

        arith = ArithmeticPulseTemplate(pt, '-', 6)

        with mock.patch.object(pt, 'build_waveform', return_value=None) as inner_build:
            with mock.patch.object(arith, '_get_transformation') as _get_transformation:
                self.assertIsNone(arith.build_waveform(parameters=parameters, channel_mapping=channel_mapping))
                inner_build.assert_called_once_with(parameters=parameters, channel_mapping=channel_mapping)
                _get_transformation.assert_not_called()

        expected = TransformingWaveform(inner_wf, trafo)

        with mock.patch.object(pt, 'build_waveform', return_value=inner_wf) as inner_build:
            with mock.patch.object(arith, '_get_transformation', return_value=trafo) as _get_transformation:
                result = arith.build_waveform(parameters=parameters, channel_mapping=channel_mapping)
                inner_build.assert_called_once_with(parameters=parameters, channel_mapping=channel_mapping)
                _get_transformation.assert_called_once_with(parameters=parameters, channel_mapping=channel_mapping)
        self.assertEqual(expected, result)
Beispiel #5
0
    def _internal_create_program(self, *,
                                 parameters: Dict[str, Parameter],
                                 measurement_mapping: Dict[str, Optional[str]],
                                 channel_mapping: Dict[ChannelID, Optional[ChannelID]],
                                 global_transformation: Optional[Transformation],
                                 to_single_waveform: Set[Union[str, 'PulseTemplate']],
                                 parent_loop: Loop) -> None:
        """Parameter constraints are validated in build_waveform because build_waveform is guaranteed to be called
        during sequencing"""
        ### current behavior (same as previously): only adds EXEC Loop and measurements if a waveform exists.
        ### measurements are directly added to parent_loop (to reflect behavior of Sequencer + MultiChannelProgram)
        # todo (2018-08-08): could move measurements into own Loop object?

        # todo (2018-07-05): why are parameter constraints not validated here?
        try:
            parameters = {parameter_name: parameters[parameter_name].get_value()
                          for parameter_name in self.parameter_names}
        except KeyError as e:
            raise ParameterNotProvidedException(str(e)) from e

        waveform = self.build_waveform(parameters=parameters,
                                       channel_mapping=channel_mapping)
        if waveform:
            measurements = self.get_measurement_windows(parameters=parameters,
                                                        measurement_mapping=measurement_mapping)

            if global_transformation:
                waveform = TransformingWaveform(waveform, global_transformation)

            parent_loop.add_measurements(measurements=measurements)
            parent_loop.append_child(waveform=waveform)
Beispiel #6
0
    def test_const_value(self):
        output_channels = {'c', 'd', 'e'}
        trafo = TransformationStub()
        inner_wf = WaveformStub()

        trafo_wf = TransformingWaveform(inner_wf, trafo)

        self.assertFalse(trafo_wf.is_constant())
        self.assertIsNone(trafo_wf.constant_value_dict())

        with mock.patch.object(trafo, 'is_constant_invariant', return_value=False) as is_constant_invariant:
            self.assertIsNone(trafo_wf.constant_value('A'))
            is_constant_invariant.assert_called_once_with()

        with mock.patch.object(trafo, 'is_constant_invariant', return_value=True):
            # all inputs constant
            inner_const_values = {'A': 1.1, 'B': 2.2}

            with mock.patch.object(trafo, 'get_input_channels', return_value=inner_const_values.keys()):
                with mock.patch.object(inner_wf, 'constant_value', side_effect=inner_const_values.values()) as constant_value:
                    with mock.patch.object(TransformationStub, '__call__', return_value={'C': mock.sentinel}) as call:
                        self.assertIs(trafo_wf.constant_value('C'), call.return_value['C'])
                        call.assert_called_once_with(0., inner_const_values)
                    self.assertEqual([mock.call(ch) for ch in inner_const_values], constant_value.call_args_list)

                inner_const_values['B'] = None
                with mock.patch.object(inner_wf, 'constant_value', side_effect=inner_const_values.values()) as constant_value:
                    self.assertIsNone(trafo_wf.constant_value('C'))
Beispiel #7
0
    def build_waveform(self, parameters: Dict[str, numbers.Real],
                       channel_mapping: Dict[ChannelID, Optional[ChannelID]]) -> Optional[Waveform]:
        inner_waveform = self._template.build_waveform(parameters, channel_mapping)

        if inner_waveform:
            overwritten_channels = self._get_overwritten_channels_values(parameters=parameters,
                                                                         channel_mapping=channel_mapping)
            transformation = ParallelConstantChannelTransformation(overwritten_channels)
            return TransformingWaveform(inner_waveform, transformation)
Beispiel #8
0
    def test_simple_properties(self):
        output_channels = {'c', 'd', 'e'}

        trafo = TransformationDummy(output_channels=output_channels)

        inner_wf = DummyWaveform(duration=1.5, defined_channels={'a', 'b'})
        trafo_wf = TransformingWaveform(inner_waveform=inner_wf, transformation=trafo)

        self.assertIs(trafo_wf.inner_waveform, inner_wf)
        self.assertIs(trafo_wf.transformation, trafo)
        self.assertEqual(trafo_wf.compare_key, (inner_wf, trafo))
        self.assertIs(trafo_wf.duration, inner_wf.duration)
        self.assertIs(trafo_wf.defined_channels, output_channels)
        trafo.get_output_channels.assert_called_once_with(inner_wf.defined_channels)
Beispiel #9
0
    def build_waveform(self,
                       parameters: Dict[str, Real],
                       channel_mapping: Dict[ChannelID, ChannelID]) -> Optional[Waveform]:
        pt = cast(AtomicPulseTemplate, self._pulse_template)
        inner_waveform = pt.build_waveform(parameters=parameters, channel_mapping=channel_mapping)

        if inner_waveform is None:
            return None

        # put arithmetic into transformation
        transformation = self._get_transformation(parameters=parameters,
                                                  channel_mapping=channel_mapping)

        return TransformingWaveform(inner_waveform, transformation=transformation)
Beispiel #10
0
    def _create_program(self, *, scope: Scope,
                        measurement_mapping: Dict[str, Optional[str]],
                        channel_mapping: Dict[ChannelID, Optional[ChannelID]],
                        global_transformation: Optional[Transformation],
                        to_single_waveform: Set[Union[str, 'PulseTemplate']],
                        parent_loop: Loop):
        """Generic part of create program. This method handles to_single_waveform and the configuration of the
        transformer."""
        if self.identifier in to_single_waveform or self in to_single_waveform:
            root = Loop()

            if not scope.get_volatile_parameters().keys().isdisjoint(
                    self.parameter_names):
                raise NotImplementedError(
                    'A pulse template that has volatile parameters cannot be transformed into a '
                    'single waveform yet.')

            self._internal_create_program(
                scope=scope,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                global_transformation=None,
                to_single_waveform=to_single_waveform,
                parent_loop=root)

            waveform = to_waveform(root)

            if global_transformation:
                waveform = TransformingWaveform(waveform,
                                                global_transformation)

            # convert the nicely formatted measurement windows back into the old format again :(
            measurements = root.get_measurement_windows()
            measurement_window_list = []
            for measurement_name, (begins, lengths) in measurements.items():
                measurement_window_list.extend(
                    zip(itertools.repeat(measurement_name), begins, lengths))

            parent_loop.add_measurements(measurement_window_list)
            parent_loop.append_child(waveform=waveform)

        else:
            self._internal_create_program(
                scope=scope,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                to_single_waveform=to_single_waveform,
                global_transformation=global_transformation,
                parent_loop=parent_loop)
Beispiel #11
0
    def _create_program(self, *, parameters: Dict[str, Parameter],
                        measurement_mapping: Dict[str, Optional[str]],
                        channel_mapping: Dict[ChannelID, Optional[ChannelID]],
                        global_transformation: Optional[Transformation],
                        to_single_waveform: Set[Union[str, 'PulseTemplate']],
                        parent_loop: Loop):
        """Generic part of create program. This method handles to_single_waveform and the configuration of the
        transformer."""
        if self.identifier in to_single_waveform or self in to_single_waveform:
            root = Loop()

            self._internal_create_program(
                parameters=parameters,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                global_transformation=None,
                to_single_waveform=to_single_waveform,
                parent_loop=root)

            waveform = to_waveform(root)

            if global_transformation:
                waveform = TransformingWaveform(waveform,
                                                global_transformation)

            # convert the nicely formatted measurement windows back into the old format again :(
            measurements = root.get_measurement_windows()
            measurement_window_list = []
            for measurement_name, (begins, lengths) in measurements.items():
                measurement_window_list.extend(
                    zip(itertools.repeat(measurement_name), begins, lengths))

            parent_loop.add_measurements(measurement_window_list)
            parent_loop.append_child(waveform=waveform)

        else:
            self._internal_create_program(
                parameters=parameters,
                measurement_mapping=measurement_mapping,
                channel_mapping=channel_mapping,
                to_single_waveform=to_single_waveform,
                global_transformation=global_transformation,
                parent_loop=parent_loop)
Beispiel #12
0
    def test_from_transformation(self):
        const_output = {'c': 4.4, 'd': 5.5, 'e': 6.6}
        trafo = TransformationDummy(output_channels=const_output.keys(), constant_invariant=False)
        const_trafo = TransformationDummy(output_channels=const_output.keys(), constant_invariant=True,
                                          transformed=const_output)
        dummy_wf = DummyWaveform(duration=1.5, defined_channels={'a', 'b'})
        const_wf = ConstantWaveform.from_mapping(3, {'a': 2.2, 'b': 3.3})

        self.assertEqual(TransformingWaveform(inner_waveform=dummy_wf, transformation=trafo),
                         TransformingWaveform.from_transformation(inner_waveform=dummy_wf, transformation=trafo))

        self.assertEqual(TransformingWaveform(inner_waveform=dummy_wf, transformation=const_trafo),
                         TransformingWaveform.from_transformation(inner_waveform=dummy_wf, transformation=const_trafo))

        self.assertEqual(TransformingWaveform(inner_waveform=const_wf, transformation=trafo),
                         TransformingWaveform.from_transformation(inner_waveform=const_wf, transformation=trafo))

        with mock.patch.object(ConstantWaveform, 'from_mapping', return_value=mock.sentinel) as from_mapping:
            self.assertIs(from_mapping.return_value,
                          TransformingWaveform.from_transformation(inner_waveform=const_wf, transformation=const_trafo))
            from_mapping.assert_called_once_with(const_wf.duration, const_output)
Beispiel #13
0
    def test_internal_create_program_transformation(self):
        inner_wf = DummyWaveform()
        template = AtomicPulseTemplateStub(parameter_names=set())
        program = Loop()
        global_transformation = TransformationStub()
        scope = DictScope.from_kwargs()
        expected_program = Loop(children=[
            Loop(
                waveform=TransformingWaveform(inner_wf, global_transformation))
        ])

        with mock.patch.object(template,
                               'build_waveform',
                               return_value=inner_wf):
            template._internal_create_program(
                scope=scope,
                measurement_mapping={},
                channel_mapping={},
                parent_loop=program,
                to_single_waveform=set(),
                global_transformation=global_transformation)

        self.assertEqual(expected_program, program)
Beispiel #14
0
    def test__create_program_single_waveform(self):
        template = PulseTemplateStub(identifier='pt_identifier',
                                     parameter_names={'alpha'})

        for to_single_waveform in ({template}, {template.identifier}):
            for global_transformation in (None, TransformationStub()):
                scope = DictScope.from_kwargs(a=1., b=2., volatile={'a'})
                measurement_mapping = {'M': 'N'}
                channel_mapping = {'B': 'A'}
                parent_loop = Loop()

                wf = DummyWaveform()
                single_waveform = DummyWaveform()
                measurements = [('m', 0, 1), ('n', 0.1, .9)]

                expected_inner_program = Loop(children=[Loop(waveform=wf)],
                                              measurements=measurements)

                appending_create_program = get_appending_internal_create_program(
                    wf, measurements=measurements, always_append=True)

                if global_transformation:
                    final_waveform = TransformingWaveform(
                        single_waveform, global_transformation)
                else:
                    final_waveform = single_waveform

                expected_program = Loop(
                    children=[Loop(waveform=final_waveform)],
                    measurements=measurements)

                with mock.patch.object(template,
                                       '_internal_create_program',
                                       wraps=appending_create_program
                                       ) as _internal_create_program:
                    with mock.patch(
                            'qupulse.pulses.pulse_template.to_waveform',
                            return_value=single_waveform) as to_waveform:
                        template._create_program(
                            scope=scope,
                            measurement_mapping=measurement_mapping,
                            channel_mapping=channel_mapping,
                            global_transformation=global_transformation,
                            to_single_waveform=to_single_waveform,
                            parent_loop=parent_loop)

                        _internal_create_program.assert_called_once_with(
                            scope=scope,
                            measurement_mapping=measurement_mapping,
                            channel_mapping=channel_mapping,
                            global_transformation=None,
                            to_single_waveform=to_single_waveform,
                            parent_loop=expected_inner_program)

                        to_waveform.assert_called_once_with(
                            expected_inner_program)

                        expected_program._measurements = set(
                            expected_program._measurements)
                        parent_loop._measurements = set(
                            parent_loop._measurements)

                        self.assertEqual(expected_program, parent_loop)