semi_cr.core.station package¶
Subpackages¶
- semi_cr.core.station.instruments package
LabInstrument- Submodules
- semi_cr.core.station.instruments.base module
- semi_cr.core.station.instruments.dmm module
DMMVoltageTerminalDMMBlueprintDMMBlueprint.nameDMMBlueprint.inputsDMMBlueprint.connectionsDMMBlueprint.addressDMMBlueprint.read_voltage()DMMBlueprint.from_instrument_spec()DMMBlueprint.graph_nodes()DMMBlueprint.graph_edges()DMMBlueprint.connect()DMMBlueprint.disconnect()DMMBlueprint.is_connected()DMMBlueprint.qcodes_config
- semi_cr.core.station.instruments.opx1000 module
OPX1000LFTerminalOPX1000LFTerminal.RoleOPX1000LFTerminal.parent_refOPX1000LFTerminal.nameOPX1000LFTerminal.roleOPX1000LFTerminal.femOPX1000LFTerminal.node_idOPX1000LFTerminal.opx1000OPX1000LFTerminal.graph_nodes()OPX1000LFTerminal.graph_edges()OPX1000LFTerminal.to_opx_output_ref()OPX1000LFTerminal.to_opx_input_ref()
OPX1000LFFEMOPX1000Blueprint
- semi_cr.core.station.instruments.qcodes_proxy module
- semi_cr.core.station.instruments.spirack module
SPIRackD5aTerminalSPIRackD5aTerminal.parent_refSPIRackD5aTerminal.nameSPIRackD5aTerminal.channelSPIRackD5aTerminal.roleSPIRackD5aTerminal.moduleSPIRackD5aTerminal.spirackSPIRackD5aTerminal.node_idSPIRackD5aTerminal.graph_nodes()SPIRackD5aTerminal.graph_edges()SPIRackD5aTerminal.set_voltage()SPIRackD5aTerminal.get_voltage()SPIRackD5aTerminal.get_voltage_parameter()
SPIRackD5aModuleSPIRackStaticTerminalSPIRackStaticModuleSPIRackStaticModule.parent_refSPIRackStaticModule.nameSPIRackStaticModule.module_typeSPIRackStaticModule.slotSPIRackStaticModule.connectionsSPIRackStaticModule.voltage_conversion_factorSPIRackStaticModule.gain_v_per_aSPIRackStaticModule.attributesSPIRackStaticModule.from_instrument_spec()SPIRackStaticModule.graph_nodes()SPIRackStaticModule.graph_edges()
SPIRackBlueprintSPIRackBlueprint.nameSPIRackBlueprint.d5a_modulesSPIRackBlueprint.static_modulesSPIRackBlueprint.from_instrument_spec()SPIRackBlueprint.graph_nodes()SPIRackBlueprint.graph_edges()SPIRackBlueprint.connect()SPIRackBlueprint.disconnect()SPIRackBlueprint.is_connected()SPIRackBlueprint.qcodes_config
Submodules¶
semi_cr.core.station.chip module¶
This module declares a Chip class representing a quantum chip and its associated devices. For now, it’s deserializable from the QCoDes YAML format, but in the future it should hold more chip-related information.
Example of a chip configuration in YAML format:
instruments:
X002001C1:
type: semi_cr.core.lab.instrument.chip.Chip
init:
devices:
D1:
type: semi_cr.core.lab.devices.multiplexer.Multiplexer
pins:
T2:
type: Gate
pads:
- QboardII[8]
T4:
type: Gate
pads:
- QboardII[17]
B1:
type: Gate
pads:
- QboardII[38]
B4:
type: Gate
pads:
- QboardII[32]
RF_In:
type: RFInput
pads:
- QboardII[RF1]
RF_Out_1:
type: RFOutput
pads:
- QboardII[RF4]
RF_Out_2:
type: RFOutput
pads:
- QboardII[RF8]
RF_Out_3:
type: RFOutput
pads:
- QboardII[RF10]
RF_Out_4:
type: RFOutput
pads:
- QboardII[RF12]
- class semi_cr.core.station.chip.Chip(chip_id: 'str', parent_ref: 'NQCPStation', devices: 'list[QuantumDevice]' = <factory>)[source]¶
Bases:
object- parent_ref: NQCPStation¶
- devices: list[QuantumDevice]¶
- device(device_id: str) QuantumDevice[source]¶
Gets a device by name.
- Returns:
The device matching
device_id.- Raises:
KeyError – If no matching device exists.
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: NQCPStation) Chip[source]¶
Given the parsed yaml of a chip, return a Chip object. Recursively creates QuantumDevice objects.
spec is a tuple: - First element is the identifier of the Chip - Second element is the QCoDes compatible YAML structure underneath it
- graph_nodes() Iterable[GraphNode][source]¶
Iterates over all devices to return the graph nodes for this chip.
- graph_edges() Iterable[GraphEdge][source]¶
Iterates over all devices to return any graph edges for this chip.
- to_quam() BaseQuamQD[source]¶
Exports a representation of the current chip for use with quam-builder, such as the gate tuning web app Torbjørn presented. At the meeting on 2026-09-28 we decided that it should live on our Chip representation, not device or station.
- Returns:
A
BaseQuamQDrepresentation of the current chip.
semi_cr.core.station.device module¶
- class semi_cr.core.station.device.DevicePin(name: 'str', pin_type: 'str', config: 'Mapping[str, Any]', parent_ref: 'QuantumDevice')[source]¶
Bases:
object- parent_ref: QuantumDevice¶
- property station¶
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: QuantumDevice) DevicePin[source]¶
Instantiates a DevicePin (or subclass thereof) depending on the spec. Currently, the specification uses the type property to denote the pin type. When hydrating we’d like to have that reflected in what object is instantiated. So the logic is this:
Extract the pin type
Look up what class is appropriate for that type
Extract that class with the spec, ensure it points back to the QuantumDevice containing it, and return.
- class semi_cr.core.station.device.Gate(name: 'str', pin_type: 'str', config: 'Mapping[str, Any]', parent_ref: 'QuantumDevice', role: 'Role | None' = None)[source]¶
Bases:
DevicePin- class Role(*values)[source]¶
Bases:
Enum- Plunger = 1¶
- Barrier = 2¶
- Screening = 3¶
- Cutter = 4¶
- classmethod __contains__(value)¶
Return True if value is in cls.
value is in cls if: 1) value is a member of cls, or 2) value is the value of one of the cls’s members.
- classmethod __getitem__(name)¶
Return the member matching name.
- classmethod __iter__()¶
Return members in definition order.
- classmethod __len__()¶
Return the number of members (no aliases)
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: QuantumDevice) DevicePin¶
Instantiates a DevicePin (or subclass thereof) depending on the spec. Currently, the specification uses the type property to denote the pin type. When hydrating we’d like to have that reflected in what object is instantiated. So the logic is this:
Extract the pin type
Look up what class is appropriate for that type
Extract that class with the spec, ensure it points back to the QuantumDevice containing it, and return.
- get_ac_driver()¶
- get_dc_driver()¶
- property station¶
- name¶
- pin_type¶
- config¶
- parent_ref¶
- class semi_cr.core.station.device.Ohmic(name: 'str', pin_type: 'str', config: 'Mapping[str, Any]', parent_ref: 'QuantumDevice', role: 'Role | None' = None)[source]¶
Bases:
DevicePin- class Role(*values)[source]¶
Bases:
Enum- Source = 1¶
- Drain = 2¶
- classmethod __contains__(value)¶
Return True if value is in cls.
value is in cls if: 1) value is a member of cls, or 2) value is the value of one of the cls’s members.
- classmethod __getitem__(name)¶
Return the member matching name.
- classmethod __iter__()¶
Return members in definition order.
- classmethod __len__()¶
Return the number of members (no aliases)
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: QuantumDevice) DevicePin¶
Instantiates a DevicePin (or subclass thereof) depending on the spec. Currently, the specification uses the type property to denote the pin type. When hydrating we’d like to have that reflected in what object is instantiated. So the logic is this:
Extract the pin type
Look up what class is appropriate for that type
Extract that class with the spec, ensure it points back to the QuantumDevice containing it, and return.
- get_ac_driver()¶
- get_dc_driver()¶
- property station¶
- name¶
- pin_type¶
- config¶
- parent_ref¶
- class semi_cr.core.station.device.RFPin(name: 'str', pin_type: 'str', config: 'Mapping[str, Any]', parent_ref: 'QuantumDevice', role: 'Role | None' = None)[source]¶
Bases:
DevicePin- class Role(*values)[source]¶
Bases:
Enum- RFInput = 1¶
- RFOutput = 2¶
- classmethod __contains__(value)¶
Return True if value is in cls.
value is in cls if: 1) value is a member of cls, or 2) value is the value of one of the cls’s members.
- classmethod __getitem__(name)¶
Return the member matching name.
- classmethod __iter__()¶
Return members in definition order.
- classmethod __len__()¶
Return the number of members (no aliases)
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: QuantumDevice) DevicePin¶
Instantiates a DevicePin (or subclass thereof) depending on the spec. Currently, the specification uses the type property to denote the pin type. When hydrating we’d like to have that reflected in what object is instantiated. So the logic is this:
Extract the pin type
Look up what class is appropriate for that type
Extract that class with the spec, ensure it points back to the QuantumDevice containing it, and return.
- get_ac_driver()¶
- get_dc_driver()¶
- property station¶
- name¶
- pin_type¶
- config¶
- parent_ref¶
- class semi_cr.core.station.device.ReadoutPath(drive: OPX1000LFTerminal, acquire: OPX1000LFTerminal, drive_root: DevicePin, acquire_root: DevicePin)[source]¶
Bases:
objectOPX terminals used to drive and acquire a measurement profile.
The path is derived from a
MeasurementProfileand the station graph. It stores terminal objects rather than raw node IDs so callers can convert them directly to OPX references.- drive: OPX1000LFTerminal¶
- acquire: OPX1000LFTerminal¶
- class semi_cr.core.station.device.MeasurementMethod(name: str, method_type: str, roles: Mapping[str, Any], config: Mapping[str, Any], parent_ref: MeasurementProfile)[source]¶
Bases:
objectMeasurement method declared inside a
MeasurementProfile.A method gives semantic roles to the profile’s pins for one concrete measurement procedure. For example, an S11-like method may use the same pin for
rf_sourceandrf_receiver, while an S21-like method may receive on a different pin.- parent_ref: MeasurementProfile¶
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: MeasurementProfile) MeasurementMethod[source]¶
Hydrate a measurement method from a profile config fragment.
- role(role_name: str) Any[source]¶
Return the hydrated value assigned to
role_namein this method.Role values mirror the config shape, but profile pin references are replaced with hydrated
DevicePinobjects. A role may therefore be a pin, a list of pins, or a nested mapping containing pins and scalar values.- Parameters:
role_name – Semantic method role name, such as
rf_source.- Returns:
The hydrated role value.
- Raises:
KeyError – If the method has no role with this name.
- get_readout_path(source_role: str = 'rf_source', receiver_role: str = 'rf_receiver') ReadoutPath[source]¶
Return the OPX readout path for this measurement method.
- Parameters:
source_role – Method role that identifies the source pin.
receiver_role – Method role that identifies the receiver pin.
- Returns:
The OPX drive/acquire terminal pair for this method.
- Raises:
KeyError – If either role does not exist.
LookupError – If either OPX terminal cannot be found.
- semi_cr.core.station.device.hydrate_measurement_role(profile: MeasurementProfile, role_spec: Any) Any[source]¶
Hydrate a measurement-method role value.
Strings that match profile pin names are resolved to
DevicePinobjects. Other strings are kept as scalar values. Lists and mappings are hydrated recursively so nested role structures keep their original shape.
- class semi_cr.core.station.device.MeasurementProfile(name: str, profile_type: str, pins: Mapping[str, DevicePin], methods: list[MeasurementMethod], config: Mapping[str, Any], parent_ref: QuantumDevice)[source]¶
Bases:
objectMeasurement profile declared on a
QuantumDevice.A profile gives semantic names to device pins for a measurement mode. For example, an RF profile may map
rf_into the device’sRF_INpin andrf_outtoRF_OUT. The profile stores direct references to the hydratedDevicePinobjects so downstream code does not need to re-resolve config strings.- methods: list[MeasurementMethod]¶
- parent_ref: QuantumDevice¶
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: QuantumDevice) MeasurementProfile[source]¶
Hydrate a measurement profile from a device config fragment.
- Parameters:
spec –
(profile_name, profile_config)from the device’smeasurement_profilessection.parent_ref – The owning quantum device.
- Returns:
A measurement profile with profile pin names resolved to hydrated
DevicePinobjects.- Raises:
KeyError – If a profile references a device pin that does not exist on
parent_ref.
- method(method_name: str) MeasurementMethod[source]¶
Return a measurement method by name.
- Parameters:
method_name – Name of the method, such as
vna_s11.- Returns:
The matching
MeasurementMethod.- Raises:
KeyError – If no method with this name exists.
- get_readout_path(method_name: str, source_role: str = 'rf_source', receiver_role: str = 'rf_receiver') ReadoutPath[source]¶
Return the OPX readout path for a measurement method.
- Parameters:
method_name – Name of the measurement method, such as
vna_s11.source_role – Method role that identifies the source profile pin.
receiver_role – Method role that identifies the receiver profile pin.
- Returns:
The OPX drive/acquire terminal pair for this method.
- Raises:
KeyError – If the method or roles do not exist.
LookupError – If either OPX terminal cannot be found.
- class semi_cr.core.station.device.QuantumDevice(device_id: 'str', qcodes_type: 'str', parent_ref: 'Chip', pins: 'list[DevicePin]' = <factory>, measurement_profiles: 'list[MeasurementProfile]' = <factory>)[source]¶
Bases:
object- measurement_profiles: list[MeasurementProfile]¶
- gate(gate_id: str) Gate[source]¶
Return a gate pin by name.
- Parameters:
gate_id – Name of the gate pin.
- Returns:
The matching
Gate.- Raises:
ValueError – If no gate with this name exists.
- property available_measurement_profiles: list[str]¶
Names of measurement profiles declared on this device.
- measurement_profile(profile_id: str) MeasurementProfile[source]¶
Return a measurement profile by name.
- Parameters:
profile_id – Name of the profile, such as
rf.- Returns:
The matching
MeasurementProfile.- Raises:
KeyError – If no profile with this name exists.
- property gates: list[Gate]¶
Returns the list of Gates for a QuantumDevice. Gates are a special case of DevicePin so we check if members of the pins list are in fact subclasses of Gate.
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: Chip) QuantumDevice[source]¶
Quantum devices are described in the QCoDeS configuration schema in the same way whether they are chips of our own design, or special-case things like for instance a tank inductor. In the general case we inflate the devices such that all pins become graph nodes that are responsible for their own edge relations (if any).
Special cases like the
TankInductorare registered inDEVICE_CLASS_BY_TYPEif they require special treatment during hydration.- Returns:
A
QuantumDeviceinstance containing references to a number ofDevicePininstances.
- class semi_cr.core.station.device.TankInductor(device_id: str, qcodes_type: str, parent_ref: Chip, pins: list[DevicePin] = <factory>, measurement_profiles: list[MeasurementProfile] = <factory>)[source]¶
Bases:
QuantumDeviceA special case of a QuantumDevice including edges between the graph nodes on its periphery, to model its actual conductance.
- graph_edges() Iterable[GraphEdge][source]¶
Iterates over all pins to return any graph edges for this device.
- property available_measurement_profiles: list[str]¶
Names of measurement profiles declared on this device.
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec, parent_ref: Chip) QuantumDevice¶
Quantum devices are described in the QCoDeS configuration schema in the same way whether they are chips of our own design, or special-case things like for instance a tank inductor. In the general case we inflate the devices such that all pins become graph nodes that are responsible for their own edge relations (if any).
Special cases like the
TankInductorare registered inDEVICE_CLASS_BY_TYPEif they require special treatment during hydration.- Returns:
A
QuantumDeviceinstance containing references to a number ofDevicePininstances.
- gate(gate_id: str) Gate¶
Return a gate pin by name.
- Parameters:
gate_id – Name of the gate pin.
- Returns:
The matching
Gate.- Raises:
ValueError – If no gate with this name exists.
- property gates: list[Gate]¶
Returns the list of Gates for a QuantumDevice. Gates are a special case of DevicePin so we check if members of the pins list are in fact subclasses of Gate.
- graph_nodes() Iterable[GraphNode]¶
Iterates over all pins to return the graph nodes for this device.
- measurement_profile(profile_id: str) MeasurementProfile¶
Return a measurement profile by name.
- Parameters:
profile_id – Name of the profile, such as
rf.- Returns:
The matching
MeasurementProfile.- Raises:
KeyError – If no profile with this name exists.
- device_id¶
- qcodes_type¶
- parent_ref¶
- pins¶
- measurement_profiles¶
semi_cr.core.station.drivers module¶
- class semi_cr.core.station.drivers.DCDriver[source]¶
Bases:
ABC- abstractmethod set_voltage(voltage: VoltageLike) None[source]¶
Set the voltage of the DC driver.
- get_voltage() VoltageLike[source]¶
Get the current set voltage of the DC driver. This is a readback of a DAC, not a measurement.
semi_cr.core.station.graph module¶
- semi_cr.core.station.graph.graph_attributes(config: Mapping[str, Any]) dict[str, Any][source]¶
Return the explicit graph metadata declared in a YAML config section.
Configuration keys are intentionally not copied wholesale: only values under
attributesbecome graph metadata. This keeps constructor settings such astypeandslotout of the graph namespace.
- class semi_cr.core.station.graph.GraphNode(id: 'str', obj: 'object', kind: 'str', attrs: 'Mapping[str, Any]'=<factory>)[source]¶
Bases:
object
- class semi_cr.core.station.graph.Conduction(*values)[source]¶
Bases:
Flag- DC = 1¶
- AC = 2¶
- __contains__(other)¶
Returns True if self has at least the same flags set as other.
- __iter__()¶
Returns flags in definition order.
- classmethod __getitem__(name)¶
Return the member matching name.
- class semi_cr.core.station.graph.GraphEdge(id: 'str', source: 'str', target: 'str', kind: 'str', attrs: 'Mapping[str, Any]'=<factory>, conducts: 'Conduction' = <Conduction.DC|AC: 3>)[source]¶
Bases:
object- conducts: Conduction = 3¶
- class semi_cr.core.station.graph.Routable(*args, **kwargs)[source]¶
Bases:
ProtocolUse this protocol for anything that can add nodes or edges to the station graph. The idea is that devices export themselves as nodes at least. If they have internal edges that need to exist for the routing to work, they can supply those, too.
- class semi_cr.core.station.graph.Connector(name: str, connections: ~collections.abc.Mapping[str, list[str]], connection_attributes: ~collections.abc.Mapping[str, ~collections.abc.Mapping[str, ~typing.Any]] = <factory>)[source]¶
Bases:
objectImplements a non-QCoDeS variant of semi_cr.core.lab.instrument.connector.Connector, a class representing a junction or set of junctions between two instruments in our setup.
The class is thought to be instantiated using the from_instrument_spec class method, and exposes the
Routableprotocol.- graph_edges() Iterable[GraphEdge][source]¶
Emits graph edges from the connections stored on the Connector element.
- classmethod from_instrument_spec(spec: QCoDeSInstrumentSpec) Connector[source]¶
- semi_cr.core.station.graph.build_node_aliases(graph: Graph) dict[str, str][source]¶
In some config references there seems to be a convention that e.g. tank inductors can be referred to by concatenating the chip ID with the device ID, such as B083004D010033 where B083004D01 is the chip part and 0033 is the device part. When configurations refer to endpoints like this the graph resolver gets confused. So for each device pin we add an alias that we can use when looking up the node to make edges later on.
- semi_cr.core.station.graph.resolve_endpoint_reference(reference: str, aliases: Mapping[str, str]) str[source]¶
Resolve an edge endpoint reference to a canonical graph node ID.
Config strings like
foo[bar]are ambiguous: they may refer to a modeled device pin, or to a wiring terminal. Device-pin aliases are tried first. If no alias matches, the string is treated as a terminal reference. Existinglab://node IDs are already canonical and are returned unchanged.
- class semi_cr.core.station.graph.StationGraph(graph: 'nx.Graph' = <factory>, aliases: 'dict[str, str]'=<factory>)[source]¶
Bases:
object- graph: Graph¶
- opx_source_for_pin(pin: DevicePin) object | None[source]¶
Return the OPX source terminal reachable from a device pin.
- Parameters:
pin – Device pin object with a
node_id.- Returns:
The first reachable OPX source terminal, or
None.
- opx_receiver_for_pin(pin: DevicePin) object | None[source]¶
Return the OPX receiver terminal reachable from a device pin.
- Parameters:
pin – Device pin object with a
node_id.- Returns:
The first reachable OPX receiver terminal, or
None.
- opx_terminal_for_pin(pin: DevicePin, role: object) object | None[source]¶
Return the first OPX terminal with
rolereachable from a device pin.Driver lookup is rooted at the pin and walks the station topology outward. Matching is based on the graph node’s
objrelation, not graph metadata.- Parameters:
pin – Device pin object with a
node_id.role –
OPX1000LFTerminal.Rolemember to match.
- Returns:
The first matching OPX terminal object, or
None.
- dc_driver_for_pin(pin: DevicePin) DCDriver | None[source]¶
Gets the DC driver for a given pin.
It does this by extracting the subgraph that only contains DC-carrying edges, and find a path in that one from the pin to any DCDriver.
- reachable_from_pin(pin: DevicePin) Iterator[object][source]¶
- reachable_from_pin(pin: DevicePin, object_type: type[T], where: Callable[[T], bool] | None = None) Iterator[T]
Iterate over matching hydrated objects reachable from a device pin.
This returns values stored in graph-node
objmetadata, not NetworkX node IDs or node metadata. The starting pin and nodes without anobjvalue are excluded. Omittingobject_typereturns all other reachable hydrated objects.- Parameters:
pin – Device pin from which to start the graph traversal.
object_type – Type of object to return. Defaults to
object.where – Optional predicate applied to objects of
object_type.
- Returns:
Matching objects in breadth-first traversal order.
- classmethod from_routable(routable: Routable) StationGraph[source]¶
Creates a station graph from a Routable object, usually
NQCPStation.Ordering matters: all nodes are created before edges. Edge endpoints may use different names for the same node, so we need the full node set before we can resolve those names to canonical node IDs.
For example, a device pin may be referred to as “B083004D010033[RF_IN]” in one place and “B083004D01/0033[RF_IN]” in another. Before adding the edges exported by the Routable, we build aliases for all device pins and use them to resolve edge sources and targets.
- conducting(signal: Conduction) StationGraph[source]¶
Returns a subgraph of the station graph containing only the edges that conduct the specified signal type.
semi_cr.core.station.helpers module¶
- semi_cr.core.station.helpers.print_station_map(station: NQCPStation)[source]¶
semi_cr.core.station.hydration module¶
Hydration module for the NQCP station configuration. Hydration is what turns our configuration into more “live”-like objects, such as Chip and Connector. It is akin to the QCoDeS way of creating a rich object from the configuration, only here we declare a _handler_ per type, treating the types as regular strings instead of the QCoDeS way of pointing to some class. That allows the two approaches to coexist.
- class semi_cr.core.station.hydration.UnloadedSpec(name: 'str', type: 'str', config: 'Mapping[str, Any]')[source]¶
Bases:
object
- class semi_cr.core.station.hydration.HydratedStationObjects(chips: 'list[Chip]' = <factory>, connectors: 'list[Connector]' = <factory>, instruments: 'list[LabInstrument]' = <factory>, unloaded_specs: 'list[UnloadedSpec]' = <factory>)[source]¶
Bases:
object- instruments: list[LabInstrument]¶
- unloaded_specs: list[UnloadedSpec]¶
- exception semi_cr.core.station.hydration.MissingStaticLoaderError[source]¶
Bases:
Exception- add_note()¶
Exception.add_note(note) – add a note to the exception
- args¶
- with_traceback()¶
Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.
- semi_cr.core.station.hydration.load_chip(spec: InstrumentSpec, station: NQCPStation) Chip[source]¶
- semi_cr.core.station.hydration.load_connector(spec: InstrumentSpec, station: NQCPStation) Connector[source]¶
- semi_cr.core.station.hydration.load_opx1000(spec: InstrumentSpec, station: NQCPStation) OPX1000Blueprint[source]¶
- semi_cr.core.station.hydration.load_spirack(spec: InstrumentSpec, station: NQCPStation) SPIRackBlueprint[source]¶
- semi_cr.core.station.hydration.load_dmm(spec: InstrumentSpec, station: NQCPStation) DMMBlueprint[source]¶
- semi_cr.core.station.hydration.hydrate_station_config(config_bundle: ConfigBundle, station: NQCPStation) HydratedStationObjects[source]¶
- semi_cr.core.station.hydration.hydrate_instrument_spec(spec: InstrumentSpec, station: NQCPStation) object[source]¶
semi_cr.core.station.lifecycle module¶
Independent, retryable attachment state for live laboratory instruments.
- class semi_cr.core.station.lifecycle.AttachmentState(*values)[source]¶
Bases:
StrEnum- DETACHED = 'detached'¶
- ATTACHING = 'attaching'¶
- ATTACHED = 'attached'¶
- DETACHING = 'detaching'¶
- FAILED = 'failed'¶
- __new_member__(*values)¶
values must already be of type str
- encode(encoding='utf-8', errors='strict')¶
Encode the string using the codec registered for encoding.
- encoding
The encoding in which to encode the string.
- errors
The error handling scheme to use for encoding errors. The default is ‘strict’ meaning that encoding errors raise a UnicodeEncodeError. Other possible values are ‘ignore’, ‘replace’ and ‘xmlcharrefreplace’ as well as any other name registered with codecs.register_error that can handle UnicodeEncodeErrors.
- replace(old, new, count=-1, /)¶
Return a copy with all occurrences of substring old replaced by new.
- count
Maximum number of occurrences to replace. -1 (the default value) means replace all occurrences.
If the optional argument count is given, only the first count occurrences are replaced.
- split(sep=None, maxsplit=-1)¶
Return a list of the substrings in the string, using sep as the separator string.
- sep
The separator used to split the string.
When set to None (the default value), will split on any whitespace character (including n r t f and spaces) and will discard empty strings from the result.
- maxsplit
Maximum number of splits. -1 (the default value) means no limit.
Splitting starts at the front of the string and works to the end.
Note, str.split() is mainly useful for data that has been intentionally delimited. With natural text that includes punctuation, consider using the regular expression module.
- rsplit(sep=None, maxsplit=-1)¶
Return a list of the substrings in the string, using sep as the separator string.
- sep
The separator used to split the string.
When set to None (the default value), will split on any whitespace character (including n r t f and spaces) and will discard empty strings from the result.
- maxsplit
Maximum number of splits. -1 (the default value) means no limit.
Splitting starts at the end of the string and works to the front.
- join(iterable, /)¶
Concatenate any number of strings.
The string whose method is called is inserted in between each given string. The result is returned as a new string.
Example: ‘.’.join([‘ab’, ‘pq’, ‘rs’]) -> ‘ab.pq.rs’
- capitalize()¶
Return a capitalized version of the string.
More specifically, make the first character have upper case and the rest lower case.
- casefold()¶
Return a version of the string suitable for caseless comparisons.
- title()¶
Return a version of the string where each word is titlecased.
More specifically, words start with uppercased characters and all remaining cased characters have lower case.
- center(width, fillchar=' ', /)¶
Return a centered string of length width.
Padding is done using the specified fill character (default is a space).
- count(sub[, start[, end]]) int¶
Return the number of non-overlapping occurrences of substring sub in string S[start:end]. Optional arguments start and end are interpreted as in slice notation.
- expandtabs(tabsize=8)¶
Return a copy where all tab characters are expanded using spaces.
If tabsize is not given, a tab size of 8 characters is assumed.
- find(sub[, start[, end]]) int¶
Return the lowest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation.
Return -1 on failure.
- partition(sep, /)¶
Partition the string into three parts using the given separator.
This will search for the separator in the string. If the separator is found, returns a 3-tuple containing the part before the separator, the separator itself, and the part after it.
If the separator is not found, returns a 3-tuple containing the original string and two empty strings.
- index(sub[, start[, end]]) int¶
Return the lowest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation.
Raises ValueError when the substring is not found.
- ljust(width, fillchar=' ', /)¶
Return a left-justified string of length width.
Padding is done using the specified fill character (default is a space).
- lower()¶
Return a copy of the string converted to lowercase.
- lstrip(chars=None, /)¶
Return a copy of the string with leading whitespace removed.
If chars is given and not None, remove characters in chars instead.
- rfind(sub[, start[, end]]) int¶
Return the highest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation.
Return -1 on failure.
- rindex(sub[, start[, end]]) int¶
Return the highest index in S where substring sub is found, such that sub is contained within S[start:end]. Optional arguments start and end are interpreted as in slice notation.
Raises ValueError when the substring is not found.
- rjust(width, fillchar=' ', /)¶
Return a right-justified string of length width.
Padding is done using the specified fill character (default is a space).
- rstrip(chars=None, /)¶
Return a copy of the string with trailing whitespace removed.
If chars is given and not None, remove characters in chars instead.
- rpartition(sep, /)¶
Partition the string into three parts using the given separator.
This will search for the separator in the string, starting at the end. If the separator is found, returns a 3-tuple containing the part before the separator, the separator itself, and the part after it.
If the separator is not found, returns a 3-tuple containing two empty strings and the original string.
- splitlines(keepends=False)¶
Return a list of the lines in the string, breaking at line boundaries.
Line breaks are not included in the resulting list unless keepends is given and true.
- strip(chars=None, /)¶
Return a copy of the string with leading and trailing whitespace removed.
If chars is given and not None, remove characters in chars instead.
- swapcase()¶
Convert uppercase characters to lowercase and lowercase characters to uppercase.
- translate(table, /)¶
Replace each character in the string using the given translation table.
- table
Translation table, which must be a mapping of Unicode ordinals to Unicode ordinals, strings, or None.
The table must implement lookup/indexing via __getitem__, for instance a dictionary or list. If this operation raises LookupError, the character is left untouched. Characters mapped to None are deleted.
- upper()¶
Return a copy of the string converted to uppercase.
- startswith(prefix[, start[, end]]) bool¶
Return True if S starts with the specified prefix, False otherwise. With optional start, test S beginning at that position. With optional end, stop comparing S at that position. prefix can also be a tuple of strings to try.
- endswith(suffix[, start[, end]]) bool¶
Return True if S ends with the specified suffix, False otherwise. With optional start, test S beginning at that position. With optional end, stop comparing S at that position. suffix can also be a tuple of strings to try.
- removeprefix(prefix, /)¶
Return a str with the given prefix string removed if present.
If the string starts with the prefix string, return string[len(prefix):]. Otherwise, return a copy of the original string.
- removesuffix(suffix, /)¶
Return a str with the given suffix string removed if present.
If the string ends with the suffix string and that suffix is not empty, return string[:-len(suffix)]. Otherwise, return a copy of the original string.
- isascii()¶
Return True if all characters in the string are ASCII, False otherwise.
ASCII characters have code points in the range U+0000-U+007F. Empty string is ASCII too.
- islower()¶
Return True if the string is a lowercase string, False otherwise.
A string is lowercase if all cased characters in the string are lowercase and there is at least one cased character in the string.
- isupper()¶
Return True if the string is an uppercase string, False otherwise.
A string is uppercase if all cased characters in the string are uppercase and there is at least one cased character in the string.
- istitle()¶
Return True if the string is a title-cased string, False otherwise.
In a title-cased string, upper- and title-case characters may only follow uncased characters and lowercase characters only cased ones.
- isspace()¶
Return True if the string is a whitespace string, False otherwise.
A string is whitespace if all characters in the string are whitespace and there is at least one character in the string.
- isdecimal()¶
Return True if the string is a decimal string, False otherwise.
A string is a decimal string if all characters in the string are decimal and there is at least one character in the string.
- isdigit()¶
Return True if the string is a digit string, False otherwise.
A string is a digit string if all characters in the string are digits and there is at least one character in the string.
- isnumeric()¶
Return True if the string is a numeric string, False otherwise.
A string is numeric if all characters in the string are numeric and there is at least one character in the string.
- isalpha()¶
Return True if the string is an alphabetic string, False otherwise.
A string is alphabetic if all characters in the string are alphabetic and there is at least one character in the string.
- isalnum()¶
Return True if the string is an alpha-numeric string, False otherwise.
A string is alpha-numeric if all characters in the string are alpha-numeric and there is at least one character in the string.
- isidentifier()¶
Return True if the string is a valid Python identifier, False otherwise.
Call keyword.iskeyword(s) to test whether string s is a reserved identifier, such as “def” or “class”.
- isprintable()¶
Return True if the string is printable, False otherwise.
A string is printable if all of its characters are considered printable in repr() or if it is empty.
- zfill(width, /)¶
Pad a numeric string with zeros on the left, to fill a field of the given width.
The string is never truncated.
- format(*args, **kwargs) str¶
Return a formatted version of S, using substitutions from args and kwargs. The substitutions are identified by braces (‘{’ and ‘}’).
- format_map(mapping) str¶
Return a formatted version of S, using substitutions from mapping. The substitutions are identified by braces (‘{’ and ‘}’).
- static maketrans()¶
Return a translation table usable for str.translate().
If there is only one argument, it must be a dictionary mapping Unicode ordinals (integers) or characters to Unicode ordinals, strings or None. Character keys will be then converted to ordinals. If there are two arguments, they must be strings of equal length, and in the resulting dictionary, each character in x will be mapped to the character at the same position in y. If there is a third argument, it must be a string, whose characters will be mapped to None in the result.
- __dir__()¶
Returns public methods and other interesting attributes.
- class semi_cr.core.station.lifecycle.InstrumentSnapshot(name: 'str', state: 'AttachmentState', error: 'str | None', revision: 'int')[source]¶
Bases:
object- state: AttachmentState¶
- class semi_cr.core.station.lifecycle.InstrumentHandle(name: str, attach: Callable[[], ResourceT], detach: Callable[[ResourceT], None])[source]¶
Bases:
GenericOwn one live resource without allowing its failure to escape startup.
Calls can be synchronous for scripts/tests or run on daemon threads for a GUI. A generation counter makes an attach result stale when detach is requested while the connection attempt is still in flight.
- property snapshot: InstrumentSnapshot¶
- property has_resource: bool¶
Whether a resource still needs releasing, including after a failed detach.
- attach() InstrumentSnapshot[source]¶
- detach() InstrumentSnapshot[source]¶
- mark_failed(error: Exception | str) InstrumentSnapshot[source]¶
Invalidate a live resource after a runtime communication failure.
semi_cr.core.station.manifest module¶
- class semi_cr.core.station.manifest.NQCPStationManifest(manifest_path: Path)[source]¶
Bases:
objectHelper class for loading a station manifest. The main value proposition is that we don’t leak to the callers how the manifest is encoded (TOML) or where it’s stored.
The TOML manifest station.toml has three sections of interest; wiring, electronics, and device. Each section has a files key that lists the configuration files to load for that section. Besides that it carries a few keys at the top level, like name.
The device section contains a list of files describing individual chips (and the devices on these chips). Moreover it has a loaded_chip_id key that indicates which chip is currently loaded in the station.
- manifest_path: Path¶
- basedir: Path¶
- get_config_bundle() ConfigBundle[source]¶
semi_cr.core.station.measurement_context module¶
- class semi_cr.core.station.measurement_context.NQCPStationMeasurementContext(station: NQCPStation)[source]¶
Bases:
objectNQCPStationmakes an object like this for wrapping a measurement of some type. It connects to the relevant instruments. In the future this would also be the place for some telemetry or automated aggregation of data.- station: NQCPStation¶
- connect(instrument_name: str) Instrument[source]¶
Just s stub for now: Connect to a live instrument by name.
This method is intended to be used within the context of a with statement, ensuring that the instrument is properly managed and disconnected when no longer needed.
semi_cr.core.station.plotting module¶
- class semi_cr.core.station.plotting.StationGraphPlotter(station_graph: StationGraph)[source]¶
Bases:
objectPlots a
StationGraphin columns: device pins on the left, sources towards the right.Usage:
StationGraphPlotter(station.graph).plot() StationGraphPlotter(station.graph).chip_and_drivers().merge_boards().plot() # debug severed AC/DC paths
- station_graph: StationGraph¶
- chip_and_drivers() StationGraphPlotter[source]¶
Keep only wiring connected to a device pin or to an AC/DC driver.
A driver whose wiring never reaches the chip ends up in the last column, so a severed path shows as a pin marked missing AC/DC on the left and a dangling driver on the right.
- merge_boards() StationGraphPlotter[source]¶
Draw each board channel and the connector pins it is traced to as a single row.
A board’s own connectors are recognised by name:
fbrd_1_ffc_J2belongs to boardfbrd_1. The traces between a board and its connectors reshuffle line order, which causes crossings no layout can remove, so every set of nodes joined by board traces is contracted into one node. It keeps the board-side node’s ID (and data) and lists the IDs it absorbed undermerged.
- pin_status(node_id: str) tuple[bool, bool][source]¶
Whether a device pin reaches an AC (OPX source) and a DC driver, by the same lookup the pins use.
- groups() dict[str, list[str]][source]¶
Node IDs grouped by parent, e.g.
lab://terminal/opx1000_1/LF_1orlab://pin/TestChip/D1.Groups and their members are in
_discovery_rank()order.
- columns() list[list[str]][source]¶
Group names per column, laid out so every wire between groups points from the chip towards the electronics.
Groups are ordered by how close they get to a device pin (in hops), and every wire is directed from the closer group to the farther one. Each group then goes one column right of the furthest group wired into it (longest-path layering), so no wire runs vertically or backwards. Wiring not connected to the chip is ordered by closeness to a driver instead and right-aligned, so a severed path shows as a stub hanging off the electronics side.
- crossings(pos: Mapping[str, tuple[float, float]]) int[source]¶
Count edge crossings between adjacent columns for a layout. Edges skipping a column are not counted.
- layout(sweeps: int = 10) dict[str, tuple[float, float]][source]¶
Compute node positions in
columns(), with each group drawn as a block of consecutive nodes.Crossings are reduced with the layered (Sugiyama) barycenter heuristic, applied to groups as blocks: each column is re-sorted by the mean height of its neighbours in the column before it (left-to-right sweep) and then after it (right-to-left sweep). Groups move as a whole, and nodes are re-sorted only inside their group. The layout with the fewest
crossings()is returned.- Parameters:
sweeps – Number of left-to-right plus right-to-left sweep pairs.
- Returns:
Mapping from node ID to
(x, y).
- plot() go.Figure[source]¶
Draw each parent group as a labelled box, with edges coloured by kind (physical/device).
Hover a node for its full ID and, for device pins, whether it reaches an AC/DC driver. Call
.show()on the result to open it in a browser (config={"scrollZoom": True}enables mouse-wheel zoom).
- show(path: str | None = None) str[source]¶
Write
plot()to an HTML file and open it in the browser.Click a node to highlight all wiring connected to it (e.g. a pin’s path to its drivers) and fade the rest; double-click to reset. Scroll to zoom, drag to pan.
- Parameters:
path – Where to write the HTML. Defaults to a temporary file.
- Returns:
The path written.
semi_cr.core.station.station module¶
- class semi_cr.core.station.station.NQCPStation(manifest: str | Path | NQCPStationManifest)[source]¶
Bases:
objectSets up a station handler, given a manifest. In the constructor we establish an object-oriented model of the station constituents, meaning instruments, wiring and the quantum device model as well.
- manifest: NQCPStationManifest¶
- config: ConfigBundle¶
- instruments: list[LabInstrument]¶
- unloaded_specs: list[UnloadedSpec]¶
- graph: StationGraph¶
- get_chip(chip_id: str | None = None) Chip[source]¶
Gets a chip by name.
- Returns:
The chip matching
chip_id, or the loaded chip when omitted.- Raises:
KeyError – If no matching chip exists.
- property device: QuantumDevice¶
- get_device(device_id: str | None = None) QuantumDevice[source]¶
Gets a device on the loaded chip.
- Returns:
The named device, or the only device on the loaded chip when omitted.
- Raises:
ValueError – If
device_idis omitted and the loaded chip has multiple devices.
- get_gates(device_id: str | None = None) list[Gate][source]¶
Gets gates on the station.
- Returns:
All gates, or gates on
device_idwhen provided.
- get_instruments_of_type(instrument_type: type[StaticInstrumentT], *, name: str | None = None) list[StaticInstrumentT][source]¶
Gets static instruments matching
instrument_typeand optionalname.
- get_instrument_of_type(instrument_type: type[StaticInstrumentT], *, name: str | None = None) StaticInstrumentT[source]¶
Gets exactly one static instrument matching
instrument_typeand optionalname.- Raises:
LookupError – If zero or multiple instruments match.
- gate(gate_name: str) Gate[source]¶
Gets a gate by name. This is kind of a placeholder method because it kind of glosses over the fact that a station may contain more than one chip with more than one device, and so a gate name can’t be considered a unique property.
- Returns:
The gate matching the requested name
- Raises:
KeyError if the gate doesn’t exist
- Raises:
ValueError if there is more than one gate with that name
- classmethod available_stations() dict[str, NQCPStationManifest][source]¶
Finds setup manifests under semi_cr.setup.
- classmethod get(name: str) NQCPStation[source]¶
Load a station description without connecting to hardware.
semi_cr.core.station.units module¶
- semi_cr.core.station.units.as_volts(value: VoltageLike) float[source]¶
Converts to volts. Strings are parsed by pint, e.g. “20 mV”; bare numbers are taken as volts.