fromtypingimportAnnotated,Optional,UnionfrompydanticimportConfigDict,Fieldfrom.identifierimportChannelId,QubitId,TransitionIdfrom.serializeimportModel__all__=["Qubit"]DefaultChannelType=Annotated[Optional[ChannelId],True]"""If ``True`` the channel is included in the default qubit constructor."""
[docs]classQubit(Model):"""Representation of a physical qubit. Contains the channel ids used to control the qubit and is instantiated in the function that creates the corresponding :class:`qibolab.Platform` """model_config=ConfigDict(frozen=False)drive:DefaultChannelType=None"""Ouput channel, to drive the qubit state."""drive_extra:Annotated[dict[Union[TransitionId,QubitId],ChannelId],False]=(Field(default_factory=dict))"""Output channels collection, to drive non-qubit transitions."""flux:DefaultChannelType=None"""Output channel, to control the qubit flux."""probe:DefaultChannelType=None"""Output channel, to probe the resonator."""acquisition:DefaultChannelType=None"""Input channel, to acquire the readout results."""@propertydefchannels(self)->list[ChannelId]:return[xforxin([getattr(self,ch)forchin["probe","acquisition","drive","flux"]]+list(self.drive_extra.values()))ifxisnotNone]
[docs]@classmethoddefdefault(cls,name:QubitId,channels:Optional[list[str]]=None,**kwargs):"""Create a qubit with default channel names. Default channel names follow the convention: '{qubit_name}/{channel_type}' Args: name: Name for the qubit to be used for channel ids. channels: List of channels to add to the qubit. If ``None`` the following channels will be added: probe, acquisition, drive and flux. """ifchannelsisNone:channels=[nameforname,fincls.model_fields.items()iff.metadata[0]]returncls(**{ch:f"{name}/{ch}"forchinchannels},**kwargs)
[docs]@classmethoddefcoupler(cls,name:QubitId,**kwargs):"""Create a qubit with default channel names."""returncls(flux=f"coupler_{name}/flux",**kwargs)
classQubitPair(Model):"""Represent a two-qubit interaction."""drive:Optional[ChannelId]=None"""Output channel, for cross-resonance driving."""