Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions quam_builder/architecture/superconducting/__init__.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
from .components import cross_resonance, flux_line, mixer, readout_resonator, tunable_coupler, xy_drive, zz_drive
from .components import (
cross_resonance,
flux_line,
mixer,
readout_resonator,
tunable_coupler,
xy_drive,
zz_drive,
)
from .custom_gates import CZGate
from .qpu import BaseQuam, FixedFrequencyQuam, FluxTunableQuam
from .qpu import BaseQuam, FixedFrequencyQuam, FluxTunableQuam, CavityQuam
from .qubit import BaseTransmon, FixedFrequencyTransmon, FluxTunableTransmon
from .qubit_pair import FixedFrequencyTransmonPair, FluxTunableTransmonPair
from .cavity import Cavity, CavityMode

__all__ = [
*qpu.__all__,
*qubit.__all__,
*qubit_pair.__all__,
*custom_gates.__all__,
*cavity.__all__,
]
14 changes: 14 additions & 0 deletions quam_builder/architecture/superconducting/cavity/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from typing import Union
from quam_builder.architecture.superconducting.cavity.cavity import (
Cavity,
)
from quam_builder.architecture.superconducting.cavity.cavity_mode import (
CavityMode,
)

__all__ = [
*cavity.__all__,
*cavity_mode.__all__,
]

AnyTransmonPair = Union[Cavity, CavityMode]
433 changes: 433 additions & 0 deletions quam_builder/architecture/superconducting/cavity/cavity.py

Large diffs are not rendered by default.

428 changes: 428 additions & 0 deletions quam_builder/architecture/superconducting/cavity/cavity_mode.py

Large diffs are not rendered by default.

39 changes: 17 additions & 22 deletions quam_builder/architecture/superconducting/components/twpa.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ class TWPA(QuamComponent):
Args:
id (str, int): The id of the TWPA, used to generate the name.
Can be a string, or an integer in which case it will add`Channel._default_label`.
pump (IQChannel): The pump component(sticky element) used for continuous output.
pump (IQChannel): The pump component(sticky element) used for continuous output.
pump_ (IQChannel): The pump component(non sticky element)used for TWPA calibration
spectroscopy (IQChannel): Probe tone used for calibrating the saturation power of the TWPA

max_avg_gain (float): The maximum average gain around the readout resonators related to the TWPA
max_avg_snr_improvement (float): The maximum average SNR improvement around the readout resonators related to the TWPA
pump_frequency (float): calibrated pump frequency at which twpa gives the maximum average snr improvement
pump_amplitude (float): calibrated pump amplitude at which twpa gives the maximum average snr improvement
pump_frequency (float): calibrated pump frequency at which twpa gives the maximum average snr improvement
pump_amplitude (float): calibrated pump amplitude at which twpa gives the maximum average snr improvement
mltpx_pump_frequency (float): calibrated pump frequency at which twpa gives proper snr improvement for multiplexed readout
mltpx_pump_amplitude (float): calibrated pump amplitude at which twpa gives proper snr improvement for multiplexed readout
p_saturation (float): calibrated saturation power of the twpa
p_saturation (float): calibrated saturation power of the twpa
avg_std_gain (float): standard deviation of the average gain around the readout resonators related to the TWPA
avg_std_snr_improvement (float): standard deviation of the average snr improvement around the readout resonators related to the TWPA

dispersive_feature (float): dispersive feature of the twpa defined from it's designed parameters
qubits (list): list of qubits of which the signals are amplified by the twpa

initialization (bool): whether to use the twpa in the QUA program or not
_initialized_ids (ClassVar[set]): A class-level set to track initialized twpa object IDs externally.
This won't be serialized since it's not an instance attribute.
Expand All @@ -47,48 +47,43 @@ class TWPA(QuamComponent):

max_avg_gain: float = None
max_avg_snr_improvement: float = None
pump_frequency : float = None
pump_amplitude : float = None
mltpx_pump_frequency : float = None
mltpx_pump_amplitude : float = None
pump_frequency: float = None
pump_amplitude: float = None
mltpx_pump_frequency: float = None
mltpx_pump_amplitude: float = None
p_saturation: float = None
avg_std_gain: float=None
avg_std_snr_improvement: float= None
avg_std_gain: float = None
avg_std_snr_improvement: float = None

dispersive_feature: float = None
qubits: list = None

initialization: bool = True
_initialized_ids: ClassVar[set] = set()


@property
def name(self):
"""The name of the twpa"""
return self.id if isinstance(self.id, str) else f"twpa{self.id}"



def initialize(self):
# dont use twpa for the QUA program if initialization is set to False
if not self.initialization:
return
return
# Check initialization state using object ID (memory address)
# Initialize TWPA pump only when it hasn't been initialized yet
# Initialize TWPA pump only when it hasn't been initialized yet
# This won't be serialized since it's stored in a class-level set
obj_id = id(self)
if obj_id in self._initialized_ids:
return

f_p = self.pump_frequency
p_p = self.pump_amplitude
update_frequency(
self.pump.name,
f_p+ self.pump.intermediate_frequency,
f_p + self.pump.intermediate_frequency,
)
self.pump.play("pump", amplitude_scale=p_p)
# Store object ID externally (won't be serialized)
# guarantee initializing twpa pump only once per QUA program execution
self._initialized_ids.add(obj_id)


Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ class XYDriveMW(MWChannel, XYDriveBase):
@property
def upconverter_frequency(self):
"""Returns the up-converter/LO frequency in Hz."""
return self.opx_output.upconverter_frequency
return (
self.opx_output.upconverter_frequency
if self.opx_output.upconverter_frequency is not None
else super().upconverter_frequency
)

def get_output_power(self, operation, Z=50) -> float:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
from quam.components.macro import QubitPairMacro
from quam.components.pulses import Pulse
from quam.core import quam_dataclass
from quam.utils.qua_types import (
ScalarInt
)
from quam.utils.qua_types import ScalarInt

__all__ = ["CZGate"]


Expand Down Expand Up @@ -65,7 +64,7 @@ class CZGate(QubitPairMacro):
unwanted frequency shifts during the CZ gate.
- Maintaining qubit states: keeping spectator qubits in specific states during the gate.
- Multi-qubit gate synchronization: ensuring all qubits are properly aligned and synchronized.

The three spectator qubit parameters work together:
- ``spectator_qubits``: Dictionary mapping qubit names (str) to qubit objects. These are the
qubit instances that will be controlled during the gate.
Expand All @@ -75,7 +74,7 @@ class CZGate(QubitPairMacro):
- ``spectator_qubits_phase_shift``: Dictionary mapping qubit names (str) to phase shift values
(float, in units of 2π). These frame rotations are applied to the spectator qubits after
the flux pulses, similar to phase_shift_control and phase_shift_target.

Usage Example:
```python
# Configure spectator qubits for crosstalk compensation
Expand All @@ -101,7 +100,7 @@ class CZGate(QubitPairMacro):
"q1": 0.01, # Small phase correction for q1 (0.01 * 2π)
"q2": 0.0 # No phase correction needed for q2
}

# When apply() is called, spectator qubits will:
# 1. Be aligned with control and target qubits
# 2. Have their flux pulses played in parallel with the control qubit pulse
Expand All @@ -110,7 +109,7 @@ class CZGate(QubitPairMacro):
```
Note: The keys in all three dictionaries must match (same qubit names). Only qubits listed
in both ``spectator_qubits`` and ``spectator_qubits_control`` will have flux pulses applied.

spectator_qubits: dict[str, Any]
Optional dictionary of spectator qubit objects.
spectator_qubits_control: dict[str, Pulse]
Expand Down Expand Up @@ -175,7 +174,7 @@ class CZGate(QubitPairMacro):
spectator_qubits: dict[str, Any] = field(default_factory=dict)
spectator_qubits_control: dict[str, Pulse] = field(default_factory=dict)
spectator_qubits_phase_shift: dict[str, float] = field(default_factory=dict)

fidelity: dict[str, Any] = field(default_factory=dict)
extras: dict[str, Any] = field(default_factory=dict)
duration_control: ScalarInt = None
Expand Down Expand Up @@ -207,9 +206,8 @@ def apply(
phase_shift_control=None,
phase_shift_target=None,
**kwargs,

) -> None:

# Build list of spectator qubits and their pulse names
spectator_qubits_list = []
spectator_pulse_names = {}
Expand All @@ -224,17 +222,19 @@ def apply(
self.qubit_pair.qubit_control.align(align_list)

# Spectator qubit flux pulses
for qubit_name, spectator_qubit in zip(self.spectator_qubits.keys(), spectator_qubits_list):
for qubit_name, spectator_qubit in zip(
self.spectator_qubits.keys(), spectator_qubits_list
):
if qubit_name in spectator_pulse_names:
spectator_qubit.z.play(spectator_pulse_names[qubit_name])

# Control qubit flux
self.qubit_pair.qubit_control.z.play(
self.flux_pulse_control_label,
amplitude_scale=amplitude_scale_control,
duration=duration_control
duration=duration_control,
)

# Coupler flux
if self.coupler_flux_pulse is not None:
self.qubit_pair.coupler.play(
Expand All @@ -244,8 +244,10 @@ def apply(
)

# Align all resources after playing pulses
self.qubit_pair.qubit_control.align([self.qubit_pair.qubit_target] + spectator_qubits_list)

self.qubit_pair.qubit_control.align(
[self.qubit_pair.qubit_target] + spectator_qubits_list
)

# Apply phase shifts
if phase_shift_control is not None:
self.qubit_pair.qubit_control.xy.frame_rotation_2pi(phase_shift_control)
Expand All @@ -264,4 +266,6 @@ def apply(
self.spectator_qubits[qubit_name].xy.frame_rotation_2pi(phase_shift)

# Final alignment
self.qubit_pair.qubit_control.align([self.qubit_pair.qubit_target] + spectator_qubits_list)
self.qubit_pair.qubit_control.align(
[self.qubit_pair.qubit_target] + spectator_qubits_list
)
7 changes: 6 additions & 1 deletion quam_builder/architecture/superconducting/qpu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@
from quam_builder.architecture.superconducting.qpu.flux_tunable_quam import (
FluxTunableQuam,
)
from quam_builder.architecture.superconducting.qpu.cavity_quam import (
CavityQuam,
)

from typing import Union

__all__ = [
*base_quam.__all__,
*fixed_frequency_quam.__all__,
*flux_tunable_quam.__all__,
*cavity_quam.__all__,
]

AnyQuam = Union[BaseQuam, FixedFrequencyQuam, FluxTunableQuam]
AnyQuam = Union[BaseQuam, FixedFrequencyQuam, FluxTunableQuam, CavityQuam]
Loading
Loading