Getting started

Requirements

  • Python 3.10 or later.
  • ngspice on the PATH. The library is developed with ngspice 44. Check with ngspice --version.
pip install spicefault

To work on the library itself:

git clone https://github.com/telmomm/spicefault.git
cd spicefault
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,docs]"
pytest tests/unit

1. A circuit

A circuit is a SPICE netlist, from a file or from text. spicefault reads its components, nodes and numeric parameters and never modifies it: every simulation works on a copy.

from spicefault import Circuit

circuit = Circuit.from_netlist("rc_lowpass.cir")
circuit.components()     # name, kind, nodes and parameters of each
circuit.parameters()     # {("R1", "value"): 10000.0, ...}

The netlist needs no analysis commands: the experiment adds them.

2. Faults, and the healthy population

from spicefault.faults import OpenCircuit, ParametricFault
from spicefault.variation import tolerances

faults = [OpenCircuit("R2"), ParametricFault("C1", deviation=0.5)]
population = tolerances(circuit, {"R": 0.01, "C": 0.05})   # 1 % and 5 % parts

3. What to simulate and what to read

from spicefault import Measurement, SimulationConfig

config = SimulationConfig(("op", "ac dec 20 1 1e5"), outputs=("v(out)",))
measurements = [
    Measurement.value("v(out)", name="dc"),
    Measurement.magnitude("v(out)", 1e3, name="gain_1k"),
]

4. Run it

In memory, for a small study:

from spicefault import Experiment

experiment = Experiment(circuit, faults=faults, variations=population, config=config,
                        measurements=measurements, samples=50, seed=1)
table = experiment.run(workers=4).to_frame()

To disk, for a campaign that takes long and must survive an interruption:

from spicefault import FaultCampaign

campaign = FaultCampaign(circuit, faults, out_dir="data/rc", samples_per_fault=200,
                         healthy_samples=2000, variations=population, config=config,
                         measurements=measurements, seed=1)

if __name__ == "__main__":
    print(campaign.validate())
    campaign.run(workers=8)

Scripts that use several workers

Workers are processes. On macOS and Windows the part of a script that launches them must be under if __name__ == "__main__":, and functions given to custom variations or measurements must be defined at module level.

5. Analyse

from spicefault.reliability import ReliabilityAnalysis

analysis = ReliabilityAnalysis.from_dataset("data/rc")
analysis.detectability(alpha=0.01).table

The examples do all of this on a real circuit and can be run as they are.