iqm-pulse 9.5__py3-none-any.whl → 9.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -573,3 +573,215 @@ class ProbePulse_CustomWaveforms(CustomIQWaveforms):
573
573
  @classmethod
574
574
  def get_locus_mapping_name(cls, operation_name: str, implementation_name: str) -> str:
575
575
  return PROBE_LINES_LOCUS_MAPPING
576
+
577
+
578
+ class ProbePulse_CustomWaveforms_noIntegration(CustomIQWaveforms):
579
+ """Base class for implementing a probe line probe pulse with custom waveforms in the I and Q channels without
580
+ any integration.
581
+
582
+ Similar to the :class:`ProbePulse_CustomWaveforms` except that signal integration is removed.
583
+ """
584
+
585
+ root_parameters = {
586
+ "frequency": Parameter("", "Readout pulse frequency", "Hz"),
587
+ "duration": Parameter("", "Readout pulse duration", "s"),
588
+ "phase": Parameter("", "Readout pulse phase", "rad"),
589
+ "amplitude_i": Parameter("", "Readout channel I amplitude", ""),
590
+ "amplitude_q": Parameter("", "Readout channel Q amplitude", ""),
591
+ }
592
+
593
+ def __init__(
594
+ self, parent: QuantumOp, name: str, locus: Locus, calibration_data: OILCalibrationData, builder: ScheduleBuilder
595
+ ):
596
+ super().__init__(parent, name, locus, calibration_data, builder)
597
+
598
+ self._multiplexed_timeboxes: dict[tuple[str, str, bool], MultiplexedProbeTimeBox] = {}
599
+ """Cache for :meth:`probe_timebox`."""
600
+
601
+ if len(locus) == 1: # factorizable gates only need calibration on 1-loci
602
+ self._probe_line: ProbeChannelProperties = self.builder.channels[
603
+ self.builder.get_probe_channel(self.locus[0])
604
+ ]
605
+ c_freq = self._probe_line.center_frequency
606
+ if_freq = (calibration_data["frequency"] - c_freq) / self._probe_line.sample_rate
607
+ self._duration = (
608
+ self._probe_line.duration_to_int_samples(
609
+ self._probe_line.round_duration_to_granularity(calibration_data["duration"])
610
+ )
611
+ + self._probe_line.instruction_duration_granularity
612
+ )
613
+
614
+ waveform_params = self.convert_calibration_data(
615
+ calibration_data,
616
+ {k: v for k, v in self.parameters.items() if k not in self.root_parameters or k == "duration"},
617
+ self._probe_line,
618
+ )
619
+ root_params = {k: v for k, v in calibration_data.items() if k in self.root_parameters and k != "duration"}
620
+
621
+ probe_instruction = self._build_instructions(waveform_params, root_params, if_freq)
622
+ self._probe_instruction = probe_instruction
623
+ self._prio_calibration: OILCalibrationData | None = None
624
+ else:
625
+ # we need to store the possible cal_data == priority calibration in order to propagate it to the factored
626
+ # single-component measure calls in :meth:`probe_timebox`
627
+ self._prio_calibration = calibration_data or None
628
+
629
+ def _build_instructions(
630
+ self, waveform_params: OILCalibrationData, root_params: OILCalibrationData, if_freq: float
631
+ ) -> IQPulse:
632
+ """Builds a probe pulse and an acquisition method using the calibration data.
633
+
634
+ Subclasses may override this method if needed.
635
+ """
636
+ if self.dependent_waves:
637
+ wave_i = self.wave_i(**waveform_params)
638
+ wave_q = self.wave_q(**waveform_params)
639
+ else:
640
+ wave_i = self.wave_i(**waveform_params["i"])
641
+ wave_q = self.wave_q(**waveform_params["q"])
642
+
643
+ probe_pulse = IQPulse(
644
+ duration=waveform_params["n_samples"],
645
+ wave_i=wave_i,
646
+ wave_q=wave_q,
647
+ scale_i=root_params["amplitude_i"],
648
+ scale_q=root_params["amplitude_q"],
649
+ phase=root_params["phase"],
650
+ modulation_frequency=if_freq,
651
+ )
652
+
653
+ return probe_pulse
654
+
655
+ def probe_timebox(
656
+ self, key: str = "", feedback_key: str = "", do_acquisition: bool = False
657
+ ) -> MultiplexedProbeTimeBox:
658
+ """Returns a "naked" probe timebox that supports convenient multiplexing through
659
+ ``MultiplexedProbeTimeBox.__add__``.
660
+
661
+ This method can be used if the user wants to control the multiplexing explicitly. With two
662
+ ``MultiplexedProbeTimeBox``es ``A`` and ``B`` the result ``A + B`` has all the ``ReadoutTrigger`` instructions
663
+ on each probe channel of ``A`` and ``B`` multiplexed together and played simultaneously.
664
+
665
+ Args:
666
+ key: The readout results generated on this trigger will be assigned to
667
+ ``f"{qubit}__{key}"``, where ``qubit`` goes over the component names in ``self.locus``. If empty,
668
+ the key `"readout.result"` will be used to maintain backwards compatibility.
669
+ feedback_key: The signals generated by this measure operation are routed using this key for
670
+ fast feedback purposes. See :meth:`__call__`.
671
+ do_acquisition: if False, no acquisitions are added.
672
+
673
+ Returns:
674
+ MultiplexedProbeTimeBox containing the ReadoutTrigger instruction.
675
+
676
+ """
677
+ args = (key, feedback_key, do_acquisition)
678
+ # additional caching for probe timeboxes due to the fact that both ._call and .time_trace use this
679
+ if args not in self._multiplexed_timeboxes:
680
+ if len(self.locus) == 1:
681
+ multiplexed_iq = MultiplexedIQPulse(
682
+ duration=self._probe_instruction.duration,
683
+ entries=((self._probe_instruction, 0),),
684
+ )
685
+ readout_trigger = ReadoutTrigger(
686
+ probe_pulse=multiplexed_iq,
687
+ acquisitions=(),
688
+ duration=self._duration,
689
+ )
690
+ probe_channel = self.builder.get_probe_channel(self.locus[0])
691
+ try:
692
+ drive_channel = self.builder.get_drive_channel(self.locus[0])
693
+ except KeyError:
694
+ drive_channel = ""
695
+
696
+ if drive_channel:
697
+ # drive channel must be blocked, to prevent DD insertion while measurement is taking place
698
+ # unfortunately we must allow for different channel sample rates because of UHFQA
699
+ channels = self.builder.channels
700
+ drive_channel_props = channels[drive_channel]
701
+ rt_duration_in_seconds = channels[probe_channel].duration_to_seconds(readout_trigger.duration)
702
+ block_duration = drive_channel_props.duration_to_int_samples(
703
+ drive_channel_props.round_duration_to_granularity(
704
+ rt_duration_in_seconds, round_up=True, force_min_duration=True
705
+ )
706
+ )
707
+ probe_timebox = MultiplexedProbeTimeBox.from_readout_trigger(
708
+ readout_trigger=readout_trigger,
709
+ probe_channel=probe_channel,
710
+ locus_components=self.locus,
711
+ label=f"{self.__class__.__name__} on {self.locus}",
712
+ block_channels=[drive_channel],
713
+ block_duration=block_duration,
714
+ )
715
+ else:
716
+ probe_timebox = MultiplexedProbeTimeBox.from_readout_trigger(
717
+ readout_trigger=readout_trigger,
718
+ probe_channel=probe_channel,
719
+ locus_components=self.locus,
720
+ label=f"{self.__class__.__name__} on {self.locus}",
721
+ )
722
+ else:
723
+ probe_timeboxes = [
724
+ self.builder.get_implementation(
725
+ self.parent.name, (c,), impl_name=self.name, priority_calibration=self._prio_calibration
726
+ ).probe_timebox(key, feedback_key, do_acquisition)
727
+ for c in self.locus
728
+ ]
729
+ probe_timebox = functools.reduce(lambda x, y: x + y, probe_timeboxes)
730
+ probe_timebox.neighborhood_components[0] = set(
731
+ self.locus + (self.builder.chip_topology.component_to_probe_line[self.locus[0]],)
732
+ )
733
+
734
+ self._multiplexed_timeboxes[args] = probe_timebox
735
+ return self._multiplexed_timeboxes[args]
736
+
737
+ def _call(self, key: str = "", feedback_key: str = "") -> TimeBox:
738
+ """Returns a TimeBox containing the multiplexed simultaneous measurement.
739
+
740
+ If ``len(self.locus) == 1``, the TimeBox contains the measurement for just that component, otherwise
741
+ the measurements of components that belong to the same probeline are multiplexed together.
742
+
743
+ The returned :class:`.TimeBox` instances behave like any other TimeBox in scheduling and circuit
744
+ generation. With measurement TimeBoxes ``A`` and ``B`` the result ``A + B`` first plays the ``ReadoutTrigger``
745
+ instructions of ``A`` and only then those of ``B`` in each probe channel. If the multiplexing features of
746
+ :class:`.MultiplexedProbeTimeBox` are needed, the method :meth:`probe_timebox` can be used.
747
+
748
+ In scheduling, the returned TimeBox blocks the locus components and the probe
749
+ lines they are associated with.
750
+
751
+ Args:
752
+ key: Readout results generated on this trigger will be assigned to the acquisition labels
753
+ ``f"{qubit}__{key}"``, where ``qubit`` goes over the component names in ``self.locus``.
754
+ If empty, the key ``"readout.result"`` will be used to maintain backwards compatibility.
755
+ feedback_key: If the readout mode is "threshold", the results generated by this ``measure`` operation
756
+ are routed using the label ``f"{qubit}__{feedback_key}"`` for fast feedback purposes.
757
+ The signals are picked up by :class:`.ConditionalInstruction`s that have the same label.
758
+ The default value ``""`` means the signal is not routed anywhere. TODO: currently the HW does not
759
+ support multiple feedback keys per drive channel, so the actual key used will be ``FEEDBACK_KEY``
760
+ whenever any non-empty key is inputted. When the HW is improved, the actual key the user inputs
761
+ should be passed.
762
+
763
+ Returns:
764
+ TimeBox containing the :class:`.ReadoutTrigger` instruction.
765
+
766
+ """
767
+ final_box = TimeBox.composite(
768
+ [self.probe_timebox(key=key, feedback_key=feedback_key)], label=f"Readout on {self.locus}"
769
+ )
770
+ final_box.neighborhood_components[0] = final_box.children[0].neighborhood_components[0]
771
+ return final_box
772
+
773
+ def duration_in_seconds(self) -> float:
774
+ probe_timebox = self.probe_timebox()
775
+ readout_schedule = probe_timebox.atom
776
+ return readout_schedule.duration_in_seconds(self.builder.channels)
777
+
778
+ @classmethod
779
+ def get_locus_mapping_name(cls, operation_name: str, implementation_name: str) -> str:
780
+ return SINGLE_COMPONENTS_WITH_READOUT_LOCUS_MAPPING
781
+
782
+
783
+ class Probe_Constant(ProbePulse_CustomWaveforms_noIntegration, wave_i=Constant, wave_q=Constant): # type: ignore[call-arg]
784
+ """Implementation of a single-qubit projective, dispersive measurement in the Z basis.
785
+
786
+ Uses a constant probe pulse.
787
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-pulse
3
- Version: 9.5
3
+ Version: 9.6
4
4
  Summary: A Python-based project for providing interface and implementations for control pulses.
5
5
  Author-email: IQM Finland Oy <info@meetiqm.com>
6
6
  License: Apache License
@@ -16,7 +16,7 @@ iqm/pulse/gates/default_gates.py,sha256=kLNYjt-ZXYPvfBS1p8pi7e3gZz2UnMSWS4S2Xmj6
16
16
  iqm/pulse/gates/delay.py,sha256=nST9dY2JFp_mpKhiSfsYa5yL4hFKcNJSAyCzXjhauQg,3767
17
17
  iqm/pulse/gates/enums.py,sha256=ATwb6vZYpfgQ1gQyFPW53JyIKrdAP3FPHm6jV-t9OAk,2532
18
18
  iqm/pulse/gates/flux_multiplexer.py,sha256=lnlynR_SWM6Wp7RjVcyParCSNKacKargEC5lLF5jwKU,9692
19
- iqm/pulse/gates/measure.py,sha256=VlcPufdl3tG2MNcRkUzKjBz5BFqVVqBOCn6-mPTRhoc,29518
19
+ iqm/pulse/gates/measure.py,sha256=izqaO4Pxxb7THJhs6tx3QT_YCFDpdt8Mi30E-gwvM7g,40429
20
20
  iqm/pulse/gates/move.py,sha256=yKY-Et4YJV0KmcDwN0yE3oHgDtLL-Xfgy1G_InsJN0U,17182
21
21
  iqm/pulse/gates/prx.py,sha256=SaJHcVu-NURUBTF5LtmTwwK1qcCtXA89NA5VwJXBM1o,24504
22
22
  iqm/pulse/gates/reset.py,sha256=ZgliZd2yVJZuVyeVt6qnnVTt3CGb-cLCIWmoq4nS4lk,7574
@@ -38,8 +38,8 @@ iqm/pulse/playlist/visualisation/templates/static/logo.png,sha256=rbfQZ6_UEaztpY
38
38
  iqm/pulse/playlist/visualisation/templates/static/moment.min.js,sha256=4iQZ6BVL4qNKlQ27TExEhBN1HFPvAvAMbFavKKosSWQ,53324
39
39
  iqm/pulse/playlist/visualisation/templates/static/vis-timeline-graph2d.min.css,sha256=svzNasPg1yR5gvEaRei2jg-n4Pc3sVyMUWeS6xRAh6U,19837
40
40
  iqm/pulse/playlist/visualisation/templates/static/vis-timeline-graph2d.min.js,sha256=OqCqCyA6JnxPz3PGXq_P_9VuSqWptgNt5Ev3T-xjefQ,570288
41
- iqm_pulse-9.5.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
42
- iqm_pulse-9.5.dist-info/METADATA,sha256=NX869B0rRRNQsZlG_eF1nBj-GejOTkUSAXNdTclcj34,14520
43
- iqm_pulse-9.5.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
44
- iqm_pulse-9.5.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
45
- iqm_pulse-9.5.dist-info/RECORD,,
41
+ iqm_pulse-9.6.dist-info/LICENSE.txt,sha256=R6Q7eUrLyoCQgWYorQ8WJmVmWKYU3dxA3jYUp0wwQAw,11332
42
+ iqm_pulse-9.6.dist-info/METADATA,sha256=PvoI-osxl1RWW5_IrkkNTiyl-1SEQYjCPFzWFHPNAaQ,14520
43
+ iqm_pulse-9.6.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
44
+ iqm_pulse-9.6.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
45
+ iqm_pulse-9.6.dist-info/RECORD,,