Skip to content

Commit

Permalink
Merge d761b05 into 38f986c
Browse files Browse the repository at this point in the history
  • Loading branch information
terrorfisch committed Apr 8, 2019
2 parents 38f986c + d761b05 commit 1b4f019
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 11 deletions.
2 changes: 2 additions & 0 deletions ReleaseNotes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
- Pulse Templates:
- `MappingPulseTemplate`:
- Raise a ValueError if more than one inner channel is mapped to the same outer channel
- `allow_partial_parameter_mapping` is now True as a default. The default can be changed with the class variable `MappingPulseTemplate.ALLOW_PARTIAL_PARAMETER_MAPPING`.

- Plotting:
- Make `plotting.render` behaviour and return value consistent between calls with `InstructionBlock` and `Loop`. Render now always returns 3 arguments.

Expand Down
28 changes: 19 additions & 9 deletions qupulse/pulses/mapping_pulse_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@ class MappingPulseTemplate(PulseTemplate, ParameterConstrainer):
"""This class can be used to remap parameters, the names of measurement windows and the names of channels. Besides
the standard constructor, there is a static member function from_tuple for convenience. The class also allows
constraining parameters by deriving from ParameterConstrainer"""

ALLOW_PARTIAL_PARAMETER_MAPPING = True
"""Default value for allow_partial_parameter_mapping of the __init__ method."""

def __init__(self, template: PulseTemplate, *,
identifier: Optional[str]=None,
parameter_mapping: Optional[Dict[str, str]]=None,
measurement_mapping: Optional[Dict[str, str]] = None,
channel_mapping: Optional[Dict[ChannelID, ChannelID]] = None,
parameter_constraints: Optional[List[str]]=None,
allow_partial_parameter_mapping: bool=False,
allow_partial_parameter_mapping: bool = None,
registry: PulseRegistryType=None) -> None:
"""Standard constructor for the MappingPulseTemplate.
Expand All @@ -49,11 +53,14 @@ def __init__(self, template: PulseTemplate, *,
:param measurement_mapping: mappings for other measurement names are inserted
:param channel_mapping: mappings for other channels are auto inserted
:param parameter_constraints:
:param allow_partial_parameter_mapping:
:param allow_partial_parameter_mapping: If None the value of the class variable ALLOW_PARTIAL_PARAMETER_MAPPING
"""
PulseTemplate.__init__(self, identifier=identifier)
ParameterConstrainer.__init__(self, parameter_constraints=parameter_constraints)

if allow_partial_parameter_mapping is None:
allow_partial_parameter_mapping = self.ALLOW_PARTIAL_PARAMETER_MAPPING

if parameter_mapping is None:
parameter_mapping = dict((par, par) for par in template.parameter_names)
else:
Expand Down Expand Up @@ -110,15 +117,18 @@ def __init__(self, template: PulseTemplate, *,
self.__channel_mapping = channel_mapping
self._register(registry=registry)

@staticmethod
def from_tuple(mapping_tuple: MappingTuple) -> 'MappingPulseTemplate':
@classmethod
def from_tuple(cls, mapping_tuple: MappingTuple) -> 'MappingPulseTemplate':
"""Construct a MappingPulseTemplate from a tuple of mappings. The mappings are automatically assigned to the
mapped elements based on their content.
:param mapping_tuple: A tuple of mappings
:return: Constructed MappingPulseTemplate
"""
template, *mappings = mapping_tuple

if not mappings:
return template

parameter_mapping = None
measurement_mapping = None
channel_mapping = None
Expand All @@ -133,7 +143,7 @@ def from_tuple(mapping_tuple: MappingTuple) -> 'MappingPulseTemplate':
mapped <= template.defined_channels)) > 1:
raise AmbiguousMappingException(template, mapping)

if mapped == template.parameter_names:
if mapped <= template.parameter_names:
if parameter_mapping:
raise MappingCollisionException(template, object_type='parameter',
mapped=template.parameter_names,
Expand All @@ -153,10 +163,10 @@ def from_tuple(mapping_tuple: MappingTuple) -> 'MappingPulseTemplate':
channel_mapping = mapping
else:
raise ValueError('Could not match mapping to mapped objects: {}'.format(mapping))
return MappingPulseTemplate(template,
parameter_mapping=parameter_mapping,
measurement_mapping=measurement_mapping,
channel_mapping=channel_mapping)
return cls(template,
parameter_mapping=parameter_mapping,
measurement_mapping=measurement_mapping,
channel_mapping=channel_mapping)

@property
def template(self) -> PulseTemplate:
Expand Down
49 changes: 47 additions & 2 deletions tests/pulses/mapping_pulse_template_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ def test_init_exceptions(self):
parameter_mapping = {'foo': 't*k', 'bar': 't*l'}

with self.assertRaises(MissingMappingException):
MappingPulseTemplate(template, parameter_mapping={})
MappingPulseTemplate(template, parameter_mapping={}, allow_partial_parameter_mapping=False)
with self.assertRaises(MissingMappingException):
MappingPulseTemplate(template, parameter_mapping={'bar': 'kneipe'})
MappingPulseTemplate(template, parameter_mapping={'bar': 'kneipe'}, allow_partial_parameter_mapping=False)
with self.assertRaises(UnnecessaryMappingException):
MappingPulseTemplate(template, parameter_mapping=dict(**parameter_mapping, foobar='asd'))

Expand All @@ -39,6 +39,7 @@ def test_init_exceptions(self):
with self.assertRaises(TypeError):
MappingPulseTemplate(template, parameter_mapping)

MappingPulseTemplate(template, parameter_mapping={'bar': 'kneipe'})
MappingPulseTemplate(template, parameter_mapping=parameter_mapping)

def test_from_tuple_exceptions(self):
Expand Down Expand Up @@ -98,6 +99,50 @@ def test_mapping_permutations(template: DummyPulseTemplate,
test_mapping_permutations(template, None, {'m1': 'n1', 'm2': 'n2'}, {'c1': 'd1'})
test_mapping_permutations(template, None, {'m1': 'n1', 'm2': 'n2'}, None)

def test_from_tuple_partial_mappings(self):
template = DummyPulseTemplate(parameter_names={'foo', 'bar'},
measurement_names={'m1', 'm2'},
defined_channels={'c1', 'c2'})

unbound_from_tuple = MappingPulseTemplate.from_tuple.__func__

self.assertIs(unbound_from_tuple(None, (template,)), template)

mock_cls = mock.MagicMock()
unbound_from_tuple(mock_cls, (template, {'foo': 2}))
mock_cls.assert_called_once_with(template,
parameter_mapping={'foo': 2},
measurement_mapping=None,
channel_mapping=None)

mock_cls = mock.MagicMock()
unbound_from_tuple(mock_cls, (template, {'m1': 'n1'}))
mock_cls.assert_called_once_with(template,
parameter_mapping=None,
measurement_mapping={'m1': 'n1'},
channel_mapping=None)

mock_cls = mock.MagicMock(return_value='dummy')
self.assertEqual(unbound_from_tuple(mock_cls, (template, {'c1': 'd1'})), 'dummy')
mock_cls.assert_called_once_with(template,
parameter_mapping=None,
measurement_mapping=None,
channel_mapping={'c1': 'd1'})

mock_cls = mock.MagicMock(return_value='dummy')
self.assertEqual(unbound_from_tuple(mock_cls, (template,
{'c1': 'd1'},
{'foo': 2},
{'m1': 'n1'})),
'dummy')
mock_cls.assert_called_once_with(template,
parameter_mapping={'foo': 2},
measurement_mapping={'m1': 'n1'},
channel_mapping={'c1': 'd1'})




def test_external_params(self):
template = DummyPulseTemplate(parameter_names={'foo', 'bar'})
st = MappingPulseTemplate(template, parameter_mapping={'foo': 't*k', 'bar': 't*l'})
Expand Down

0 comments on commit 1b4f019

Please sign in to comment.