Skip to content

Conversation

@peendebak
Copy link
Contributor

We combine the measurement windows from the lhs and rhs if these are templates. For expressions or numbers there are no windows.

@terrorfisch

@coveralls
Copy link

coveralls commented Apr 23, 2021

Pull Request Test Coverage Report for Build 2302

  • 1 of 7 (14.29%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.02%) to 80.026%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qupulse/pulses/arithmetic_pulse_template.py 1 7 14.29%
Totals Coverage Status
Change from base Build 2301: -0.02%
Covered Lines: 7171
Relevant Lines: 8773

💛 - Coveralls

@coveralls
Copy link

Pull Request Test Coverage Report for Build 2302

  • 1 of 7 (14.29%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.07%) to 79.983%

Changes Missing Coverage Covered Lines Changed/Added Lines %
qupulse/pulses/arithmetic_pulse_template.py 1 7 14.29%
Totals Coverage Status
Change from base Build 2301: -0.07%
Covered Lines: 7172
Relevant Lines: 8776

💛 - Coveralls

@shumpohl
Copy link
Member

What is you usecase for get_measurement_windows? I had to dig into my old code to remember that I originally intended the function to be only used locally i.e. only return the measurement windows defined by self, not by its children. The only intended use right now is in _internal_create_program. Therefore only composed AtomicPulseTemplates like ArithmeticAtomicPulseTemplate and AtomicMultiChannelPulseTemplate need to redefine them because their childrens measurement windows would otherwise be neglected during program instantiation.

However, I think that there are some inconsistencies here. I am unsure why there is an implementation for MappingPulseTemplate. But MappingPulseTemplate is somehow a special case.

If you need a function to collect all measurements that are defined by a PulseTemplate AND its children without instantiating it via create_program we should add a seperate function for that.

@eendebakpt
Copy link
Contributor

@terrorfisch I don't really have a use case, I just got an error when I used pulse arithmetic related to the missing get_measurement_windows and solved it this way. An alternative would be to return just an empty set of measurement windows.
But suppose someone added a measurement window to some pulse and somewhere later the pulse gets multiplied by a scalar (e.g. an attenuation in the fridge), then one would want the measurement window to be kept I think.

@eendebakpt
Copy link
Contributor

@terrorfisch The pulse that triggered the error was:

In [5]: pulse
Out[5]: SequencePulseTemplate(subtemplates=[SequencePulseTemplate(subtemplates=[((Expression(0) + AtomicMultiChannelPulseTemplate(subtemplates=[ConstantPulseTemplate(name='constant_pulse',duration=Expression(119.99999999999999)), MappingPulseTemplate(template=AtomicMultiChannelPulseTemplate(subtemplates=[FunctionPulseTemplate(duration_expression=Expression('duration'),expression=Expression('(amplitude*(1-heaviside(padding-t, 0))*heaviside((duration-padding_after)-t, 0))*cos(2*pi*domega*t+phase+0)'),channel='I',measurements=[],parameter_constraints=[]), FunctionPulseTemplate(duration_expression=Expression('duration'),expression=Expression('(amplitude*(1-heaviside(padding-t, 0))*heaviside((duration-padding_after)-t, 0))*cos(2*pi*domega*t+phase+-1.5707963267948966)'),channel='Q',measurements=[],parameter_constraints=[]), TablePulseTemplate(entries={'P': [(0, 1.0, 'hold'), (119.99999999999999, 1.0, 'hold')]},parameter_constraints=[],measurements=[])]),parameter_mapping=_FrozenDictByWrapping({'duration': Expression(119.99999999999999), 'amplitude': Expression(0.9), 'domega': Expression(-0.06), 'padding': Expression(0.0), 'padding_after': Expression(0.0), 'phase': Expression(0.0)}),channel_mapping={'I': 'I', 'P': 'P', 'Q': 'Q'})])) '+' AtomicMultiChannelPulseTemplate(subtemplates=[ConstantPulseTemplate(name='constant_pulse',duration=Expression(119.99999999999999)), MappingPulseTemplate(template=AtomicMultiChannelPulseTemplate(subtemplates=[FunctionPulseTemplate(duration_expression=Expression('duration'),expression=Expression('(amplitude*(1-heaviside(padding-t, 0))*heaviside((duration-padding_after)-t, 0))*cos(2*pi*domega*t+phase+0)'),channel='I',measurements=[],parameter_constraints=[]), FunctionPulseTemplate(duration_expression=Expression('duration'),expression=Expression('(amplitude*(1-heaviside(padding-t, 0))*heaviside((duration-padding_after)-t, 0))*cos(2*pi*domega*t+phase+-1.5707963267948966)'),channel='Q',measurements=[],parameter_constraints=[]), TablePulseTemplate(entries={'P': [(0, 1.0, 'hold'), (119.99999999999999, 1.0, 'hold')]},parameter_constraints=[],measurements=[])]),parameter_mapping=_FrozenDictByWrapping({'duration': Expression(119.99999999999999), 'amplitude': Expression(0.8), 'domega': Expression(0.04), 'padding': Expression(0.0), 'padding_after': Expression(0.0), 'phase': Expression(0.0)}),channel_mapping={'I': 'I', 'P': 'P', 'Q': 'Q'})]))])])

The error was triggered by plotting the pulse.

In [6]: plot_pulse(pulse, fig=2, sample_rate=2.4, plot_channels=['I', 'Q', 'P'])
Traceback (most recent call last):

  File "<ipython-input-6-9757ef3c844f>", line 1, in <module>
    plot_pulse(p, fig=2, sample_rate=2.4, plot_channels=['I', 'Q', 'P'])

  File "c:\projects\sqt\src\sqt\measurements\pulse_generator.py", line 121, in plot_pulse
    _ = plot(pulse, sample_rate=sample_rate, axes=plt.gca(), **kwargs)

  File "c:\projects\qupulse\qupulse\pulses\plotting.py", line 160, in plot
    program = pulse.create_program(parameters=parameters,

  File "c:\projects\qupulse\qupulse\pulses\pulse_template.py", line 159, in create_program
    self._create_program(scope=scope,

  File "c:\projects\qupulse\qupulse\pulses\pulse_template.py", line 230, in _create_program
    self._internal_create_program(scope=scope,

  File "c:\projects\qupulse\qupulse\pulses\sequence_pulse_template.py", line 153, in _internal_create_program
    subtemplate._create_program(scope=scope,

  File "c:\projects\qupulse\qupulse\pulses\pulse_template.py", line 230, in _create_program
    self._internal_create_program(scope=scope,

  File "c:\projects\qupulse\qupulse\pulses\sequence_pulse_template.py", line 153, in _internal_create_program
    subtemplate._create_program(scope=scope,

  File "c:\projects\qupulse\qupulse\pulses\pulse_template.py", line 230, in _create_program
    self._internal_create_program(scope=scope,

  File "c:\projects\qupulse\qupulse\pulses\pulse_template.py", line 325, in _internal_create_program
    measurements = self.get_measurement_windows(parameters=scope,

  File "c:\projects\qupulse\qupulse\pulses\arithmetic_pulse_template.py", line 136, in get_measurement_windows
    measurements.extend(self.lhs.get_measurement_windows(parameters=parameters,

AttributeError: 'ArithmeticPulseTemplate' object has no attribute 'get_measurement_windows'

@shumpohl shumpohl mentioned this pull request Apr 25, 2021
@shumpohl
Copy link
Member

Ah, I think I understand the problem now and I created an issue for the underlying cause #578. Thank you for uncovering this and the fix!

Can you add this to the method to avoid that new external code will depend on it?

if not getattr(inspect.getmodule(inspect.stack()[1][0]), '__name__', '').startswith('qupulse'):
    warnings.warn("This is only a hack until https://github.com/qutech/qupulse/issues/578 is resolved. "
                  "Do not call this method directly", category=DeprecationWarning, stacklevel=2)

@peendebak
Copy link
Contributor Author

@terrorfisch Done!

@shumpohl shumpohl merged commit 661ec9c into qutech:master Apr 27, 2021
@peendebak peendebak deleted the fix/arithmetic_template_windows branch January 28, 2022 11:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants