Skip to content

Base & Parameters

The base subpackage provides the central configuration object (Defaults), a lightweight base class (PhysicalParams), and three mixin classes that add plotting, serialization, and sweep capabilities.


SpinDefectSim.base.params

Defaults

from SpinDefectSim.base.params import Defaults

A dataclass that serves as the single source of truth for all tuneable simulation parameters. Every class that inherits PhysicalParams holds a Defaults instance and falls back to it when a per-call override is not supplied.

Constructor

Defaults(
    defect_type: str = "vb_minus",
    D0_Hz: float = 3.46e9,
    E0_Hz: float = 50e6,
    d_perp: float = 0.35,
    d_parallel: float = 0.0,
    B_mT: float = 1.5,
    gamma_e: float = 28e9,
    T2star: float = 50e-9,
    T2echo: float = 10e-6,
    contrast: Optional[float] = None,
    n_photons: int = 500,
    k_optical: Optional[float] = None,
    N_def: int = 1200,
    R_laser: float = 500e-9,
    R_patch: float = 200e-9,
    z_defect: float = 0.34e-9,
    epsilon_eff: float = 7.0,
    eps_layer: Optional[float] = None,
    eps_host: Optional[float] = None,
    screening_model: Optional[str] = "dual_gate",
    lambda_screen: float = 10e-9,
    d_gate: float = 15e-9,
    n_images: int = 30,
    r_min: float = 0.2e-9,
)

Parameters

Parameter Type Default Description
defect_type str "vb_minus" Default defect preset name
D0_Hz float 3.46e9 Axial zero-field splitting (Hz)
E0_Hz float 50e6 Intrinsic strain splitting (Hz)
d_perp float 0.35 Transverse E-field coupling (Hz / (V/m))
d_parallel float 0.0 Axial E-field coupling (Hz / (V/m))
B_mT float 1.5 External B-field magnitude (mT)
gamma_e float 28e9 Electron gyromagnetic ratio (Hz/T)
T2star float 50e-9 T₂* dephasing time for Ramsey (s)
T2echo float 10e-6 T₂ coherence time for Hahn-echo (s)
contrast float \| None None CW ODMR contrast; if None, computed from RateModel
n_photons int 500 Photons collected per readout shot
k_optical float \| None None Laser excitation rate (Hz); None → use rate preset
N_def int 1200 Number of defects inside the laser beam
R_laser float 500e-9 Laser beam radius (m)
R_patch float 200e-9 Sensing patch radius (m)
z_defect float 0.34e-9 Defect height above the moiré / sample plane (m)
epsilon_eff float 7.0 Effective dielectric constant for Coulomb screening
eps_layer float \| None None hBN layer dielectric; used for transmission factor
eps_host float \| None None Host dielectric; used for transmission factor
screening_model str \| None "dual_gate" Coulomb screening: None (bare), "yukawa", "dual_gate"
lambda_screen float 10e-9 Yukawa screening length (m)
d_gate float 15e-9 Dual-gate separation in image-charge model (m)
n_images int 30 Number of image-charge terms in the sum
r_min float 0.2e-9 Minimum distance regulariser to avoid singularities (m)

Class methods


Defaults.for_defect
@classmethod
def for_defect(cls, defect_type: str, **kwargs) -> Defaults

Create a Defaults instance with spin-Hamiltonian parameters (D₀, E₀, d⊥, d‖, γ_e, spin) pre-loaded from a named built-in defect preset.

Parameters:

Name Type Description
defect_type str Preset name, e.g. "nv_minus", "vb_minus", "v_sic"
**kwargs Any Defaults field to override after loading the preset

Returns: Defaults

Example:

d = Defaults.for_defect("nv_minus", B_mT=5.0, T2star=1e-6)
# d.D0_Hz == 2.87e9, d.B_mT == 5.0


Defaults.to_spin_params
def to_spin_params() -> SpinParams

Convert the current defaults into a SpinParams object suitable for Hamiltonian construction.

Returns: SpinParams


Defaults.coulomb_kwargs
def coulomb_kwargs() -> dict

Return a dictionary of keyword arguments (epsilon_eff, screening_model, lambda_screen, d_gate, n_images, r_min) ready to pass directly to Coulomb kernel functions.

Returns: dict


Defaults.get_contrast
def get_contrast(k_optical: Optional[float] = None) -> float

Return the CW ODMR contrast as a plain float. If self.contrast is already set, returns it directly. Otherwise, instantiates a RateModel from the defect's rate_params and computes the steady-state contrast.

Parameters:

Name Type Description
k_optical float \| None Override the laser excitation rate (Hz)

Returns: float — contrast C ∈ (0, 1)


Module-level singleton

from SpinDefectSim.base.params import DEFAULT
# DEFAULT is Defaults() — a convenience instance with all defaults

PhysicalParams

from SpinDefectSim.base.params import PhysicalParams

Lightweight base class for all domain objects. Holds a Defaults instance and exposes _resolve() for cascading parameter lookup.

Constructor

PhysicalParams(defaults: Optional[Defaults] = None)

If defaults is None, the module-level DEFAULT singleton is used.

_resolve

def _resolve(value, key: str)

Return value if it is not None; otherwise return self.defaults.<key>.

Typically called internally by subclasses to resolve per-call overrides:

z = self._resolve(z_defect, "z_defect")

PHYSICAL

from SpinDefectSim.base.params import PHYSICAL

Dictionary of fundamental physical constants:

Key Value Unit
"e" 1.602176634e-19 C
"epsilon_0" 8.854187817e-12 F/m
"k_B" 1.380649e-23 J/K
"hbar" 1.054571817e-34 J·s
"gamma_e_Hz_per_T" 28e9 Hz/T

SpinDefectSim.base.mixins

Three mixin classes that add cross-cutting capabilities. They are inherited by DefectEnsemble, ParameterSweep, SensingExperiment, and others.


PlottingMixin

Adds lightweight matplotlib helpers to any class.

quick_plot

def quick_plot(
    x: np.ndarray,
    y: np.ndarray,
    *,
    xlabel: str = "",
    ylabel: str = "",
    title: str = "",
    label: str = "",
    ax=None,
    **kwargs,
) -> tuple[plt.Figure, plt.Axes]

Plot y vs x on a new or existing axes.

Parameters:

Name Type Description
x np.ndarray x-axis data
y np.ndarray y-axis data
xlabel str x-axis label
ylabel str y-axis label
title str Figure title
label str Legend label
ax plt.Axes \| None Existing axes to plot onto; creates a new figure if None
**kwargs Forwarded to ax.plot()

Returns: (fig, ax) tuple


save_fig

def save_fig(fig: plt.Figure, name: str, *, dpi: int = 150, fmt: str = "png") -> str

Save fig to <_fig_output_dir>/<name>.<fmt>. The output directory is created if it does not exist.

Parameters:

Name Type Description
fig plt.Figure Figure to save
name str File stem (no extension)
dpi int Resolution in dots per inch
fmt str File format: "png", "pdf", "svg", etc.

Returns: str — absolute path of the saved file

Class attribute: _fig_output_dir: str = "figures" — override to change the output directory.


SerializationMixin

Adds .save() / .load() via NumPy .npz archives.

save

def save(path: str) -> str

Save all arrays returned by _serializable_arrays() to <path>.npz.

Parameters:

Name Type Description
path str File path (without .npz extension)

Returns: str — full path including .npz


load (classmethod)

@classmethod
def load(path: str) -> Dict[str, np.ndarray]

Load a previously saved .npz file.

Parameters:

Name Type Description
path str File path with or without .npz extension

Returns: dict[str, np.ndarray] — mapping of array names to arrays


_serializable_arrays

def _serializable_arrays() -> Dict[str, np.ndarray]

Override in subclasses to declare which arrays should be serialized.


SweepMixin

Generic 1-D / 2-D parameter sweep engine.

sweep

def sweep(
    fn: Callable[..., Any],
    verbose: bool = False,
    **param_grids,
) -> List[Dict[str, Any]]

Run a Cartesian product sweep over all values in param_grids, calling fn(**point) at each grid point.

Parameters:

Name Type Description
fn Callable Function to call at each grid point; must accept the sweep keys as keyword arguments
verbose bool Print progress if True
**param_grids Each keyword is a parameter name; value must be a list or array of values to sweep

Returns: List[Dict] — one dict per grid point, containing all parameter values and the return value of fn under key "result"

Example:

results = obj.sweep(
    my_fn,
    E_gate=[1e6, 2e6, 5e6],
    B_mT=[1.0, 2.0],
)
# → 6 dicts, one per (E_gate, B_mT) combination