Source code for semi_cr.core.lab.instrument.pcb

from qcodes.instrument import Instrument
from typing import Literal, Sequence, Any
from dataclasses import dataclass, field
import networkx as nx


from semi_cr.core.lab.station.graphing.models import Node, Edge
from semi_cr.core.lab.station.graphing.ids import (
    instrument_connection_node_id,
    instrument_node_id,
    instrument_module_node_id,
    terminal_node_id,
)
from semi_cr.core.lab.station.graphing.operations import build_nx_graph
from semi_cr.core.lab.station.graphing.runtime_builder import build_connection_graph_for_instrument

[docs] @dataclass class PCBLine: name: str kind: Literal["dc", "rf", "ac"] pin_type: str | None = None pads: list[str] = field(default_factory=list)
[docs] class PCB(Instrument): """Generic passive PCB / daughterboard with named electrical lines.""" def __init__( self, name: str, version: str | None = None, lines: dict[str, PCBLine] | None = None, ) -> None: super().__init__(name, metadata={}, label="pcb") self.version = version self.lines = lines or {}
[docs] def get_idn(self) -> dict[str, str | None]: """ Override Instrument.get_idn so QCoDeS never calls self.ask('*IDN?'). """ return { "vendor": None, "model": self.name, "serial": None, "firmware": None }
[docs] class RoutedPCB(PCB): def __init__( self, name: str, version: str | None = None, lines: dict[str, PCBLine] | None = None, connections: Sequence[dict[str, Any]] = (), ) -> None: super().__init__(name=name, version=version, lines=lines) self.connections = list(connections) @property def graph(self) -> nx.MultiDiGraph: def build_pcb_graph( pcb: PCB, parent_id: str | None = None, ) -> nx.MultiDiGraph: nodes: list[Node] = [] edges: list[Edge] = [] if parent_id is None: pcb_id = instrument_node_id(pcb.name) pcb_kind = "instrument" else: pcb_id = instrument_module_node_id(parent_id, pcb.name) pcb_kind = "instrument_module" nodes.append( Node( id=pcb_id, kind=pcb_kind, name=pcb.name, obj=pcb, ) ) for line_name, line in pcb.lines.items(): line_id = instrument_connection_node_id( pcb.name, line_name, ) nodes.append( Node( id=line_id, kind="pcb_line", name=line_name, obj=line, ) ) edges.append( Edge( source=pcb_id, target=line_id, kind="contains", ) ) for pad in line.pads: pad_id = terminal_node_id( pcb.name, pad, ) nodes.append( Node( id=pad_id, kind="terminal", name=pad, obj=None, ) ) edges.extend( [ Edge( source=line_id, target=pad_id, kind="contains", ), Edge( source=pad_id, target=line_id, kind="dependency", ), ] ) return build_nx_graph(nodes, edges) pcb_graph = build_pcb_graph(self) connection_graph = build_connection_graph_for_instrument( self, self.connections, ) graph = nx.compose(pcb_graph, connection_graph) return graph