# PyCircuitKit (CAT) — Circuit Analysis Toolkit
[](https://github.com/lgili/PyCircuitKit/actions/workflows/ci.yml)
[](https://lgili.github.io/PyCircuitKit/)
Modern, strongly-typed Python toolkit to **define**, **simulate** (.OP / .TRAN / .AC) and **analyze** electronic circuits with a clean, Pythonic API. CAT targets real engineering workflows: parameter sweeps, **Monte Carlo**, worst‑case, and painless result handling in NumPy/Pandas.
Documentation: https://lgili.github.io/PyCircuitKit/
> **Status:** MVP — Circuit DSL (Ports & Nets), NGSpice (CLI) `.op/.tran/.ac`, LTspice netlist import (includes `.include/.param`, V/I PULSE/SIN/PWL), controlled sources (E/G/F/H) and switches, Monte‑Carlo, and metrics/plots. Roadmap: worst‑case refinements, RAW binary, more examples.
---
## Documentation
- Site: https://lgili.github.io/PyCircuitKit/
- Getting Started: https://lgili.github.io/PyCircuitKit/getting-started/
- Guides: Monte Carlo (https://lgili.github.io/PyCircuitKit/monte-carlo/) · AC Stability (https://lgili.github.io/PyCircuitKit/ac-stability/)
- Examples: https://lgili.github.io/PyCircuitKit/examples/
- Examples Gallery: https://lgili.github.io/PyCircuitKit/examples-gallery/
---
## Quickstart (1 min)
```python
from cat import Circuit, R, C, V, GND, run_tran
c = Circuit("rc")
V1, R1, C1 = V(5.0), R("1k"), C("100n")
c.add(V1, R1, C1)
c.connect(V1.ports[0], R1.ports[0])
c.connect(R1.ports[1], C1.ports[0])
c.connect(V1.ports[1], GND)
c.connect(C1.ports[1], GND)
df = run_tran(c, "10us", "5ms", return_df=True)
print(df.head())
```
---
## Dev shortcuts (Makefile)
```bash
# 1) Create venv and install in editable mode
make install
# 2) Run the circuit preview example (prints connectivity and generates preview.svg/.dot)
make preview
# If you prefer without venv (uses PYTHONPATH=src)
make preview-ci
# Install plotting extras (Matplotlib) for figure examples
make install-extras
# Run plotting/simulation examples (require NGSpice in PATH)
make ac-bode
make step-fig
make mc-fig
make opamp-stability
# Run all figure examples
make examples
```
Install Graphviz to render the SVG preview (macOS: `brew install graphviz`, Ubuntu: `sudo apt install -y graphviz`).
---
## ✨ Features (MVP)
- **Zero-string connectivity:** connect **Port ↔ Net** objects (type-safe, IDE-friendly).
- **Core components:** `Resistor`, `Capacitor`, `Vdc` (more soon).
- **Netlist builder:** generate SPICE netlists with topology validation.
- **NGSpice (CLI) runner:** headless `.op` smoke execution (skips automatically if NGSpice is missing).
- **Utilities for design:**
- **E-series** enumerator & rounding (E12/E24/E48/E96).
- **RC low-pass** design helper by target `f_c`.
### Highlights
- **AC/DC/TRAN** via NGSpice (CLI).
- **LTspice import**: handles `.include/.param`, V/I PULSE/SIN/PWL, controlled sources (E/G/F/H), diode D, simple `.SUBCKT` flatten.
- **Monte Carlo**: parallel, deterministic order; DataFrame stacking.
- **Metrics/Plots**: AC (Bode/PM/GM) e tran (rise/fall/settling/overshoot).
---
## 🧰 Installation
### Requirements
- Python **3.10+**
- pip / virtualenv (or **uv** / **poetry**)
- **NGSpice** (recommended for simulation; optional for building & unit tests)
> LTspice support is planned. For now, NGSpice is the reference backend.
### macOS (pip)
```bash
# 1) Install NGSpice
brew install ngspice
# 2) Clone and set up the project
git clone https://github.com/lgili/PyCircuitKit.git
cd pycircuitkit
python -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e .
pip install ruff mypy pytest pytest-cov
```
> Optionally, add `matplotlib` and `pandas` for plotting/stacking examples.
### Linux (Ubuntu/Debian)
```bash
# 1) Install NGSpice
sudo apt update
sudo apt install -y ngspice
# 2) Clone and set up
git clone https://github.com/lgili/PyCircuitKit.git
cd pycircuitkit
python3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e .
pip install ruff mypy pytest pytest-cov
```
### Windows (PowerShell)
```powershell
# 1) Install NGSpice
# Download installer from: https://ngspice.sourceforge.io/download.html
# Add the ngspice bin folder (e.g. C:\Program Files\Spice64\bin) to your PATH.
# 2) Clone and set up
git clone https://github.com/lgili/PyCircuitKit.git
cd pycircuitkit
py -m venv .venv
.venv\Scripts\activate
pip install -U pip
pip install -e .
pip install ruff mypy pytest pytest-cov
```
### Alternative without uv (pip-only):
```powershell
py -m venv .venv
.venv\Scripts\activate
pip install -U pip
pip install -e ".[opt]"
pip install -r dev-requirements.txt
```
If ngspice is not on your PATH, tests that require it will auto-skip.
## 🚀 Quick Start (User Guide)
### 1) Define a circuit (Style 1: Ports & Nets) and run **.TRAN**
```python
from cat.core.circuit import Circuit
from cat.core.net import Net, GND
from cat.core.components import Vdc, Resistor, Capacitor
from cat.analysis import TRAN
# Circuit: RC low‑pass
c = Circuit("rc_lowpass")
vin = Net("vin")
vout = Net("vout")
V1 = Vdc("1", 5.0)
R1 = Resistor("1", "1k")
C1 = Capacitor("1", "100n")
c.add(V1, R1, C1)
c.connect(V1.ports[0], vin)
c.connect(V1.ports[1], GND)
c.connect(R1.ports[0], vin)
c.connect(R1.ports[1], vout)
c.connect(C1.ports[0], vout)
c.connect(C1.ports[1], GND)
res = TRAN("10us", "5ms").run(c)
ts = res.traces
print("traces:", ts.names)
```
### 2) **Monte Carlo** on the same circuit
```python
from cat.analysis import OP, monte_carlo, NormalPct
# Varia apenas R1 com 5% (sigma) — 16 amostras
mc = monte_carlo(
circuit=c,
mapping={R1: NormalPct(0.05)},
n=16,
analysis_factory=lambda: OP(),
seed=123,
)
# Empilha em DataFrame (se quiser)
from cat.analysis import stack_runs_to_df
print(stack_runs_to_df(mc.runs).head())
```
### 2.1) Monte Carlo to DataFrame (metrics)
```python
# Map metrics per run (e.g., last value of vout)
from cat.analysis.core import AnalysisResult
def metrics(res: AnalysisResult) -> dict[str, float]:
return {"vout": float(res.traces["v(n1)"].values[-1])}
df = mc.to_dataframe(metric=metrics, param_prefix="param_")
print(df.head())
```
Optionally, extract trace values at a given time for each trial:
```python
df2 = mc.to_dataframe(metric=None, y=["v(n1)"], sample_at=1e-3) # t = 1 ms
```
### 3) Ideal Op-Amp (OA) and topology helpers
```python
from cat import GND, Circuit, opamp_inverting
from cat.core.components import V, R
c = Circuit("opamp_inv")
V1 = V(1.0)
c.add(V1)
vin = V1.ports[0]
load = R("1k"); c.add(load)
vout = load.ports[0]; c.connect(load.ports[1], GND)
# Inverting amplifier: gain = -Rf/Rin = -100k/10k
opamp_inverting(c, inp=vin, out=vout, ref=GND, Rin="10k", Rf="100k", gain=1e6)
```
The helper `opamp_buffer(c, inp, out)` wires a voltage follower.
### 4) Switches (S/W) with .model
- Voltage-controlled: `SW("SWMOD")` → `Sref p n cp cn SWMOD` (requires `.model SWMOD VSWITCH(...)`).
- Current-controlled: `SWI("V1","WMOD")` → `Wref p n V1 WMOD` (requires `.model WMOD ISWITCH(...)`).
Add directives with `circuit.add_directive(".model ...")`.
### 3) Importar netlist do **LTspice** e simular
Export no LTspice: *View → SPICE Netlist* → salve como `.cir`/`.net`.
```python
from cat.io.ltspice_parser import from_ltspice_file
from cat.analysis import TRAN
c2 = from_ltspice_file("./my_filter.cir")
res2 = TRAN("1us", "2ms").run(c2)
print(res2.traces.names)
```
### 4) Utilities (E‑series & RC helper)
```python
from cat.utils.e_series import round_to_series
from cat.utils.synth import design_rc_lowpass
print(round_to_series(12700, "E96"))
print(design_rc_lowpass(fc=159.155, prefer_R=True, series="E24"))
```
## 📦 Project Layout
src/cat/
core/ # Nets, Ports, Components, Circuit, netlist builder
analysis/ # OP/AC/DC/TRAN, metrics, sweep/step/montecarlo, viz
spice/ # Simulator adapters + registry (ngspice_cli)
io/ # RAW/LOG parsers, LTspice import/flatten
utils/ # e_series, units, synth, logging, topologies
dsl/ # chain/parallel helpers and schematic ctx manager
tests/ # pytest suite (unit + smoke if ngspice available)
⸻
🛠️ Developer Guide
Tooling
We ship configs for ruff (lint & format), mypy (strict typing), pytest (tests & coverage), and pre-commit.
Install dev tools:
```bash
uv sync --all-extras --dev
pre-commit install
```
Run checks locally:
```bash
ruff check .
ruff format --check .
mypy --explicit-package-bases src
pytest -q
```
CI (GitHub Actions) runs the same steps via pip. NGSpice smoke tests are skipped if ngspice isn’t present on the runner.
Adding Components
Create a class in cat/core/components.py:
```python
from dataclasses import dataclass
from .net import Port, PortRole
from .components import Component
@dataclass
class Inductor(Component):
def __post_init__(self) -> None:
object.__setattr__(self, "_ports",
(Port(self, "a", PortRole.NODE), Port(self, "b", PortRole.NODE)))
def spice_card(self, net_of) -> str:
a, b = self.ports
return f"L{self.ref} {net_of(a)} {net_of(b)} {self.value}"
```
• Keep ports strongly-typed (PortRole).
• Implement spice_card(net_of) to render the final card.
• Add tests in tests/ (netlist presence & validation).
Coding Standards
• Type hints everywhere (mypy --strict must pass).
• Keep functions pure where possible; avoid global state.
• Small, composable modules. Prefer dataclasses for DTOs.
• Use Ruff to keep formatting consistent.
Tests
• Unit tests for:
• Netlist generation & validation
• Component cards
• Utils (E-series, synth)
• Integration (smoke) tests for NGSpice (skippable if missing).
Run:
```bash
uv run pytest -q --cov=cat --cov-report=term-missing
```
⚙️ Configuration
Environment variables (reserved, to be expanded):
• CAT_SPICE_NGSPICE — override path to ngspice executable.
• CAT_LOG_LEVEL — set logger level (INFO, DEBUG, …) for CAT.
Example:
```bash
export CAT_SPICE_NGSPICE=/opt/tools/ngspice/bin/ngspice
export CAT_LOG_LEVEL=DEBUG
```
🧭 Roadmap (Short)
1. Engines: OP/AC/DC/TRAN with unified result object (TraceSet) and Pandas export.
2. Parsers: NGSpice ASCII/RAW → structured traces (V(node), I(R1)).
3. DSL Style 2: Operators (>> series, | parallel) for fast topologies.
4. DSL Style 3: with schematic(): context and <</>> wiring sugar.
5. Sweeps: Native .STEP + Python multi-param sweeps.
6. Monte-Carlo: Distributions, samplers, parallel execution, metrics to DataFrame.
7. Worst-Case: Corners + constrained optimization (scipy).
8. LTspice adapter: CLI backend + RAW normalizer.
9. Docs website: MkDocs Material with runnable examples.
⸻
❓ Troubleshooting
• ngspice executable not found
Install it and ensure it’s on PATH (see OS-specific steps).
Quick check: which ngspice (Linux/macOS) or where ngspice (Windows).
• Unconnected port: X.Y
You created a component but didn’t connect all ports. Wire every Port to a Net or another Port.
• CI fails on mypy/ruff
Run the commands locally (uv run ruff check ., uv run mypy src) and fix warnings before pushing.
⸻
🤝 Contributing
• Fork → feature branch → PR
• Keep PRs focused and covered by tests.
• Follow the code style and typing rules.
• Add/Update docs or examples where relevant.
Good first issues: adding basic components (L, I sources, diodes), small utils, unit tests.
⸻
📄 License
MIT — see LICENSE.
⸻
🔗 Citation / Acknowledgments
CAT builds on concepts used across the SPICE ecosystem and Python scientific stack (NumPy, Pandas). We’ll add proper acknowledgments as dependencies and integrations grow.
Raw data
{
"_id": null,
"home_page": null,
"name": "pycircuitkit",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "spice, circuit, simulation, ngspice, electronics",
"author": "Luiz Carlos Gili",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/a8/eb/d0d9cd57afadb829b308416b19ed0a05e4a4554e0d8f0c233fd823fe25db/pycircuitkit-0.1.0.tar.gz",
"platform": null,
"description": "# PyCircuitKit (CAT) \u2014 Circuit Analysis Toolkit\n\n[](https://github.com/lgili/PyCircuitKit/actions/workflows/ci.yml)\n[](https://lgili.github.io/PyCircuitKit/)\n\nModern, strongly-typed Python toolkit to **define**, **simulate** (.OP / .TRAN / .AC) and **analyze** electronic circuits with a clean, Pythonic API. CAT targets real engineering workflows: parameter sweeps, **Monte Carlo**, worst\u2011case, and painless result handling in NumPy/Pandas.\n\nDocumentation: https://lgili.github.io/PyCircuitKit/\n\n> **Status:** MVP \u2014 Circuit DSL (Ports & Nets), NGSpice (CLI) `.op/.tran/.ac`, LTspice netlist import (includes `.include/.param`, V/I PULSE/SIN/PWL), controlled sources (E/G/F/H) and switches, Monte\u2011Carlo, and metrics/plots. Roadmap: worst\u2011case refinements, RAW binary, more examples.\n\n---\n\n## Documentation\n- Site: https://lgili.github.io/PyCircuitKit/\n- Getting Started: https://lgili.github.io/PyCircuitKit/getting-started/\n- Guides: Monte Carlo (https://lgili.github.io/PyCircuitKit/monte-carlo/) \u00b7 AC Stability (https://lgili.github.io/PyCircuitKit/ac-stability/)\n- Examples: https://lgili.github.io/PyCircuitKit/examples/\n- Examples Gallery: https://lgili.github.io/PyCircuitKit/examples-gallery/\n\n---\n\n## Quickstart (1 min)\n```python\nfrom cat import Circuit, R, C, V, GND, run_tran\n\nc = Circuit(\"rc\")\nV1, R1, C1 = V(5.0), R(\"1k\"), C(\"100n\")\nc.add(V1, R1, C1)\nc.connect(V1.ports[0], R1.ports[0])\nc.connect(R1.ports[1], C1.ports[0])\nc.connect(V1.ports[1], GND)\nc.connect(C1.ports[1], GND)\n\ndf = run_tran(c, \"10us\", \"5ms\", return_df=True)\nprint(df.head())\n```\n\n---\n\n## Dev shortcuts (Makefile)\n\n```bash\n# 1) Create venv and install in editable mode\nmake install\n\n# 2) Run the circuit preview example (prints connectivity and generates preview.svg/.dot)\nmake preview\n\n# If you prefer without venv (uses PYTHONPATH=src)\nmake preview-ci\n\n# Install plotting extras (Matplotlib) for figure examples\nmake install-extras\n\n# Run plotting/simulation examples (require NGSpice in PATH)\nmake ac-bode\nmake step-fig\nmake mc-fig\nmake opamp-stability\n\n# Run all figure examples\nmake examples\n```\n\nInstall Graphviz to render the SVG preview (macOS: `brew install graphviz`, Ubuntu: `sudo apt install -y graphviz`).\n\n---\n\n## \u2728 Features (MVP)\n\n- **Zero-string connectivity:** connect **Port \u2194 Net** objects (type-safe, IDE-friendly).\n- **Core components:** `Resistor`, `Capacitor`, `Vdc` (more soon).\n- **Netlist builder:** generate SPICE netlists with topology validation.\n- **NGSpice (CLI) runner:** headless `.op` smoke execution (skips automatically if NGSpice is missing).\n- **Utilities for design:**\n - **E-series** enumerator & rounding (E12/E24/E48/E96).\n - **RC low-pass** design helper by target `f_c`.\n\n### Highlights\n- **AC/DC/TRAN** via NGSpice (CLI).\n- **LTspice import**: handles `.include/.param`, V/I PULSE/SIN/PWL, controlled sources (E/G/F/H), diode D, simple `.SUBCKT` flatten.\n- **Monte Carlo**: parallel, deterministic order; DataFrame stacking.\n- **Metrics/Plots**: AC (Bode/PM/GM) e tran (rise/fall/settling/overshoot).\n\n---\n\n## \ud83e\uddf0 Installation\n\n### Requirements\n- Python **3.10+**\n- pip / virtualenv (or **uv** / **poetry**)\n- **NGSpice** (recommended for simulation; optional for building & unit tests)\n\n> LTspice support is planned. For now, NGSpice is the reference backend.\n\n### macOS (pip)\n\n```bash\n# 1) Install NGSpice\nbrew install ngspice\n\n# 2) Clone and set up the project\ngit clone https://github.com/lgili/PyCircuitKit.git\ncd pycircuitkit\npython -m venv .venv\nsource .venv/bin/activate\npip install -U pip\npip install -e .\npip install ruff mypy pytest pytest-cov\n```\n\n> Optionally, add `matplotlib` and `pandas` for plotting/stacking examples.\n\n### Linux (Ubuntu/Debian)\n```bash\n# 1) Install NGSpice\nsudo apt update\nsudo apt install -y ngspice\n\n# 2) Clone and set up\ngit clone https://github.com/lgili/PyCircuitKit.git\ncd pycircuitkit\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -U pip\npip install -e .\npip install ruff mypy pytest pytest-cov\n```\n\n### Windows (PowerShell)\n```powershell\n# 1) Install NGSpice\n# Download installer from: https://ngspice.sourceforge.io/download.html\n# Add the ngspice bin folder (e.g. C:\\Program Files\\Spice64\\bin) to your PATH.\n\n# 2) Clone and set up\ngit clone https://github.com/lgili/PyCircuitKit.git\ncd pycircuitkit\npy -m venv .venv\n.venv\\Scripts\\activate\npip install -U pip\npip install -e .\npip install ruff mypy pytest pytest-cov\n```\n\n### Alternative without uv (pip-only):\n```powershell\npy -m venv .venv\n.venv\\Scripts\\activate\npip install -U pip\npip install -e \".[opt]\"\npip install -r dev-requirements.txt\n```\n\nIf ngspice is not on your PATH, tests that require it will auto-skip.\n\n## \ud83d\ude80 Quick Start (User Guide)\n\n### 1) Define a circuit (Style 1: Ports & Nets) and run **.TRAN**\n```python\nfrom cat.core.circuit import Circuit\nfrom cat.core.net import Net, GND\nfrom cat.core.components import Vdc, Resistor, Capacitor\nfrom cat.analysis import TRAN\n\n# Circuit: RC low\u2011pass\nc = Circuit(\"rc_lowpass\")\nvin = Net(\"vin\")\nvout = Net(\"vout\")\n\nV1 = Vdc(\"1\", 5.0)\nR1 = Resistor(\"1\", \"1k\")\nC1 = Capacitor(\"1\", \"100n\")\n\nc.add(V1, R1, C1)\nc.connect(V1.ports[0], vin)\nc.connect(V1.ports[1], GND)\nc.connect(R1.ports[0], vin)\nc.connect(R1.ports[1], vout)\nc.connect(C1.ports[0], vout)\nc.connect(C1.ports[1], GND)\n\nres = TRAN(\"10us\", \"5ms\").run(c)\nts = res.traces\nprint(\"traces:\", ts.names)\n```\n\n### 2) **Monte Carlo** on the same circuit\n```python\nfrom cat.analysis import OP, monte_carlo, NormalPct\n\n# Varia apenas R1 com 5% (sigma) \u2014 16 amostras\nmc = monte_carlo(\n circuit=c,\n mapping={R1: NormalPct(0.05)},\n n=16,\n analysis_factory=lambda: OP(),\n seed=123,\n)\n# Empilha em DataFrame (se quiser)\nfrom cat.analysis import stack_runs_to_df\nprint(stack_runs_to_df(mc.runs).head())\n```\n\n### 2.1) Monte Carlo to DataFrame (metrics)\n```python\n# Map metrics per run (e.g., last value of vout)\nfrom cat.analysis.core import AnalysisResult\n\ndef metrics(res: AnalysisResult) -> dict[str, float]:\n return {\"vout\": float(res.traces[\"v(n1)\"].values[-1])}\n\ndf = mc.to_dataframe(metric=metrics, param_prefix=\"param_\")\nprint(df.head())\n```\nOptionally, extract trace values at a given time for each trial:\n```python\ndf2 = mc.to_dataframe(metric=None, y=[\"v(n1)\"], sample_at=1e-3) # t = 1 ms\n```\n\n### 3) Ideal Op-Amp (OA) and topology helpers\n```python\nfrom cat import GND, Circuit, opamp_inverting\nfrom cat.core.components import V, R\n\nc = Circuit(\"opamp_inv\")\nV1 = V(1.0)\nc.add(V1)\nvin = V1.ports[0]\nload = R(\"1k\"); c.add(load)\nvout = load.ports[0]; c.connect(load.ports[1], GND)\n\n# Inverting amplifier: gain = -Rf/Rin = -100k/10k\nopamp_inverting(c, inp=vin, out=vout, ref=GND, Rin=\"10k\", Rf=\"100k\", gain=1e6)\n```\nThe helper `opamp_buffer(c, inp, out)` wires a voltage follower.\n\n### 4) Switches (S/W) with .model\n- Voltage-controlled: `SW(\"SWMOD\")` \u2192 `Sref p n cp cn SWMOD` (requires `.model SWMOD VSWITCH(...)`).\n- Current-controlled: `SWI(\"V1\",\"WMOD\")` \u2192 `Wref p n V1 WMOD` (requires `.model WMOD ISWITCH(...)`).\nAdd directives with `circuit.add_directive(\".model ...\")`.\n\n### 3) Importar netlist do **LTspice** e simular\nExport no LTspice: *View \u2192 SPICE Netlist* \u2192 salve como `.cir`/`.net`.\n```python\nfrom cat.io.ltspice_parser import from_ltspice_file\nfrom cat.analysis import TRAN\n\nc2 = from_ltspice_file(\"./my_filter.cir\")\nres2 = TRAN(\"1us\", \"2ms\").run(c2)\nprint(res2.traces.names)\n```\n\n### 4) Utilities (E\u2011series & RC helper)\n```python\nfrom cat.utils.e_series import round_to_series\nfrom cat.utils.synth import design_rc_lowpass\n\nprint(round_to_series(12700, \"E96\"))\nprint(design_rc_lowpass(fc=159.155, prefer_R=True, series=\"E24\"))\n```\n\n## \ud83d\udce6 Project Layout\nsrc/cat/\n core/ # Nets, Ports, Components, Circuit, netlist builder\n analysis/ # OP/AC/DC/TRAN, metrics, sweep/step/montecarlo, viz\n spice/ # Simulator adapters + registry (ngspice_cli)\n io/ # RAW/LOG parsers, LTspice import/flatten\n utils/ # e_series, units, synth, logging, topologies\n dsl/ # chain/parallel helpers and schematic ctx manager\ntests/ # pytest suite (unit + smoke if ngspice available)\n\n\u2e3b\n\n\ud83d\udee0\ufe0f Developer Guide\n\nTooling\n\nWe ship configs for ruff (lint & format), mypy (strict typing), pytest (tests & coverage), and pre-commit.\n\nInstall dev tools:\n```bash\nuv sync --all-extras --dev\npre-commit install\n```\n\nRun checks locally:\n```bash\nruff check .\nruff format --check .\nmypy --explicit-package-bases src\npytest -q\n```\n\nCI (GitHub Actions) runs the same steps via pip. NGSpice smoke tests are skipped if ngspice isn\u2019t present on the runner.\n\nAdding Components\n\nCreate a class in cat/core/components.py:\n\n```python\nfrom dataclasses import dataclass\nfrom .net import Port, PortRole\nfrom .components import Component\n\n@dataclass\nclass Inductor(Component):\n def __post_init__(self) -> None:\n object.__setattr__(self, \"_ports\",\n (Port(self, \"a\", PortRole.NODE), Port(self, \"b\", PortRole.NODE)))\n\n def spice_card(self, net_of) -> str:\n a, b = self.ports\n return f\"L{self.ref} {net_of(a)} {net_of(b)} {self.value}\"\n```\n\n\t\u2022\tKeep ports strongly-typed (PortRole).\n\t\u2022\tImplement spice_card(net_of) to render the final card.\n\t\u2022\tAdd tests in tests/ (netlist presence & validation).\n\nCoding Standards\n\t\u2022\tType hints everywhere (mypy --strict must pass).\n\t\u2022\tKeep functions pure where possible; avoid global state.\n\t\u2022\tSmall, composable modules. Prefer dataclasses for DTOs.\n\t\u2022\tUse Ruff to keep formatting consistent.\n\nTests\n\t\u2022\tUnit tests for:\n\t\u2022\tNetlist generation & validation\n\t\u2022\tComponent cards\n\t\u2022\tUtils (E-series, synth)\n\t\u2022\tIntegration (smoke) tests for NGSpice (skippable if missing).\n\nRun:\n\n```bash\nuv run pytest -q --cov=cat --cov-report=term-missing\n```\n\n\u2699\ufe0f Configuration\n\nEnvironment variables (reserved, to be expanded):\n\t\u2022\tCAT_SPICE_NGSPICE \u2014 override path to ngspice executable.\n\t\u2022\tCAT_LOG_LEVEL \u2014 set logger level (INFO, DEBUG, \u2026) for CAT.\n\nExample:\n```bash\nexport CAT_SPICE_NGSPICE=/opt/tools/ngspice/bin/ngspice\nexport CAT_LOG_LEVEL=DEBUG\n```\n\n\ud83e\udded Roadmap (Short)\n\t1.\tEngines: OP/AC/DC/TRAN with unified result object (TraceSet) and Pandas export.\n\t2.\tParsers: NGSpice ASCII/RAW \u2192 structured traces (V(node), I(R1)).\n\t3.\tDSL Style 2: Operators (>> series, | parallel) for fast topologies.\n\t4.\tDSL Style 3: with schematic(): context and <</>> wiring sugar.\n\t5.\tSweeps: Native .STEP + Python multi-param sweeps.\n\t6.\tMonte-Carlo: Distributions, samplers, parallel execution, metrics to DataFrame.\n\t7.\tWorst-Case: Corners + constrained optimization (scipy).\n\t8.\tLTspice adapter: CLI backend + RAW normalizer.\n\t9.\tDocs website: MkDocs Material with runnable examples.\n\n\u2e3b\n\n\u2753 Troubleshooting\n\t\u2022\tngspice executable not found\nInstall it and ensure it\u2019s on PATH (see OS-specific steps).\nQuick check: which ngspice (Linux/macOS) or where ngspice (Windows).\n\t\u2022\tUnconnected port: X.Y\nYou created a component but didn\u2019t connect all ports. Wire every Port to a Net or another Port.\n\t\u2022\tCI fails on mypy/ruff\nRun the commands locally (uv run ruff check ., uv run mypy src) and fix warnings before pushing.\n\n\u2e3b\n\n\ud83e\udd1d Contributing\n\t\u2022\tFork \u2192 feature branch \u2192 PR\n\t\u2022\tKeep PRs focused and covered by tests.\n\t\u2022\tFollow the code style and typing rules.\n\t\u2022\tAdd/Update docs or examples where relevant.\n\nGood first issues: adding basic components (L, I sources, diodes), small utils, unit tests.\n\n\u2e3b\n\n\ud83d\udcc4 License\n\nMIT \u2014 see LICENSE.\n\n\u2e3b\n\n\ud83d\udd17 Citation / Acknowledgments\n\nCAT builds on concepts used across the SPICE ecosystem and Python scientific stack (NumPy, Pandas). We\u2019ll add proper acknowledgments as dependencies and integrations grow.\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "PyCircuitKit (CAT): Modern, strongly-typed Python toolkit for SPICE circuit definition, simulation and analysis.",
"version": "0.1.0",
"project_urls": {
"Documentation": "https://lgili.github.io/PyCircuitKit/",
"Homepage": "https://github.com/lgili/PyCircuitKit",
"Issues": "https://github.com/lgili/PyCircuitKit/issues",
"Repository": "https://github.com/lgili/PyCircuitKit.git"
},
"split_keywords": [
"spice",
" circuit",
" simulation",
" ngspice",
" electronics"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "9570421a2a733c5d0cd58611dc6eff8293ba0ba69ea9361ba90093e13a6ac3f3",
"md5": "92f8e9925359fbb76497f1066afc509b",
"sha256": "d7f8bc9c58381168f1cebfc245b3feeb044386aaf6c9d7ba882242eec0f00dcf"
},
"downloads": -1,
"filename": "pycircuitkit-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "92f8e9925359fbb76497f1066afc509b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 58675,
"upload_time": "2025-09-13T01:58:45",
"upload_time_iso_8601": "2025-09-13T01:58:45.697170Z",
"url": "https://files.pythonhosted.org/packages/95/70/421a2a733c5d0cd58611dc6eff8293ba0ba69ea9361ba90093e13a6ac3f3/pycircuitkit-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "a8ebd0d9cd57afadb829b308416b19ed0a05e4a4554e0d8f0c233fd823fe25db",
"md5": "75a83f1f25e9781305e0930377d6de7c",
"sha256": "55866d4b37138df57da2af750e247dd48a943375e5358e446c5a8f6f654db778"
},
"downloads": -1,
"filename": "pycircuitkit-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "75a83f1f25e9781305e0930377d6de7c",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 76014,
"upload_time": "2025-09-13T01:58:47",
"upload_time_iso_8601": "2025-09-13T01:58:47.002141Z",
"url": "https://files.pythonhosted.org/packages/a8/eb/d0d9cd57afadb829b308416b19ed0a05e4a4554e0d8f0c233fd823fe25db/pycircuitkit-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-13 01:58:47",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lgili",
"github_project": "PyCircuitKit",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pycircuitkit"
}