diff --git a/changes.d/593.removal b/changes.d/593.removal new file mode 100644 index 00000000..e9741b2a --- /dev/null +++ b/changes.d/593.removal @@ -0,0 +1 @@ +Deprecate boolean `duration` argument of `AtomicMultiChannelPulseTemplate` and remove duration check in `__init__`. diff --git a/qupulse/pulses/multi_channel_pulse_template.py b/qupulse/pulses/multi_channel_pulse_template.py index 1214712e..b6c220b0 100644 --- a/qupulse/pulses/multi_channel_pulse_template.py +++ b/qupulse/pulses/multi_channel_pulse_template.py @@ -23,7 +23,7 @@ from qupulse.pulses.mapping_pulse_template import MappingPulseTemplate, MappingTuple from qupulse.pulses.parameters import Parameter, ParameterConstrainer from qupulse.pulses.measurement import MeasurementDeclaration, MeasurementWindow -from qupulse.expressions import Expression, ExpressionScalar +from qupulse.expressions import Expression, ExpressionScalar, ExpressionLike __all__ = ["AtomicMultiChannelPulseTemplate", "ParallelConstantChannelPulseTemplate"] @@ -32,15 +32,14 @@ class AtomicMultiChannelPulseTemplate(AtomicPulseTemplate, ParameterConstrainer) """Combines multiple PulseTemplates that are defined on different channels into an AtomicPulseTemplate.""" def __init__(self, *subtemplates: Union[AtomicPulseTemplate, MappingTuple, MappingPulseTemplate], - identifier: Optional[str]=None, - parameter_constraints: Optional[List]=None, - measurements: Optional[List[MeasurementDeclaration]]=None, - registry: PulseRegistryType=None, - duration: Union[str, Expression, bool]=False) -> None: - """Parallels multiple AtomicPulseTemplates of the same duration. The duration equality check is performed on - construction by default. If the duration keyword argument is given the check is performed on instantiation - (when build_waveform is called). duration can be a Expression to enforce a certain duration or True for an - unspecified duration. + identifier: Optional[str] = None, + parameter_constraints: Optional[List] = None, + measurements: Optional[List[MeasurementDeclaration]] = None, + registry: PulseRegistryType = None, + duration: Optional[ExpressionLike] = None) -> None: + """Parallels multiple AtomicPulseTemplates of the same duration. If the duration keyword argument is given + it is enforced that the instantiated pulse template has this duration. If duration is None the duration of the + PT is the duration of the first subtemplate. There are probably changes to this behaviour in the future. Args: *subtemplates: Positional arguments are subtemplates to combine. @@ -56,6 +55,11 @@ def __init__(self, self._subtemplates = [st if isinstance(st, PulseTemplate) else MappingPulseTemplate.from_tuple(st) for st in subtemplates] + if duration in (True, False): + warnings.warn("Boolean duration is deprecated since qupulse 0.6 and interpreted as None", + category=DeprecationWarning, stacklevel=2) + duration = None + for subtemplate in self._subtemplates: if isinstance(subtemplate, AtomicPulseTemplate): continue @@ -80,16 +84,7 @@ def __init__(self, 'subtemplate {}'.format(i + 2 + j), (channels_i & channels_j).pop()) - if not duration: - duration = self._subtemplates[0].duration - for subtemplate in self._subtemplates[1:]: - if almost_equal(duration.sympified_expression, subtemplate.duration.sympified_expression): - continue - else: - raise ValueError('Could not assert duration equality of {} and {}'.format(duration, - subtemplate.duration)) - self._duration = None - elif duration is True: + if duration is None: self._duration = None else: self._duration = ExpressionScalar(duration) @@ -98,10 +93,10 @@ def __init__(self, @property def duration(self) -> ExpressionScalar: - if self._duration: - return self._duration - else: + if self._duration is None: return self._subtemplates[0].duration + else: + return self._duration @property def parameter_names(self) -> Set[str]: diff --git a/tests/pulses/multi_channel_pulse_template_tests.py b/tests/pulses/multi_channel_pulse_template_tests.py index bfe46363..89e2b782 100644 --- a/tests/pulses/multi_channel_pulse_template_tests.py +++ b/tests/pulses/multi_channel_pulse_template_tests.py @@ -85,10 +85,11 @@ def test_instantiation_duration_check(self): duration='t_3', waveform=DummyWaveform(duration=4, defined_channels={'c3'}))] - with self.assertRaisesRegex(ValueError, 'duration equality'): - AtomicMultiChannelPulseTemplate(*subtemplates) + # with self.assertRaisesRegex(ValueError, 'duration equality'): + # AtomicMultiChannelPulseTemplate(*subtemplates) - amcpt = AtomicMultiChannelPulseTemplate(*subtemplates, duration=True) + with self.assertWarns(DeprecationWarning): + amcpt = AtomicMultiChannelPulseTemplate(*subtemplates, duration=True) self.assertIs(amcpt.duration, subtemplates[0].duration) with self.assertRaisesRegex(ValueError, 'duration'): @@ -115,13 +116,7 @@ def test_duration(self): sts = [DummyPulseTemplate(duration='t1', defined_channels={'A'}), DummyPulseTemplate(duration='t1', defined_channels={'B'}), DummyPulseTemplate(duration='t2', defined_channels={'C'})] - with self.assertRaises(ValueError): - AtomicMultiChannelPulseTemplate(*sts) - - with self.assertRaises(ValueError): - AtomicMultiChannelPulseTemplate(sts[0], sts[2]) template = AtomicMultiChannelPulseTemplate(*sts[:1]) - self.assertEqual(template.duration, 't1') def test_mapping_template_pure_conversion(self):