Skip to content

QUAM Ports API

Welcome to the QUAM Ports API Documentation. The QUAM Ports module provides abstractions for hardware connection points including analog and digital inputs/outputs. Information can be found in QUAM Ports Documentation in the User Guide.

This section provides detailed API references for port types—from base ports to specific analog and digital implementations—that represent physical connections between the quantum control hardware and quantum devices.

BasePort

Bases: QuamComponent, ABC

Source code in quam/components/ports/base_ports.py
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@quam_dataclass
class BasePort(QuamComponent, ABC):
    port_type: ClassVar[str]

    @abstractmethod
    def get_port_config(
        self, config: Dict[str, Any], create: bool = True
    ) -> Dict[str, Any]:
        pass

    @abstractmethod
    def get_port_properties(self) -> Dict[str, Any]:
        pass

    @property
    @abstractmethod
    def port_tuple(self) -> Union[Tuple[str, int], Tuple[str, int, int]]:
        pass

    def _update_port_config(self, port_config, port_properties):
        for key, value in port_properties.items():
            try:
                if key in port_config and value != port_config[key]:
                    warnings.warn(
                        f"Error generating QUA config: Controller {self.port_type} "
                        f"port {self.port_tuple} already has entry for {key}. This "
                        f"likely means that the port is being configured multiple "
                        f"times. Overwriting {port_config[key]}{value}."
                    )
            except Exception:
                pass
            port_config[key] = value

    def apply_to_config(self, config: Dict) -> None:
        super().apply_to_config(config)

        port_cfg = self.get_port_config(config)
        port_properties = self.get_port_properties()
        self._update_port_config(port_cfg, port_properties)

OPXPlusPort

Bases: BasePort, ABC

Source code in quam/components/ports/base_ports.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@quam_dataclass(kw_only=False)
class OPXPlusPort(BasePort, ABC):
    controller_id: Union[str, int]
    port_id: int

    @property
    def port_tuple(self) -> Tuple[Union[str, int], int]:
        return self.controller_id, self.port_id

    def get_port_config(
        self, config: Dict[str, Any], create: bool = True
    ) -> Dict[str, Any]:

        if not create:
            try:
                controller_cfg = config["controllers"][self.controller_id]
                return controller_cfg[f"{self.port_type}"][self.port_id]
            except KeyError:
                raise KeyError(
                    f"Error generating config: controller {self.controller_id} does "
                    f"not have entry {self.port_type}s for port {self.port_tuple}"
                )

        controller_cfg = config["controllers"].setdefault(self.controller_id, {})
        ports_cfg = controller_cfg.setdefault(f"{self.port_type}s", {})
        port_cfg = ports_cfg.setdefault(self.port_id, {})
        return port_cfg

FEMPort

Bases: BasePort, ABC

Source code in quam/components/ports/base_ports.py
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
@quam_dataclass(kw_only=False)
class FEMPort(BasePort, ABC):
    fem_type: ClassVar[str]
    controller_id: Union[str, int]
    fem_id: int
    port_id: int

    @property
    def port_tuple(self) -> Tuple[Union[str, int], int, int]:
        return self.controller_id, self.fem_id, self.port_id

    def get_port_config(
        self, config: Dict[str, Any], create: bool = True
    ) -> Dict[str, Any]:

        if not create:
            try:
                controller_cfg = config["controllers"][self.controller_id]
                fem_cfg = controller_cfg["fems"][self.fem_id]
            except KeyError:
                raise KeyError(
                    f"Error generating config: controller {self.controller_id} does "
                    f"not have entry for FEM {self.fem_id} for "
                    f"port {self.port_id}"
                )
            try:
                return fem_cfg[f"{self.port_type}s"][self.port_id]
            except KeyError:
                raise KeyError(
                    f"Error generating config: controller {self.controller_id} does "
                    f"not have entry {self.port_type}s for port {self.port_tuple}"
                )

        controller_cfg = config["controllers"].setdefault(self.controller_id, {})
        fems_cfg = controller_cfg.setdefault("fems", {})
        fem_cfg = fems_cfg.setdefault(self.fem_id, {})
        if hasattr(self, "fem_type"):
            if fem_cfg.get("type", self.fem_type) != self.fem_type:
                raise ValueError(
                    f"Error generating config: FEM {self.fem_id} is not of type "
                    f"{self.fem_type}"
                )
            fem_cfg["type"] = self.fem_type

        ports_cfg = fem_cfg.setdefault(f"{self.port_type}s", {})
        port_cfg = ports_cfg.setdefault(self.port_id, {})
        return port_cfg

OPXPlusAnalogOutputPort

Bases: LFAnalogOutputPort, OPXPlusPort

Source code in quam/components/ports/analog_outputs.py
47
48
49
@quam_dataclass
class OPXPlusAnalogOutputPort(LFAnalogOutputPort, OPXPlusPort):
    pass

OPXPlusAnalogInputPort

Bases: LFAnalogInputPort, OPXPlusPort

Source code in quam/components/ports/analog_inputs.py
35
36
37
@quam_dataclass
class OPXPlusAnalogInputPort(LFAnalogInputPort, OPXPlusPort):
    pass

LFAnalogOutputPort

Bases: BasePort, ABC

Source code in quam/components/ports/analog_outputs.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@quam_dataclass
class LFAnalogOutputPort(BasePort, ABC):
    fem_type: ClassVar[str] = "LF"
    port_type: ClassVar[str] = "analog_output"

    offset: Optional[float] = None
    delay: int = 0
    crosstalk: Optional[Dict[int, float]] = None
    feedforward_filter: Optional[List[float]] = None
    feedback_filter: Optional[List[float]] = None
    shareable: bool = False

    def get_port_properties(self):
        port_properties = {
            "delay": self.delay,
            "shareable": self.shareable,
        }
        if self.crosstalk is not None:
            port_properties["crosstalk"] = dict(self.crosstalk)
        if self.feedforward_filter is not None:
            port_properties.setdefault("filter", {})["feedforward"] = list(
                self.feedforward_filter
            )
        if self.feedback_filter is not None:
            port_properties.setdefault("filter", {})["feedback"] = list(
                self.feedback_filter
            )
        if self.offset is not None:
            port_properties["offset"] = self.offset
        return port_properties

LFAnalogInputPort

Bases: BasePort, ABC

Source code in quam/components/ports/analog_inputs.py
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@quam_dataclass
class LFAnalogInputPort(BasePort, ABC):
    fem_type: ClassVar[str] = "LF"
    port_type: ClassVar[str] = "analog_input"

    offset: Optional[float] = None
    gain_db: int = 0
    shareable: bool = False

    def get_port_properties(self):
        port_cfg = {
            "gain_db": self.gain_db,
            "shareable": self.shareable,
        }
        if self.offset is not None:
            port_cfg["offset"] = self.offset
        return port_cfg

LFFEMAnalogOutputPort

Bases: LFAnalogOutputPort, FEMPort

Source code in quam/components/ports/analog_outputs.py
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
@quam_dataclass
class LFFEMAnalogOutputPort(LFAnalogOutputPort, FEMPort):
    fem_type: ClassVar[str] = "LF"
    sampling_rate: float = 1e9  # Either 1e9 or 2e9
    upsampling_mode: Literal["mw", "pulse"] = "mw"
    exponential_filter: Optional[List[Tuple[float, float]]] = None
    # high_pass_filter: Optional[float] = None  # Not yet supported
    output_mode: Literal["direct", "amplified"] = "direct"

    def get_port_properties(self) -> Dict[str, Any]:
        port_properties = super().get_port_properties()
        if self.exponential_filter is not None:
            filter_properties = port_properties.setdefault("filter", {})
            filter_properties["exponential"] = list(self.exponential_filter)
            if "feedback" in filter_properties:
                raise ValueError(
                    "LFFEMAnalogOutputPort: Please only specify 'exponential_filter' "
                    "if QOP >=3.3.0, or 'feedback_filter' if QOP < 3.3.0, not both"
                )

        port_properties["sampling_rate"] = self.sampling_rate
        if self.sampling_rate == 1e9:
            port_properties["upsampling_mode"] = self.upsampling_mode
        port_properties["output_mode"] = self.output_mode
        return port_properties

LFFEMAnalogInputPort

Bases: LFAnalogInputPort, FEMPort

Source code in quam/components/ports/analog_inputs.py
40
41
42
43
44
45
46
47
@quam_dataclass
class LFFEMAnalogInputPort(LFAnalogInputPort, FEMPort):
    sampling_rate: float = 1e9  # Either 1e9 or 2e9

    def get_port_properties(self) -> Dict[str, Any]:
        port_properties = super().get_port_properties()
        port_properties["sampling_rate"] = self.sampling_rate
        return port_properties

MWFEMAnalogOutputPort

Bases: FEMPort

Source code in quam/components/ports/analog_outputs.py
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
@quam_dataclass
class MWFEMAnalogOutputPort(FEMPort):
    fem_type: ClassVar[str] = "MW"
    port_type: ClassVar[str] = "analog_output"

    band: int
    upconverter_frequency: Optional[float] = None
    upconverters: Optional[Dict[int, Dict[str, float]]] = None
    delay: int = 0
    shareable: bool = False
    sampling_rate: float = 1e9  # Either 1e9 or 2e9
    full_scale_power_dbm: int = -11

    def __post_init__(self) -> None:
        super().__post_init__()
        if self.upconverter_frequency is None and self.upconverters is None:
            raise ValueError(
                "MWAnalogOutputPort: Either upconverter_frequency or upconverters must "
                "be provided"
            )

    def get_port_properties(self) -> Dict[str, Any]:
        port_cfg = {
            "band": self.band,
            "delay": self.delay,
            "shareable": self.shareable,
            "sampling_rate": self.sampling_rate,
            "full_scale_power_dbm": self.full_scale_power_dbm,
        }
        if self.upconverter_frequency is not None:
            port_cfg["upconverter_frequency"] = self.upconverter_frequency
        if self.upconverters is not None:
            port_cfg["upconverters"] = {
                key: dict(val) for key, val in self.upconverters.items()
            }
        return port_cfg

MWFEMAnalogInputPort

Bases: FEMPort

Source code in quam/components/ports/analog_inputs.py
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@quam_dataclass
class MWFEMAnalogInputPort(FEMPort):
    fem_type: ClassVar[str] = "MW"
    port_type: ClassVar[str] = "analog_input"

    band: int
    downconverter_frequency: float
    gain_db: Optional[int] = None
    sampling_rate: float = 1e9  # Either 1e9 or 2e9
    shareable: bool = False

    def get_port_properties(self) -> Dict[str, Any]:
        port_properties = {
            "band": self.band,
            "downconverter_frequency": self.downconverter_frequency,
            "sampling_rate": self.sampling_rate,
            "shareable": self.shareable,
        }
        if self.gain_db is not None:
            port_properties["gain_db"] = self.gain_db
        return port_properties

OPXPlusDigitalOutputPort

Bases: DigitalOutputPort, OPXPlusPort

Source code in quam/components/ports/digital_outputs.py
22
23
24
@quam_dataclass
class OPXPlusDigitalOutputPort(DigitalOutputPort, OPXPlusPort):
    pass

OPXPlusDigitalInputPort

Bases: OPXPlusPort

Source code in quam/components/ports/digital_inputs.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@quam_dataclass
class OPXPlusDigitalInputPort(OPXPlusPort):
    port_type: ClassVar[str] = "digital_input"

    deadtime: int = 4
    polarity: Literal["rising", "falling"] = "rising"
    threshold: float = 2.0
    shareable: bool = False

    def get_port_properties(self) -> Dict[str, Any]:
        return {
            "deadtime": self.deadtime,
            "polarity": self.polarity,
            "threshold": self.threshold,
            "shareable": self.shareable,
        }

DigitalOutputPort

Bases: BasePort, ABC

Source code in quam/components/ports/digital_outputs.py
11
12
13
14
15
16
17
18
19
@quam_dataclass
class DigitalOutputPort(BasePort, ABC):
    port_type: ClassVar[str] = "digital_output"

    inverted: bool = False
    shareable: bool = False

    def get_port_properties(self) -> Dict[str, Any]:
        return {"inverted": self.inverted, "shareable": self.shareable}

FEMDigitalOutputPort

Bases: DigitalOutputPort, FEMPort

Source code in quam/components/ports/digital_outputs.py
27
28
29
30
31
32
33
34
@quam_dataclass
class FEMDigitalOutputPort(DigitalOutputPort, FEMPort):
    level: Literal["TTL", "LVTTL"] = "LVTTL"

    def get_port_properties(self) -> Dict[str, Any]:
        port_properties = super().get_port_properties()
        port_properties["level"] = self.level
        return port_properties

OPXPlusPortsContainer

Bases: QuamComponent

Source code in quam/components/ports/ports_containers.py
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
@quam_dataclass
class OPXPlusPortsContainer(QuamComponent):
    analog_outputs: Dict[Union[str, int], Dict[int, OPXPlusAnalogOutputPort]] = field(
        default_factory=dict
    )
    analog_inputs: Dict[Union[str, int], Dict[int, OPXPlusAnalogInputPort]] = field(
        default_factory=dict
    )
    digital_outputs: Dict[Union[str, int], Dict[int, OPXPlusDigitalOutputPort]] = field(
        default_factory=dict
    )
    digital_inputs: Dict[Union[str, int], Dict[int, OPXPlusDigitalInputPort]] = field(
        default_factory=dict
    )

    def _get_port(
        self,
        controller_id: Union[str, int],
        port_id: int,
        port_type: str,
        create: bool = False,
        **kwargs,
    ):
        controllers = getattr(self, f"{port_type}s")

        try:
            return controllers[controller_id][port_id]
        except KeyError:
            if not create:
                raise KeyError(
                    f"Could not find existing {port_type} port: "
                    f"{port_type} ({controller_id}, {port_id}"
                )

        controllers.setdefault(controller_id, {})
        ports = controllers[controller_id]

        if port_type == "analog_output":
            ports[port_id] = OPXPlusAnalogOutputPort(controller_id, port_id, **kwargs)
        elif port_type == "analog_input":
            ports[port_id] = OPXPlusAnalogInputPort(controller_id, port_id, **kwargs)
        elif port_type == "digital_output":
            ports[port_id] = OPXPlusDigitalOutputPort(controller_id, port_id, **kwargs)
        elif port_type == "digital_input":
            ports[port_id] = OPXPlusDigitalInputPort(controller_id, port_id, **kwargs)
        else:
            raise ValueError(f"Invalid port type: {port_type}")

        return ports[port_id]

    def reference_to_port(
        self,
        port_reference: Union[QuamComponent, str],
        attr: Optional[str] = None,
        create=False,
    ) -> OPXPlusPortTypes:
        if isinstance(port_reference, QuamComponent):
            reference = port_reference.get_reference(attr=attr)
            if reference is None:
                raise ValueError("Cannot get port from reference {port_reference}")
            port_reference = reference
        elems = port_reference.split("/")
        port_type, controller_id, port_id = elems[-3:]

        port_type = port_type[:-1]
        if controller_id.isdigit():
            controller_id = int(controller_id)
        port_id = int(port_id)

        return self._get_port(controller_id, port_id, port_type, create=create)

    def get_analog_output(
        self,
        controller_id: Union[str, int],
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> OPXPlusAnalogOutputPort:
        return self._get_port(
            controller_id, port_id, port_type="analog_output", create=create, **kwargs
        )

    def get_analog_input(
        self,
        controller_id: Union[str, int],
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> OPXPlusAnalogInputPort:
        return self._get_port(
            controller_id, port_id, port_type="analog_input", create=create, **kwargs
        )

    def get_digital_output(
        self,
        controller_id: Union[str, int],
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> OPXPlusDigitalOutputPort:
        return self._get_port(
            controller_id, port_id, port_type="digital_output", create=create, **kwargs
        )

    def get_digital_input(
        self,
        controller_id: Union[str, int],
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> OPXPlusDigitalInputPort:
        return self._get_port(
            controller_id, port_id, port_type="digital_input", create=create, **kwargs
        )

FEMPortsContainer

Bases: QuamComponent

Source code in quam/components/ports/ports_containers.py
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
@quam_dataclass
class FEMPortsContainer(QuamComponent):
    num_port_elems: ClassVar[int] = 3
    analog_outputs: Dict[
        Union[str, int], Dict[int, Dict[int, LFFEMAnalogOutputPort]]
    ] = field(default_factory=dict)
    analog_inputs: Dict[Union[str, int], Dict[int, Dict[int, LFFEMAnalogInputPort]]] = (
        field(default_factory=dict)
    )
    mw_outputs: Dict[Union[str, int], Dict[int, Dict[int, MWFEMAnalogOutputPort]]] = (
        field(default_factory=dict)
    )
    mw_inputs: Dict[Union[str, int], Dict[int, Dict[int, MWFEMAnalogInputPort]]] = (
        field(default_factory=dict)
    )
    digital_outputs: Dict[
        Union[str, int], Dict[int, Dict[int, FEMDigitalOutputPort]]
    ] = field(default_factory=dict)

    def _get_port(
        self,
        controller_id: Union[str, int],
        fem_id: int,
        port_id: int,
        port_type: str,
        create: bool = False,
        **kwargs,
    ):
        controllers = getattr(self, f"{port_type}s")

        try:
            return controllers[controller_id][fem_id][port_id]
        except KeyError:
            if not create:
                raise KeyError(
                    f"Could not find existing {port_type} port: "
                    f"{port_type} ({controller_id}, {fem_id}, {port_id}"
                )

        controllers.setdefault(controller_id, {})
        fems = controllers[controller_id]
        fems.setdefault(fem_id, {})
        ports = fems[fem_id]

        if port_type == "analog_output":
            ports[port_id] = LFFEMAnalogOutputPort(
                controller_id, fem_id, port_id, **kwargs
            )
        elif port_type == "analog_input":
            ports[port_id] = LFFEMAnalogInputPort(
                controller_id, fem_id, port_id, **kwargs
            )
        elif port_type == "mw_output":
            # Set default values in kwargs before passing to constructor
            # Safe to mutate since kwargs is used only once per port creation
            if "upconverter_frequency" not in kwargs and "upconverters" not in kwargs:
                kwargs["upconverter_frequency"] = 5e9
            if "band" not in kwargs:
                kwargs["band"] = 1
            ports[port_id] = MWFEMAnalogOutputPort(
                controller_id, fem_id, port_id, **kwargs
            )
        elif port_type == "mw_input":
            # Set default values in kwargs before passing to constructor
            # Safe to mutate since kwargs is used only once per port creation
            if "band" not in kwargs:
                kwargs["band"] = 1
            if "downconverter_frequency" not in kwargs:
                kwargs["downconverter_frequency"] = 5e9
            ports[port_id] = MWFEMAnalogInputPort(
                controller_id,
                fem_id,
                port_id,
                **kwargs,
            )
        elif port_type == "digital_output":
            ports[port_id] = FEMDigitalOutputPort(
                controller_id, fem_id, port_id, **kwargs
            )
        else:
            raise ValueError(f"Invalid port type: {port_type}")

        return ports[port_id]

    def reference_to_port(
        self,
        port_reference: Union[QuamComponent, str],
        attr: Optional[str] = None,
        create=False,
    ) -> FEMPortTypes:
        if isinstance(port_reference, QuamBase):
            reference = port_reference.get_reference(attr=attr)
            if reference is None:
                raise ValueError("Cannot get port from reference {port_reference}")
            port_reference = reference

        elems = port_reference.split("/")
        port_type, controller_id, fem_id, port_id = elems[-4:]

        port_type = port_type[:-1]
        if controller_id.isdigit():
            controller_id = int(controller_id)
        fem_id = int(fem_id)
        port_id = int(port_id)

        return self._get_port(controller_id, fem_id, port_id, port_type, create=create)

    def get_analog_output(
        self,
        controller_id: Union[str, int],
        fem_id: int,
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> LFFEMAnalogOutputPort:
        return self._get_port(
            controller_id,
            fem_id,
            port_id,
            port_type="analog_output",
            create=create,
            **kwargs,
        )

    def get_analog_input(
        self,
        controller_id: Union[str, int],
        fem_id: int,
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> LFFEMAnalogInputPort:
        return self._get_port(
            controller_id,
            fem_id,
            port_id,
            port_type="analog_input",
            create=create,
            **kwargs,
        )

    def get_mw_output(
        self,
        controller_id: Union[str, int],
        fem_id: int,
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> MWFEMAnalogOutputPort:
        return self._get_port(
            controller_id,
            fem_id,
            port_id,
            port_type="mw_output",
            create=create,
            **kwargs,
        )

    def get_mw_input(
        self,
        controller_id: Union[str, int],
        fem_id: int,
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> MWFEMAnalogInputPort:
        return self._get_port(
            controller_id,
            fem_id,
            port_id,
            port_type="mw_input",
            create=create,
            **kwargs,
        )

    def get_digital_output(
        self,
        controller_id: Union[str, int],
        fem_id: int,
        port_id: int,
        create: bool = False,
        **kwargs,
    ) -> FEMDigitalOutputPort:
        return self._get_port(
            controller_id,
            fem_id,
            port_id,
            port_type="digital_output",
            create=create,
            **kwargs,
        )