API Reference¶
This page documents the public API of simpleLOMs.
Package¶
Simple Lumped Oscillator Models for superconducting quantum device design.
- class simpleLOMs.AnalyticalFit(mode: int = 2)[source]¶
Bases:
BaseFitLumped LC model via the closed-form λ/2 CPW approximation.
- Parameters:
mode (int, optional) – Resonance mode number (default 2 for the fundamental λ/2 mode). The formula C_r = m·π / (2·ω_r·Z0) generalises to higher modes.
Examples
from simpleLOMs.models.analytical import AnalyticalFit import skrf as rf freq = rf.Frequency(4e9, 10e9, 10_001, unit="Hz") model = AnalyticalFit() # Provide f_r and Z0 directly — no network needed model.fit(freq, f_r=8.581e9, Z0=45.926) print(model.get_params()) # {'L': 5.55e-10, 'C': 6.18e-13, 'f_r_Hz': 8.581e9, 'Z0': 45.926} net = model.get_network(freq, Cc1=5e-15, Cc2=5e-15, Ctog1=1e-14, Ctog2=1e-14)
- fit(freq: Frequency, f_r: float, Z0: float, **kwargs) None[source]¶
Compute L and C from the closed-form λ/2 approximation.
- get_network(freq: Frequency, Cc1: float, Cc2: float, Z0: float = 50.0, with_grounds: bool = True, Ctog1: float = None, Ctog2: float = None, **kwargs) Network[source]¶
Build the 2-port LC LOM network from the analytical L and C.
- Parameters:
freq (rf.Frequency)
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Z0 (float) – Reference impedance in Ohms.
with_grounds (bool) – If True (default), include Ctog shunt capacitors. The analytical model is typically compared alongside the full CPW topology so including the grounds is more representative.
Ctog1 (float or None) – Required when with_grounds=True.
Ctog2 (float or None) – Required when with_grounds=True.
- Return type:
rf.Network
- class simpleLOMs.CPWParams(w: float = 1.17e-05, s: float = 5.1e-06, t: float = 0.0, h: float = 0.0005, rho: float = 1e-19, ep_r: float = 11.45, has_metal_backside: bool = False, tand: float = 0.0)[source]¶
Bases:
objectPhysical geometry and material parameters for a Coplanar Waveguide (CPW).
- t¶
Metal thickness (m). Set to 0 to ignore (for an ideal thin film). This quantity is generally on the order of 100-200 nm.
- Type:
Examples
- Use the defaults (ultracold silicon chip):
>>> cpw = CPWParams()
- Override just the substrate:
>>> cpw = CPWParams(ep_r=11.9, has_metal_backside=False)
- Pass into a network builder:
>>> net = cpw_resonator_network_2port(freq, d=7e-3, cpw_params=cpw, ...)
- class simpleLOMs.FosterFit(cpw_params: CPWParams = None, port_z0: float = 500.0)[source]¶
Bases:
BaseFitLumped LC model via Foster admittance synthesis on a bare CPW line.
- Parameters:
cpw_params (CPWParams, optional) – Physical geometry and material parameters for the CPW. Uses default CPWParams() (11.7 µm / 5.1 µm gap, ultracold Si) if not provided.
port_z0 (float, optional) – Port impedance used when building the bare CPW network for synthesis. Default 500 Ω (high impedance → weakly loaded line, closer to the unloaded resonator condition).
- yin¶
Complex input admittance array computed during fit(). Stored for diagnostics / plotting without recomputing.
- Type:
np.ndarray or None
Examples
Basic usage:
from simpleLOMs.params import CPWParams from simpleLOMs.models.foster import FosterFit import skrf as rf freq = rf.Frequency(4e9, 10e9, 10_001, unit="Hz") cpw = CPWParams(ep_r=11.45) model = FosterFit(cpw_params=cpw) model.fit(freq, d=7e-3) print(model.get_params()) # {'L': 5.53e-10, 'C': 6.22e-13, 'f0_Hz': 8.58e9} net = model.get_network(freq, Cc1=5e-15, Cc2=5e-15, Ctog1=1e-14, Ctog2=1e-14)
- fit(freq: Frequency, d: float, **kwargs) None[source]¶
Run Foster synthesis on a bare CPW line of length d.
Computes the input admittance Yin(ω), finds ω0 from a peak in Im(S22), then extracts C_eq from the admittance slope and L_eq from the resonance constraint ω0² L C = 1.
- Parameters:
freq (rf.Frequency) – Frequency sweep. Should span at least one resonance of the bare CPW line at length d.
d (float) – Physical resonator length in metres.
**kwargs – Ignored — included for a consistent BaseFit interface.
- get_network(freq: Frequency, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, Z0: float = 50.0, **kwargs) Network[source]¶
Build the 2-port LC LOM network using the Foster-synthesised L and C.
Uses the “with grounds” topology so that Ctog1/Ctog2 are included, matching the structure of the CPW model that was synthesised.
- Parameters:
freq (rf.Frequency) – May differ from the freq used in fit().
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port LC network with ground capacitors.
- Return type:
rf.Network
- class simpleLOMs.OptimizationConfig(w0_window_frac: float = 1e-05, n_w0: int = 20, n_dense: int = 100, n_kappa: float = 0.75, n_widths: float = 1.0, max_nfev: int = 100, verbose: bool = False, fit_phase: bool = False, s_params: Sequence[str] = <factory>, weights: dict[str, float] | None=None)[source]¶
Bases:
objectTuning knobs for the two-stage OptimizedFit algorithm.
Core algorithm knobs¶
- w0_window_fracfloat
Half-width of the ω0 scan window as a fraction of ω0_guess.
- n_w0int
Number of ω0 grid points in the coarse scan.
- n_denseint
Number of data points sampled around resonance in Stage 1.
- n_kappafloat
Half-width of the dense sampling window in units of κ (linewidth).
- n_widthsfloat
Half-width of each residual window in Stage 2, in units of κ.
- max_nfevint
Maximum function evaluations for the Stage 2 least_squares call.
- verbosebool
If True, least_squares prints iteration progress.
Residual configuration¶
- fit_phasebool
If True, a global scalar phase φ is added to the free parameters so that the model prediction is e^{i·φ} · S_model. The fitted phase is stored in OptimizedFit.phase (radians) after fit().
- s_paramssequence of str
Which S-parameter channels to include in Stage 2. Any non-empty subset of {“S11”, “S22”, “S21”, “S12”}. Default: (“S11”, “S22”).
- weightsdict[str, float] or None
Manual per-channel weight multipliers applied after depth normalisation. None → equal weights (all 1.0). Example: {“S11”: 2.0, “S22”: 2.0, “S21”: 1.0}
- class simpleLOMs.OptimizedFit(config: OptimizationConfig = None)[source]¶
Bases:
BaseFitLumped LC model via two-stage numerical optimisation.
- Parameters:
config (OptimizationConfig, optional) – Hyperparameters and residual options. Defaults to OptimizationConfig() (S11 + S22, no phase fitting).
- phase¶
Fitted global phase in radians. None if config.fit_phase is False or before fit() is called.
- Type:
float or None
- scan_results¶
Diagnostic array from the Stage 1 ω0 scan, shape (n_w0, 4): columns are [ω0, Ceff, Leff, sse].
- Type:
np.ndarray or None
Examples
from simpleLOMs.models.optimized_fit import OptimizedFit, OptimizationConfig # Fit using only S21, with phase as a free parameter cfg = OptimizationConfig(s_params=["S21"], fit_phase=True) model = OptimizedFit(config=cfg) model.fit(freq, data_ntw=cpw_net, Cc1=3e-14, Cc2=7e-14, Ctog1=4e-14, Ctog2=6e-14, d=7e-3, cpw_params=cpw_params, Z0=50) print(model) # OptimizedFit(L=…, C=…, phase=…) net = model.get_network(freq, Cc1=3e-14, Cc2=7e-14, Z0=50)
- config: OptimizationConfig¶
- fit(freq: Frequency, data_ntw: Network, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, d: float, cpw_params, Z0: float = 50.0, **kwargs) None[source]¶
Two-stage optimisation to fit Leff, Ceff (and optionally phase) to data_ntw.
- Stage 1: coarse Nelder-Mead scan over ω0, constrained Ceff.
Uses an explicitly constructed 1-port CPW network so that the Stage 1 data points come from a true single-port reflection measurement rather than a 2-port S11 view.
- Stage 2: windowed least_squares refinement on the channels specified
in config.s_params.
- Parameters:
freq (rf.Frequency) – Frequency grid for the optimisation (should be centred on the resonance with enough bandwidth to capture the linewidth).
data_ntw (rf.Network) – 2-port reference network (CPW model or measured data).
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
d (float) – Resonator length in metres.
cpw_params (CPWParams) – CPW geometry parameters.
Z0 (float) – Reference impedance in Ohms.
- get_network(freq: Frequency, Cc1: float, Cc2: float, Z0: float = 50.0, with_grounds: bool = False, Ctog1: float = None, Ctog2: float = None, shifted: bool = False, **kwargs) Network[source]¶
Build the 2-port LC LOM network from the optimised L and C.
Note: the optional fitted phase is not applied here because it is a calibration correction for the data, not a physical property of the LC network. Apply it separately if you need to compare against phase-corrected data:
net_s = net.s * np.exp(1j * model.phase)
- Parameters:
freq (rf.Frequency)
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Z0 (float) – Reference impedance in Ohms.
with_grounds (bool) – If True, include Ctog1/Ctog2 shunt caps.
Ctog1 (float or None) – Required when with_grounds=True.
Ctog2 (float or None) – Required when with_grounds=True.
- Return type:
rf.Network
- class simpleLOMs.SweepConfig(cpw_params: CPWParams, freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, Z0: float = 50.0, analytical_Z0: float | None = None, opt_config: OptimizationConfig | None = None)[source]¶
Bases:
objectA complete snapshot of a device and its operating conditions.
Every parameter that any sweep might want to vary is a field here. The sweep machinery calls dataclasses.replace(config, field=new_value) to create a modified copy at each sweep point — the original is never mutated.
- Parameters:
cpw_params (CPWParams) – Physical geometry of the CPW line.
freq (rf.Frequency) – Frequency sweep used for network construction. Should be wide enough to contain all resonances of interest.
d (float) – Resonator length in metres.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
Lload1 (float) – Inductance (H) and capacitance (F) of the load on port 1 side.
Cload1 (float) – Inductance (H) and capacitance (F) of the load on port 1 side.
Lload2 (float) – Inductance (H) and capacitance (F) of the load on port 2 side.
Cload2 (float) – Inductance (H) and capacitance (F) of the load on port 2 side.
Z0 (float) – Reference impedance in Ohms (default 50 Ω).
analytical_Z0 (float or None) – Characteristic impedance used in the AnalyticalFit formula. If None, Z0 is used.
opt_config (OptimizationConfig or None) – Hyperparameters for OptimizedFit. Uses defaults if None.
Examples
Creating a base config:
base = SweepConfig( cpw_params=CPWParams(), freq=rf.Frequency(4e9, 12e9, 10_001, unit="Hz"), d=7e-3, Cc1=5e-15, Cc2=5e-15, Ctog1=1e-14, Ctog2=1e-14, Lload1=5e-10, Cload1=6e-13, Lload2=5e-10, Cload2=6e-13, )
Manually overriding one field:
longer = dataclasses.replace(base, d=9e-3)
- freq: Frequency¶
- opt_config: OptimizationConfig | None = None¶
- simpleLOMs.analyze_system(freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, cpw_params: CPWParams | None = None, Z0: float = 50.0, analytical_f_r: float | None = None, analytical_Z0: float | None = None, opt_config: OptimizationConfig | None = None, verbose: bool = False, shifted: bool = False) dict[source]¶
Compare FosterFit, OptimizedFit, and AnalyticalFit against a CPW reference.
Uses reflection circle fits on S11 and S22 for f0 and kappa extraction.
- simpleLOMs.analyze_system_load_grid(*, freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, load1_freqs_hz: ndarray, load2_freqs_hz: ndarray, cpw_params: CPWParams | None = None, Z0: float = 50.0, analytical_Z0: float | None = None, opt_config: OptimizationConfig | None = None, verbose: bool = False, shifted: bool = False, Cload1_fixed: float = 6e-13, Cload2_fixed: float = 6e-13) dict[source]¶
- simpleLOMs.run_accuracy_sweep(sweep_params: dict, fixed_params: dict, save_path: str | None = None, skip_errors: bool = True, verbose: bool = True) list[source]¶
Run analyze_system() over a grid of parameter combinations.
- simpleLOMs.run_accuracy_sweep_load_grid(*, sweep_params: dict, fixed_params: dict, load1_freqs_hz: ndarray, load2_freqs_hz: ndarray, save_path: str | None = None, skip_errors: bool = True, verbose: bool = True, n_jobs: int = 1) list[source]¶
- simpleLOMs.sweep(param: str, values: ndarray, base_config: SweepConfig, extract: list[str], model: str = 'cpw', refit: bool | None = None) DataFrame[source]¶
Sweep a single parameter across a range of values and extract quantities.
At each sweep point, the chosen model is either rebuilt from scratch (for CPW or when the swept parameter changes L/C) or reuses the L/C fitted at the first sweep point (for Cc, Ctog, and load parameters).
- Parameters:
param (str) – Name of the SweepConfig field to vary. Must be an attribute of SweepConfig, e.g. “d”, “Cc1”, “Cc2”, “Ctog1”, “Lload1”, “Cload1”. Use “Lload1_Lload2” or “Cload1_Cload2” to sweep both loads together.
values (np.ndarray) – Array of values for the swept parameter.
base_config (SweepConfig) – Fixed device state. Not mutated.
Quantities to compute at each sweep point. Supported values:
”f0_s11”
S11 resonance frequency (GHz)
”f0_s22”
S22 resonance frequency (GHz)
”kappa_s11”
S11 linewidth / FWHM (MHz)
”kappa_s22”
S22 linewidth / FWHM (MHz)
”Q_s11”
Quality factor from S11 = f0 / kappa
”Q_s22”
Quality factor from S22
model (str) – Which model to use: “cpw” (default), “foster”, “optimized”, or “analytical”.
refit (bool or None) – Whether to re-fit the LC model at every sweep point. None (default) means automatic: refit when sweeping a parameter in {d, cpw_params}, reuse L/C otherwise. Setting refit=True forces refitting at every point (slower but safer when sweeping Cc1/Cc2 with OptimizedFit). Setting refit=False always reuses the first-point L/C (fastest).
- Returns:
One row per sweep point. Columns are the swept parameter value plus all requested extract quantities.
- Return type:
pd.DataFrame
Examples
Sweep resonator length with CPW ground truth:
df = sweep("d", np.linspace(5e-3, 10e-3, 20), base, extract=["f0_s11", "kappa_s11"])
Sweep coupling cap with FosterFit (reuses L/C — fast):
df = sweep("Cc1", np.linspace(1e-15, 20e-15, 30), base, extract=["f0_s11", "kappa_s11", "Q_s11"], model="foster")
- simpleLOMs.sweep_coupling(Cc_values: ndarray, base_config: SweepConfig, extract: list[str] = None, model: str = 'cpw', symmetric: bool = True, refit: bool = False) DataFrame[source]¶
Sweep coupling capacitor(s).
- Parameters:
Cc_values (np.ndarray) – Array of coupling capacitance values in Farads.
base_config (SweepConfig)
extract (list of str, optional) – Defaults to [“f0_s11”, “kappa_s11”, “Q_s11”] if not provided.
model (str) – “cpw” (default), “foster”, “optimized”, or “analytical”.
symmetric (bool) – If True (default), sweeps Cc1 and Cc2 together. If False, sweeps only Cc1 and leaves Cc2 fixed.
refit (bool) – Whether to re-fit the LC model at every point. Default False because Cc does not change L or C — reusing is valid and fast. Set to True if you suspect OptimizedFit is sensitive to Cc during Stage 1 (unlikely but possible for very asymmetric coupling).
- Returns:
Columns: “Cc” (the swept value), plus all extract quantities.
- Return type:
pd.DataFrame
- simpleLOMs.sweep_length(d_values: ndarray, base_config: SweepConfig, extract: list[str] = None, model: str = 'cpw') DataFrame[source]¶
Sweep resonator length d.
Always refits the model at every point because d directly sets L and C.
- Parameters:
d_values (np.ndarray) – Array of resonator lengths in metres.
base_config (SweepConfig)
extract (list of str, optional) – Defaults to [“f0_s11”, “kappa_s11”] if not provided.
model (str) – “cpw” (default), “foster”, “optimized”, or “analytical”.
- Returns:
Columns: “d”, plus all extract quantities.
- Return type:
pd.DataFrame
- simpleLOMs.sweep_load_frequency(f_load_values: ndarray, base_config: SweepConfig, extract: list[str] = None, model: str = 'cpw', side: str = 'both', load_impedance: float = 50.0, refit: bool = False) DataFrame[source]¶
Sweep the bare load resonance frequency.
Converts each target frequency to a (L, C) pair by fixing the load characteristic impedance Z_load = sqrt(L/C), then sweeping C = 1/(ω²L).
- Parameters:
f_load_values (np.ndarray) – Array of target load resonance frequencies in Hz.
base_config (SweepConfig)
extract (list of str, optional) – Defaults to [“f0_s11”, “shift_mode1”, “shift_mode2”, “shift_mode3”].
model (str) – “cpw” (default), “foster”, “optimized”, or “analytical”.
side ({"both", "1", "2"}) – Which load to sweep. “both” sweeps load 1 and load 2 together (useful when the two loads are identical, e.g. symmetric qubits).
load_impedance (float) – Characteristic impedance of the load resonator in Ohms. Used to fix L from Z_load = sqrt(L/C) → L = Z_load / ω₀. Default 50 Ω.
refit (bool) – Whether to re-fit the LC model at every point. Default False.
- Returns:
Columns: “f_load_GHz” (the swept load frequency in GHz), “Lload” (H), “Cload” (F), plus all extract quantities.
- Return type:
pd.DataFrame
Parameters¶
params.py¶
Shared parameter dataclasses used across simpleLOMs.
Here we define CPWParams once. Every function that needs CPW geometry accepts a single CPWParams.
- class simpleLOMs.params.CPWParams(w: float = 1.17e-05, s: float = 5.1e-06, t: float = 0.0, h: float = 0.0005, rho: float = 1e-19, ep_r: float = 11.45, has_metal_backside: bool = False, tand: float = 0.0)[source]¶
Bases:
objectPhysical geometry and material parameters for a Coplanar Waveguide (CPW).
- t¶
Metal thickness (m). Set to 0 to ignore (for an ideal thin film). This quantity is generally on the order of 100-200 nm.
- Type:
Examples
- Use the defaults (ultracold silicon chip):
>>> cpw = CPWParams()
- Override just the substrate:
>>> cpw = CPWParams(ep_r=11.9, has_metal_backside=False)
- Pass into a network builder:
>>> net = cpw_resonator_network_2port(freq, d=7e-3, cpw_params=cpw, ...)
System¶
system.py¶
Top-level orchestration: runs all three fitting methods and compares them against the CPW reference network using reflection circle fits.
- simpleLOMs.system.analyze_system(freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, cpw_params: CPWParams | None = None, Z0: float = 50.0, analytical_f_r: float | None = None, analytical_Z0: float | None = None, opt_config: OptimizationConfig | None = None, verbose: bool = False, shifted: bool = False) dict[source]¶
Compare FosterFit, OptimizedFit, and AnalyticalFit against a CPW reference.
Uses reflection circle fits on S11 and S22 for f0 and kappa extraction.
- simpleLOMs.system.analyze_system_cf(freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, cpw_params: CPWParams | None = None, Z0: float = 50.0, analytical_f_r: float | None = None, analytical_Z0: float | None = None, opt_config: OptimizationConfig | None = None, verbose: bool = False, shifted: bool = False) dict¶
Compare FosterFit, OptimizedFit, and AnalyticalFit against a CPW reference.
Uses reflection circle fits on S11 and S22 for f0 and kappa extraction.
Analysis¶
analysis.py¶
Pure numerical analysis functions for extracting resonance frequencies and linewidths from S-parameter networks.
None of these functions build networks or do optimization — they only inspect existing rf.Network objects. This makes them easy to test independently and reuse across models.
- simpleLOMs.analysis.circle_fit_f0_kappa(ntwk: Network, m: int = 0, n: int = 0, smooth_window: int | None = 51, smooth_polyorder: int = 3) tuple[float, float][source]¶
Extract resonance frequency (f0) and linewidth (kappa) from a circle fit to S[m,n] in the complex plane (reflection S11/S22).
- Returns:
f0 (float) – Resonance frequency in Hz.
kappa (float) – Linewidth (FWHM of the angular velocity peak) in Hz.
- simpleLOMs.analysis.circle_fit_modes(ntwk: Network, m: int = 0, n: int = 0, n_modes: int = 3, prominence: float = None, min_spacing_hz: float = None, smooth_window: int | None = 51, smooth_polyorder: int = 3) tuple[ndarray, ndarray][source]¶
Find multiple resonance modes in S[m,n] using the reflection circle fit.
- Returns:
f0s (np.ndarray) – Mode frequencies in Hz, length n_modes (NaN-padded).
kappas (np.ndarray) – Mode linewidths in Hz, length n_modes (NaN-padded).
- simpleLOMs.analysis.fwhm_from_res11(ntwk: Network) float[source]¶
Linewidth from zero crossings of Re(S11).
Re(S11) crosses zero at the two half-power frequencies of the resonance. Uses linear interpolation between samples for accuracy.
- Parameters:
ntwk (rf.Network)
- Returns:
Linewidth (distance between the two zero crossings) in Hz.
- Return type:
- Raises:
ValueError – If fewer than two zero crossings are found.
- simpleLOMs.analysis.fwhm_from_trace_db(ntwk: Network, m: int = 0, n: int = 0, kind: str = 'dip', smooth: int = None) float[source]¶
Full-Width at Half Maximum (FWHM) from S-parameter magnitude in dB.
Uses crossing-interpolation to find the two frequencies where the magnitude crosses the half-depth level, giving a more accurate result than a pure index-based approach.
- Parameters:
ntwk (rf.Network)
m (int) – S-parameter indices (0-based).
n (int) – S-parameter indices (0-based).
kind ({"dip", "peak"}) – “dip” — resonance appears as a downward dip (typical for S11/S22). “peak” — resonance appears as an upward peak (typical for S12/S21).
smooth (int or None) – Optional moving-average window length for noisy traces. Use an odd integer; None disables smoothing.
- Returns:
FWHM linewidth in Hz.
- Return type:
- Raises:
ValueError – If two crossings at the half-depth level cannot be found.
- simpleLOMs.analysis.resonance(ntwk: Network, m: int = 0, n: int = 0, use_max: bool = False, method: str = 'min_re') float[source]¶
Estimate resonance frequency from S[m,n].
- Parameters:
ntwk (rf.Network)
m (int) – S-parameter indices (0-based).
n (int) – S-parameter indices (0-based).
use_max (bool) – Only used for method=’min_re’. If True, find frequency of maximum Re(S) instead of minimum.
method (str) –
- Resonance estimator. Supported:
’min_re’ : min/max of Re(S)
’circle_fit’ : circle fit in complex plane
- Returns:
Resonance frequency in Hz.
- Return type:
- simpleLOMs.analysis.resonance_circle_fit(ntwk: Network, m: int = 0, n: int = 0, smooth_window: int | None = 51, smooth_polyorder: int = 3) float[source]¶
Estimate resonance frequency from a circle fit to S[m,n] in the complex plane.
Strategy¶
Fit a circle to the complex trace S[m,n](f).
Compute the angle of each point about the fitted center.
Take the frequency where |d(theta)/df| is largest.
This is usually a good reflection-based estimator for S11/S22.
- param ntwk:
- type ntwk:
rf.Network
- param m:
S-parameter indices.
- type m:
int
- param n:
S-parameter indices.
- type n:
int
- param smooth_window:
Optional Savitzky-Golay smoothing window for theta before differentiation. Must be odd if provided.
- type smooth_window:
int or None
- param smooth_polyorder:
Polynomial order for Savitzky-Golay smoothing.
- type smooth_polyorder:
int
- returns:
Resonance frequency in Hz.
- rtype:
float
- simpleLOMs.analysis.resonance_from_res11(ntwk: Network) float[source]¶
Resonance frequency from the minimum of Re(S11).
Thin convenience wrapper around resonance for the common single-port S11 case.
- Parameters:
ntwk (rf.Network)
- Returns:
Resonance frequency in Hz.
- Return type:
- simpleLOMs.analysis.resonance_from_s_max(network: Network, m: int = 0, n: int = 0) float[source]¶
Resonance frequency from the dominant peak in |S[m,n]|.
Finds all peaks in the magnitude and returns the frequency of the largest one. Useful for transmission parameters (S12/S21) where the resonance appears as a peak rather than a dip.
- Parameters:
- Returns:
Dominant resonance frequency in GHz.
- Return type:
- Raises:
ValueError – If no peaks are found in |S[m,n]|.
- simpleLOMs.analysis.resonances(ntwk: Network, m: int = 0, n: int = 0, n_modes: int = 3, method: str = 'min_re', prominence: float = None, min_spacing_hz: float = None) ndarray[source]¶
Estimate resonance frequencies for multiple modes from S[m,n].
- Parameters:
ntwk (rf.Network)
m (int) – S-parameter indices (0-based).
n (int) – S-parameter indices (0-based).
n_modes (int) – Number of resonant modes to find.
method (str) –
- Resonance estimator. Supported:
’min_re’ : finds n_modes minima of Re(S)
’circle_fit’ : finds n_modes peaks of |dθ/df| from circle fit
prominence (float, optional) – Minimum peak prominence passed to scipy.signal.find_peaks. If None, defaults to 0.1 * (max - min) of the trace being searched.
min_spacing_hz (float, optional) – Minimum frequency separation between modes in Hz. If None, defaults to (f_max - f_min) / (10 * n_modes).
- Returns:
Resonance frequencies in Hz, sorted ascending, length n_modes. If fewer than n_modes peaks are found, the array is padded with NaN.
- Return type:
np.ndarray
- simpleLOMs.analysis.resonances_from_s(network: Network, m: int = 0, n: int = 0) ndarray[source]¶
Find all resonance frequencies from peaks in Re(S[m,n]).
- simpleLOMs.analysis.resonances_from_s_max(network: Network, m: int = 0, n: int = 0) float[source]¶
Resonance frequency from the dominant peak in |S[m,n]|.
Finds all peaks in the magnitude and returns the frequency of the largest one. Useful for transmission parameters (S12/S21) where the resonance appears as a peak rather than a dip.
- Parameters:
- Returns:
Dominant resonance frequency in GHz.
- Return type:
- Raises:
ValueError – If no peaks are found in |S[m,n]|.
Models¶
Elements¶
elements.py¶
Primitive lumped-element circuit blocks built on top of scikit-rf. Each function returns an rf.Network (a 2-port element) that can be wired into an rf.Circuit connection list.
For netowrks built using these eleemnts see simpleLOMs/networks/.
- simpleLOMs.elements.coupling_capacitor(C: float, freq: Frequency, name: str = 'cc', Z0: float = 50) Network[source]¶
Series coupling capacitor.
Implemented as a SeriesImpedance with Z = 1 / (jωC).
- simpleLOMs.elements.lc_resonator(L: float, C: float, freq: Frequency, name: str = 'lc', Z0: float = 50) Network[source]¶
Parallel LC resonator shunted to ground.
Implemented as a ShuntAdmittance with Y = jωC + 1/(jωL), the admittance of a parallel LC tank.
Networks¶
networks/cpw.py¶
Network builders for CPW (Coplanar Waveguide) resonator topologies.
Each function takes a CPWParams dataclass for device geometry plus circuit-level parameters (coupling caps, frequency, etc.) and returns an rf.Network.
Topology overview¶
All networks follow the same chain:
[Port1] – Cc1 – Ctog1 – [CPW line] – Ctog2 – Cc2 – [Port2 or Open]
The “loaded” variants insert an LC resonator between the port and the coupling capacitor on each side:
[Port1] – cc_port1 – load1 – Cc1 – Ctog1 – [CPW line] – …
- simpleLOMs.networks.cpw.cpw_resonator_loaded_network_2port(freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, cpw_params: CPWParams = None, Z0: float = 50) Network[source]¶
Two-port CPW resonator with an LC load on each port side.
The loads model external resonators (e.g. qubits or readout resonators) weakly coupled to each port via small series capacitors.
- Topology:
- [Port1] – cc_port1 – load1 (shunt LC) – Cc1 – Ctog1 – [CPW line]
– Ctog2 – Cc2 – load2 (shunt LC) – cc_port2 – [Port2]
- Parameters:
freq (rf.Frequency)
d (float) – Resonator length in metres.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
Lload1 (float) – Inductance (H) and capacitance (F) of the load on port 1 side.
Cload1 (float) – Inductance (H) and capacitance (F) of the load on port 1 side.
Lload2 (float) – Inductance (H) and capacitance (F) of the load on port 2 side.
Cload2 (float) – Inductance (H) and capacitance (F) of the load on port 2 side.
cpw_params (CPWParams, optional) – CPW geometry. Uses default CPWParams() if not provided.
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port loaded transmission network.
- Return type:
rf.Network
- simpleLOMs.networks.cpw.cpw_resonator_network(freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, cpw_params: CPWParams = None, Z0: float = 50) Network[source]¶
Single-port CPW resonator (reflection measurement, port + open termination).
- Topology:
[Port1] – Cc1 (series) – Ctog1 (shunt) – [CPW line] – Ctog2 (shunt) – Cc2 (shunt) – [Open]
- Parameters:
freq (rf.Frequency)
d (float) – Physical resonator length in metres.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
cpw_params (CPWParams, optional) – CPW geometry. Uses default CPWParams() if not provided.
Z0 (float) – Reference impedance in Ohms.
- Returns:
1-port reflection network.
- Return type:
rf.Network
- simpleLOMs.networks.cpw.cpw_resonator_network_2port(freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, cpw_params: CPWParams = None, Z0: float = 50) Network[source]¶
Two-port CPW resonator (transmission measurement, port on each side).
- Topology:
[Port1] – Cc1 (series) – Ctog1 (shunt) – [CPW line] – Ctog2 (shunt) – Cc2 (series) – [Port2]
- Parameters:
freq (rf.Frequency)
d (float) – Physical resonator length in metres.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
cpw_params (CPWParams, optional) – CPW geometry. Uses default CPWParams() if not provided.
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port transmission network.
- Return type:
rf.Network
- simpleLOMs.networks.cpw.cpw_resonator_single_load_network_2port(freq: Frequency, d: float, Cc1: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, cpw_params: CPWParams = None, Z0: float = 50) Network[source]¶
Two-port CPW resonator with an LC load on each port side.
The loads model external resonators (e.g. qubits or readout resonators) weakly coupled to each port via small series capacitors.
- Topology:
- [Port1] – cc_port1 – load1 (shunt LC) – Cc1 – Ctog1 – [CPW line]
– Ctog2 – Cc2 – load2 (shunt LC) – cc_port2 – [Port2]
- Parameters:
freq (rf.Frequency)
d (float) – Resonator length in metres.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
Lload1 (float) – Inductance (H) and capacitance (F) of the load on port 1 side.
Cload1 (float) – Inductance (H) and capacitance (F) of the load on port 1 side.
Lload2 (float) – Inductance (H) and capacitance (F) of the load on port 2 side.
Cload2 (float) – Inductance (H) and capacitance (F) of the load on port 2 side.
cpw_params (CPWParams, optional) – CPW geometry. Uses default CPWParams() if not provided.
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port loaded transmission network.
- Return type:
rf.Network
networks/lc.py¶
Network builders for lumped-element LC resonator topologies.
Topology families¶
- Basic 2-port:
[Port1] – Cc1 – [LC shunt] – Cc2 – [Port2]
- With grounds (mirrors CPW Ctog capacitors):
[Port1] – Cc1 – Ctog1 – [LC shunt] – Ctog2 – Cc2 – [Port2]
- Loaded variants insert an LC load (e.g. a qubit) on each port side:
[Port1] – cc_port – load – Cc1 – … – Cc2 – load – cc_port – [Port2]
- simpleLOMs.networks.lc.lc_load_bare_network(Lload: float, Cload: float, Cc_port: float, freq: Frequency, Z0: float = 50) Network[source]¶
Single isolated LC load resonator coupled to one port via Cc_port. Used to extract the ‘true’ bare frequency of a load as seen from the port, accounting for the capacitive loading of the coupler.
- Topology:
[Port1] – Cc_port (series) – [LC shunt] – [Open]
- Parameters:
- Returns:
1-port reflection network.
- Return type:
rf.Network
- simpleLOMs.networks.lc.lc_load_dressed_network(Lload: float, Cload: float, Cc_port: float, Cc1: float, freq: Frequency, Z0: float = 50) Network[source]¶
- simpleLOMs.networks.lc.lc_load_dressed_network_2(Lload: float, Cload: float, Cc_port: float, Cc1: float, freq: Frequency, Z0: float = 50) Network[source]¶
Isolated LC load with both port coupler and CPW coupler attached, to extract the ‘dressed’ bare frequency accounting for capacitive loading from both sides.
- Topology:
[Port1] – Cc_port (series) – [LC shunt] – Cc1 (series) – [Open]
- Parameters:
Lload (float) – Inductance (H) and capacitance (F) of the load resonator.
Cload (float) – Inductance (H) and capacitance (F) of the load resonator.
Cc_port (float) – Port coupling capacitance (F) — hardcoded as 1e-15 in your topology.
Cc1 (float) – CPW-side coupling capacitance (F).
freq (rf.Frequency)
Z0 (float) – Reference impedance in Ohms.
- Returns:
1-port reflection network.
- Return type:
rf.Network
- simpleLOMs.networks.lc.lc_resonator_loaded_network_2port(Leff: float, Ceff: float, Cc1: float, Cc2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, freq: Frequency, Z0: float = 50) Network[source]¶
Two-port LC resonator with LC loads on each port side.
- Topology:
[Port1] – cc_port1 – load1 – Cc1 – [LC shunt] – Cc2 – load2 – cc_port2 – [Port2]
- Parameters:
Leff (float) – Effective inductance (H) and capacitance (F) of the main resonator.
Ceff (float) – Effective inductance (H) and capacitance (F) of the main resonator.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Lload1 (float) – Load resonator on port 1 side.
Cload1 (float) – Load resonator on port 1 side.
Lload2 (float) – Load resonator on port 2 side.
Cload2 (float) – Load resonator on port 2 side.
freq (rf.Frequency)
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port loaded transmission network.
- Return type:
rf.Network
- simpleLOMs.networks.lc.lc_resonator_loaded_network_2port_shifted(Leff: float, Ceff: float, Cc1: float, Cc2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, freq: Frequency, Z0: float = 50) Network[source]¶
Two-port loaded LC resonator with π-phase correction on S21/S12.
Identical to lc_resonator_loaded_network_2port but negates S21/S12 to account for the missing half-wave CPW phase. See lc_resonator_network_2port_shifted for full explanation.
- Topology:
[Port1] – cc_port1 – load1 – Cc1 – [LC shunt] – Cc2 – load2 – cc_port2 – [Port2] (then S21, S12 negated)
- simpleLOMs.networks.lc.lc_resonator_loaded_network_with_grounds_2port(Leff: float, Ceff: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, freq: Frequency, Z0: float = 50) Network[source]¶
Two-port LC resonator with both ground capacitors and LC loads.
This is the most complete LC LOM topology: it includes the shunt Ctog capacitors that model CPW ground geometry AND external load resonators on each port side.
- Topology:
[Port1] – cc_port1 – load1 – Cc1 – Ctog1 – [LC shunt] – Ctog2 – Cc2 – load2 – cc_port2 – [Port2]
- Parameters:
Leff (float) – Effective inductance (H) and capacitance (F) of the main resonator.
Ceff (float) – Effective inductance (H) and capacitance (F) of the main resonator.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
Lload1 (float) – Load resonator on port 1 side.
Cload1 (float) – Load resonator on port 1 side.
Lload2 (float) – Load resonator on port 2 side.
Cload2 (float) – Load resonator on port 2 side.
freq (rf.Frequency)
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port fully-loaded transmission network with ground caps.
- Return type:
rf.Network
- simpleLOMs.networks.lc.lc_resonator_network(Leff: float, Ceff: float, Cc1: float, Cc2: float, freq: Frequency, Z0: float = 50) Network[source]¶
Single-port LC resonator (reflection measurement).
- Topology:
[Port1] – Cc1 (series) – [LC shunt] – Cc2 (shunt to open) – [Open]
- Parameters:
Leff (float) – Effective inductance (H) and capacitance (F) of the LC resonator.
Ceff (float) – Effective inductance (H) and capacitance (F) of the LC resonator.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
freq (rf.Frequency)
Z0 (float) – Reference impedance in Ohms.
- Returns:
1-port reflection network.
- Return type:
rf.Network
- simpleLOMs.networks.lc.lc_resonator_network_2port(Leff: float, Ceff: float, Cc1: float, Cc2: float, freq: Frequency, Z0: float = 50) Network[source]¶
Two-port LC resonator (transmission measurement).
- Topology:
[Port1] – Cc1 (series) – [LC shunt] – Cc2 (series) – [Port2]
- Parameters:
Leff (float) – Effective inductance (H) and capacitance (F) of the LC resonator.
Ceff (float) – Effective inductance (H) and capacitance (F) of the LC resonator.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
freq (rf.Frequency)
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port transmission network.
- Return type:
rf.Network
- simpleLOMs.networks.lc.lc_resonator_network_2port_shifted(Leff: float, Ceff: float, Cc1: float, Cc2: float, freq: Frequency, Z0: float = 50) Network[source]¶
Two-port LC resonator with π-phase correction on S21/S12.
Identical to lc_resonator_network_2port but negates the off-diagonal S-matrix elements to account for the π electrical phase that a half-wave CPW resonator accumulates at resonance. A lumped LC shunt has no transmission line length so it does not pick up this phase naturally; the correction restores the correct sign convention for comparison against CPW reference networks.
- Topology:
[Port1] – Cc1 (series) – [LC shunt] – Cc2 (series) – [Port2] (then S21, S12 negated)
- simpleLOMs.networks.lc.lc_resonator_network_with_grounds_2port(Leff: float, Ceff: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, freq: Frequency, Z0: float = 50) Network[source]¶
Two-port LC resonator with shunt-to-ground capacitors on each side.
These Ctog capacitors mirror the geometry of the CPW model, where the ground capacitance at each gap is an important feature of the distributed line.
- Topology:
[Port1] – Cc1 – Ctog1 (shunt) – [LC shunt] – Ctog2 (shunt) – Cc2 – [Port2]
- Parameters:
Leff (float) – Effective inductance (H) and capacitance (F) of the LC resonator.
Ceff (float) – Effective inductance (H) and capacitance (F) of the LC resonator.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
freq (rf.Frequency)
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port transmission network with ground capacitances.
- Return type:
rf.Network
- simpleLOMs.networks.lc.lc_resonator_single_load_network_2port(Leff: float, Ceff: float, Cc1: float, Lload1: float, Cload1: float, freq: Frequency, Z0: float = 50) Network[source]¶
Two-port LC resonator with LC loads on each port side.
- Topology:
[Port1] – cc_port1 – load1 – Cc1 – [LC shunt] – Cc2 – load2 – cc_port2 – [Port2]
- Parameters:
Leff (float) – Effective inductance (H) and capacitance (F) of the main resonator.
Ceff (float) – Effective inductance (H) and capacitance (F) of the main resonator.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Lload1 (float) – Load resonator on port 1 side.
Cload1 (float) – Load resonator on port 1 side.
Lload2 (float) – Load resonator on port 2 side.
Cload2 (float) – Load resonator on port 2 side.
freq (rf.Frequency)
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port loaded transmission network.
- Return type:
rf.Network
- simpleLOMs.networks.lc.lc_resonator_single_load_network_with_grounds_2port(Leff: float, Ceff: float, Cc1: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, freq: Frequency, Z0: float = 50) Network[source]¶
Two-port LC resonator with both ground capacitors and LC loads.
This is the most complete LC LOM topology: it includes the shunt Ctog capacitors that model CPW ground geometry AND external load resonators on each port side.
- Topology:
[Port1] – cc_port1 – load1 – Cc1 – Ctog1 – [LC shunt] – Ctog2 – Cc2 – load2 – cc_port2 – [Port2]
- Parameters:
Leff (float) – Effective inductance (H) and capacitance (F) of the main resonator.
Ceff (float) – Effective inductance (H) and capacitance (F) of the main resonator.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
Lload1 (float) – Load resonator on port 1 side.
Cload1 (float) – Load resonator on port 1 side.
Lload2 (float) – Load resonator on port 2 side.
Cload2 (float) – Load resonator on port 2 side.
freq (rf.Frequency)
Z0 (float) – Reference impedance in Ohms.
- Returns:
2-port fully-loaded transmission network with ground caps.
- Return type:
rf.Network
Plotting¶
plotting.py¶
Plotting functions for notebooks or scripts after running fits.
- simpleLOMs.plotting.fancy_plot(lom_network: Network, data_network: Network, m: int = 0, n: int = 0, lom_label: str = 'LOM', data_label: str = 'Data') None[source]¶
- simpleLOMs.plotting.fancy_plot_all_models(networks: dict[str, Network], m: int = 0, n: int = 0, quantity: str = 're', title: str = None) None[source]¶
Plot one S-parameter quantity for multiple networks on a single axes. Useful for comparing CPW, FosterFit, OptimizedFit, and AnalyticalFit in one call.
- Parameters:
networks (dict[str, rf.Network]) – Mapping of label → network, e.g. {“CPW”: cpw_net, “Foster”: foster_net, “Optimized”: opt_net}
m (int) – S-parameter indices (0-based).
n (int) – S-parameter indices (0-based).
quantity ({"re", "im", "db", "abs"}) – Which quantity to plot.
title (str, optional) – Plot title.
- simpleLOMs.plotting.plot_all_models(networks: dict[str, Network], m: int = 0, n: int = 0, quantity: str = 're', title: str = None) None[source]¶
Plot one S-parameter quantity for multiple networks on a single axes.
Useful for comparing CPW, FosterFit, OptimizedFit, and AnalyticalFit in one call.
- Parameters:
networks (dict[str, rf.Network]) – Mapping of label → network, e.g. {“CPW”: cpw_net, “Foster”: foster_net, “Optimized”: opt_net}
m (int) – S-parameter indices (0-based).
n (int) – S-parameter indices (0-based).
quantity ({"re", "im", "db", "abs"}) – Which quantity to plot.
title (str, optional) – Plot title.
- simpleLOMs.plotting.plot_complex_network_comparison(network1: Network, network2: Network, label1: str = 'Network 1', label2: str = 'Network 2', color1: str = '#1f77b4', color2: str = '#d62728')[source]¶
- simpleLOMs.plotting.plot_error_heatmap(results_grid: list[list[dict]], param1_values, param2_values, param1_label: str, param2_label: str, model: str, metric: str, param1_scale: float = 1.0, param2_scale: float = 1.0, param1_unit: str = '', param2_unit: str = '', vmin: float = None, vmax: float = None, cmap: str = 'RdBu_r', title: str = None, ax=None, save_path: str = None)[source]¶
Heatmap of signed percent error from a 2D grid of analyze_system() runs.
- Parameters:
results_grid (list[list[dict]]) – 2D list of analyze_system() output dicts. Shape: [len(param1_values)][len(param2_values)]. Axis 0 = param1 (y-axis), axis 1 = param2 (x-axis).
param1_values (array-like) – The swept parameter values. param1 → y-axis, param2 → x-axis.
param2_values (array-like) – The swept parameter values. param1 → y-axis, param2 → x-axis.
param1_label (str) – Human-readable axis labels (e.g. “Cc1”, “Load frequency”).
param2_label (str) – Human-readable axis labels (e.g. “Cc1”, “Load frequency”).
model (str) – “optimized”, “foster”, or “analytical”.
metric (str) –
- One of: “f0_s11”, “f0_s22”, “kappa_s11”, “kappa_s22”,
”shift_mode1”, “shift_mode2”, “shift_mode3”, “shift_max”.
param1_scale (float) – Multiply parameter values before display (e.g. 1e15 to show fF).
param2_scale (float) – Multiply parameter values before display (e.g. 1e15 to show fF).
param1_unit (str) – Unit string appended to axis labels (e.g. “fF”, “GHz”).
param2_unit (str) – Unit string appended to axis labels (e.g. “fF”, “GHz”).
vmin (float, optional) – Colour scale limits. If None, uses symmetric limits around zero based on the data range.
vmax (float, optional) – Colour scale limits. If None, uses symmetric limits around zero based on the data range.
cmap (str) – Matplotlib colormap name. Default “RdBu_r” (red = positive error, blue = negative error, white = zero).
title (str, optional)
ax (matplotlib.axes.Axes, optional) – If provided, draws into this axes (used by plot_error_heatmap_trio).
save_path (str, optional) – Only used when ax is None (i.e. this is a standalone call).
- Returns:
The image object (needed by plot_error_heatmap_trio to set shared limits).
- Return type:
matplotlib.image.AxesImage
- simpleLOMs.plotting.plot_error_heatmap_trio(results_grid: list[list[dict | None]], param1_values, param2_values, param1_label: str, param2_label: str, metric: str, param1_scale: float = 1.0, param2_scale: float = 1.0, param1_unit: str = '', param2_unit: str = '', cmap: str = 'RdBu_r', title: str = None, save_path: str = None)[source]¶
- simpleLOMs.plotting.plot_fit_residuals(data_ntw, lom_networks: dict, m: int = 0, n: int = 0, title: str = None, save_path: str = None)[source]¶
Plot the complex residual S_lom - S_data for one or more LOM networks.
Residuals are shown as Re and Im separately. A perfect fit is a flat zero line. Systematic errors (frequency offset, linewidth mismatch) appear as structured curves — much more diagnostic than an overlay.
- Parameters:
data_ntw (rf.Network) – Reference (CPW or measured) network.
lom_networks (dict[str, rf.Network]) – Mapping of label → fitted LOM network. Labels should be “optimized”, “foster”, or “analytical” to get automatic colours, or any string for a custom label.
m (int) – S-parameter indices (0-based).
n (int) – S-parameter indices (0-based).
title (str, optional)
save_path (str, optional) – If provided, saves figure to this path at 300 dpi.
- simpleLOMs.plotting.plot_fit_summary(results: dict, port: str = 's11', title: str = None, save_path: str = None)[source]¶
Three-panel summary of fitting quality for all three LC models vs CPW.
- Panels:
Left — Overlay of Re(S) for CPW + all three models Centre — f₀ and κ percent errors as a grouped bar chart Right — Complex residual magnitude |S_lom - S_cpw| across the window
- simpleLOMs.plotting.plot_lom_vs_data_re_im(lom_network: Network, data_network: Network, m: int = 0, n: int = 0, lom_label: str = 'LOM', data_label: str = 'Data') None[source]¶
Overlay Re and Im of a fitted LOM network against a reference (data/CPW).
- simpleLOMs.plotting.plot_re_im(network: Network, m: int = 0, n: int = 0, dpi: int = 300, title: str = None) None[source]¶
Plot Re(S[m,n]) and Im(S[m,n]) side by side.
- simpleLOMs.plotting.plot_shift_errors(results: dict, title: str = None, save_path: str = None)[source]¶
- simpleLOMs.plotting.plot_transmission_spectrum(networks: dict, m: int = 0, n: int = 1, annotate_resonances: bool = True, prominence: float = 3.0, title: str = None, save_path: str = None)[source]¶
Plot |S_mn| in dB for one or more networks, resembling a VNA screenshot.
Resonance dips/peaks are found automatically and annotated with their frequency and depth. Designed to look like a measurement so that simulation and data can be compared at a glance.
- Parameters:
networks (dict[str, rf.Network]) – Mapping of label → network. Use “cpw”, “optimized”, etc. for automatic colours, or any string.
m (int) – S-parameter indices (0-based). Default S21 (0,1).
n (int) – S-parameter indices (0-based). Default S21 (0,1).
annotate_resonances (bool) – If True, marks each resonance with a vertical line and frequency label.
prominence (float) – Minimum prominence in dB for peak/dip detection.
title (str, optional)
save_path (str, optional)
Sweeps¶
- class simpleLOMs.sweeps.SweepConfig(cpw_params: CPWParams, freq: Frequency, d: float, Cc1: float, Cc2: float, Ctog1: float, Ctog2: float, Lload1: float, Cload1: float, Lload2: float, Cload2: float, Z0: float = 50.0, analytical_Z0: float | None = None, opt_config: OptimizationConfig | None = None)[source]¶
Bases:
objectA complete snapshot of a device and its operating conditions.
Every parameter that any sweep might want to vary is a field here. The sweep machinery calls dataclasses.replace(config, field=new_value) to create a modified copy at each sweep point — the original is never mutated.
- Parameters:
cpw_params (CPWParams) – Physical geometry of the CPW line.
freq (rf.Frequency) – Frequency sweep used for network construction. Should be wide enough to contain all resonances of interest.
d (float) – Resonator length in metres.
Cc1 (float) – Coupling capacitances in Farads.
Cc2 (float) – Coupling capacitances in Farads.
Ctog1 (float) – Shunt-to-ground capacitances in Farads.
Ctog2 (float) – Shunt-to-ground capacitances in Farads.
Lload1 (float) – Inductance (H) and capacitance (F) of the load on port 1 side.
Cload1 (float) – Inductance (H) and capacitance (F) of the load on port 1 side.
Lload2 (float) – Inductance (H) and capacitance (F) of the load on port 2 side.
Cload2 (float) – Inductance (H) and capacitance (F) of the load on port 2 side.
Z0 (float) – Reference impedance in Ohms (default 50 Ω).
analytical_Z0 (float or None) – Characteristic impedance used in the AnalyticalFit formula. If None, Z0 is used.
opt_config (OptimizationConfig or None) – Hyperparameters for OptimizedFit. Uses defaults if None.
Examples
Creating a base config:
base = SweepConfig( cpw_params=CPWParams(), freq=rf.Frequency(4e9, 12e9, 10_001, unit="Hz"), d=7e-3, Cc1=5e-15, Cc2=5e-15, Ctog1=1e-14, Ctog2=1e-14, Lload1=5e-10, Cload1=6e-13, Lload2=5e-10, Cload2=6e-13, )
Manually overriding one field:
longer = dataclasses.replace(base, d=9e-3)
- freq: Frequency¶
- opt_config: OptimizationConfig | None = None¶
- simpleLOMs.sweeps.sweep(param: str, values: ndarray, base_config: SweepConfig, extract: list[str], model: str = 'cpw', refit: bool | None = None) DataFrame[source]¶
Sweep a single parameter across a range of values and extract quantities.
At each sweep point, the chosen model is either rebuilt from scratch (for CPW or when the swept parameter changes L/C) or reuses the L/C fitted at the first sweep point (for Cc, Ctog, and load parameters).
- Parameters:
param (str) – Name of the SweepConfig field to vary. Must be an attribute of SweepConfig, e.g. “d”, “Cc1”, “Cc2”, “Ctog1”, “Lload1”, “Cload1”. Use “Lload1_Lload2” or “Cload1_Cload2” to sweep both loads together.
values (np.ndarray) – Array of values for the swept parameter.
base_config (SweepConfig) – Fixed device state. Not mutated.
Quantities to compute at each sweep point. Supported values:
”f0_s11”
S11 resonance frequency (GHz)
”f0_s22”
S22 resonance frequency (GHz)
”kappa_s11”
S11 linewidth / FWHM (MHz)
”kappa_s22”
S22 linewidth / FWHM (MHz)
”Q_s11”
Quality factor from S11 = f0 / kappa
”Q_s22”
Quality factor from S22
model (str) – Which model to use: “cpw” (default), “foster”, “optimized”, or “analytical”.
refit (bool or None) – Whether to re-fit the LC model at every sweep point. None (default) means automatic: refit when sweeping a parameter in {d, cpw_params}, reuse L/C otherwise. Setting refit=True forces refitting at every point (slower but safer when sweeping Cc1/Cc2 with OptimizedFit). Setting refit=False always reuses the first-point L/C (fastest).
- Returns:
One row per sweep point. Columns are the swept parameter value plus all requested extract quantities.
- Return type:
pd.DataFrame
Examples
Sweep resonator length with CPW ground truth:
df = sweep("d", np.linspace(5e-3, 10e-3, 20), base, extract=["f0_s11", "kappa_s11"])
Sweep coupling cap with FosterFit (reuses L/C — fast):
df = sweep("Cc1", np.linspace(1e-15, 20e-15, 30), base, extract=["f0_s11", "kappa_s11", "Q_s11"], model="foster")
- simpleLOMs.sweeps.sweep_coupling(Cc_values: ndarray, base_config: SweepConfig, extract: list[str] = None, model: str = 'cpw', symmetric: bool = True, refit: bool = False) DataFrame[source]¶
Sweep coupling capacitor(s).
- Parameters:
Cc_values (np.ndarray) – Array of coupling capacitance values in Farads.
base_config (SweepConfig)
extract (list of str, optional) – Defaults to [“f0_s11”, “kappa_s11”, “Q_s11”] if not provided.
model (str) – “cpw” (default), “foster”, “optimized”, or “analytical”.
symmetric (bool) – If True (default), sweeps Cc1 and Cc2 together. If False, sweeps only Cc1 and leaves Cc2 fixed.
refit (bool) – Whether to re-fit the LC model at every point. Default False because Cc does not change L or C — reusing is valid and fast. Set to True if you suspect OptimizedFit is sensitive to Cc during Stage 1 (unlikely but possible for very asymmetric coupling).
- Returns:
Columns: “Cc” (the swept value), plus all extract quantities.
- Return type:
pd.DataFrame
- simpleLOMs.sweeps.sweep_length(d_values: ndarray, base_config: SweepConfig, extract: list[str] = None, model: str = 'cpw') DataFrame[source]¶
Sweep resonator length d.
Always refits the model at every point because d directly sets L and C.
- Parameters:
d_values (np.ndarray) – Array of resonator lengths in metres.
base_config (SweepConfig)
extract (list of str, optional) – Defaults to [“f0_s11”, “kappa_s11”] if not provided.
model (str) – “cpw” (default), “foster”, “optimized”, or “analytical”.
- Returns:
Columns: “d”, plus all extract quantities.
- Return type:
pd.DataFrame
- simpleLOMs.sweeps.sweep_load_frequency(f_load_values: ndarray, base_config: SweepConfig, extract: list[str] = None, model: str = 'cpw', side: str = 'both', load_impedance: float = 50.0, refit: bool = False) DataFrame[source]¶
Sweep the bare load resonance frequency.
Converts each target frequency to a (L, C) pair by fixing the load characteristic impedance Z_load = sqrt(L/C), then sweeping C = 1/(ω²L).
- Parameters:
f_load_values (np.ndarray) – Array of target load resonance frequencies in Hz.
base_config (SweepConfig)
extract (list of str, optional) – Defaults to [“f0_s11”, “shift_mode1”, “shift_mode2”, “shift_mode3”].
model (str) – “cpw” (default), “foster”, “optimized”, or “analytical”.
side ({"both", "1", "2"}) – Which load to sweep. “both” sweeps load 1 and load 2 together (useful when the two loads are identical, e.g. symmetric qubits).
load_impedance (float) – Characteristic impedance of the load resonator in Ohms. Used to fix L from Z_load = sqrt(L/C) → L = Z_load / ω₀. Default 50 Ω.
refit (bool) – Whether to re-fit the LC model at every point. Default False.
- Returns:
Columns: “f_load_GHz” (the swept load frequency in GHz), “Lload” (H), “Cload” (F), plus all extract quantities.
- Return type:
pd.DataFrame
Utilities¶
utils.py¶
Ease of use functions for processing and viewing data.
- simpleLOMs.utils.make_params_table(results: dict) DataFrame[source]¶
Summarize fitted L and C for all three models as a tidy DataFrame.
- Parameters:
results (dict) – Output from analyze_system().
- Returns:
Indexed by model name, columns L (H) and C (F).
- Return type:
pd.DataFrame
- simpleLOMs.utils.make_results_table(results: dict, round_decimals: int = 4) DataFrame[source]¶
Summarise analyze_system() output as a tidy DataFrame.
Rows are models (CPW, Optimized, Foster, Analytical). Columns are f₀, κ, and percent errors for S11 and S22.
- simpleLOMs.utils.make_shift_error_table(results: dict, round_decimals: int = 3) DataFrame[source]¶
Signed percent shift errors vs CPW reference for all three models.