QtCore's libraries (glib, icu) can load while QtWidgets/QtGui still
miss libGL - matplotlib's qt backend imports all three, so the old
probe could promise QtAgg and lose even the error figure at
switch_backend, one library layer deeper than the NixOS fix. The
regression test's mock now mirrors the real failure (bare package and
QtCore import fine, GUI modules raise): both the bare-import and the
QtCore-probe variants now fail it, verified by mutation. Also drop two
redundant f-prefixes on placeholder-less strings in report.py.
Second Mac run (KiCad demo board opened from the mounted installer
image) got past the dialog and died twice:
1. make_output_dir crashed with OSError 30: the demos volume is a
read-only filesystem. Now falls back to a temp directory named
after the board, with the path printed (the Messages panel showed
it is actually read there).
2. The error figure - and every other figure - could never render:
matplotlib refused with Cannot load backend TkAgg ... as qt is
currently running. macOS bundled Python ships tkinter, so the
old tk-first probe picked TkAgg while the PySide6 dialog and
progress window had already made this a Qt process. Windows never
saw it because KiCad Python there has no tkinter. Qt now comes
first - PySide6 is a hard dependency, so it is always there.
Both covered by tests that fail on the old code: the dev env has both
toolkits installed, so the backend-order assertion is exercised for
real, and the RO fallback is simulated by denying mkdir under the
board dir. 140 passed on the dev stack and on the Python 3.9 +
numpy 2.0 / scipy 1.13 / matplotlib 3.9 / PySide6 6.10 stack that a
Mac venv resolves.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Skin resistance is a small fraction of real AC impedance (proximity
and inductance dominate), so AC must not appear in the descriptions.
README headline, PCM/plugin metadata, pyproject, dialog note, CLI
help and the summary label now all say: skin-only lower bound on the
resistance rise, not an AC impedance simulation.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Refuse the uniform contact model when the fills form multiple
disconnected copper groups that each touch both terminals: the
prescribed injection split is ill-posed and the grounded system was
singular, silently returning garbage (e.g. negative gigaohms).
connected_restrict now reports the component count; a power-balance
backstop (SolverError) catches any other inconsistent solve.
- Connect via/pad barrels to the nearest fill copper within the pad
footprint (+1 cell) instead of only the exact center cell, so
thermal-relief spokes still stitch layers; barrels that reach fill on
fewer than two layers are warned about. ViaLink gains pad_nm
(extracted from the padstack, JSON-roundtripped).
- Validate dialog input on OK (layers, current > 0, cell > 0, parseable
frequency, extra Cu >= 0) with an inline error instead of silently
substituting defaults; parse_frequency raises on garbage; pipeline
rejects i_test <= 0; choose_cell_size rejects non-positive overrides.
- Warn when a contact part is dropped by the connectivity restriction;
floor instead of truncate in cell_of; correct the uniform-model
summary line; drop an unused variable; refresh plugin.json wording.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DC/AC resistance, power dissipation, and via/injection-area currents of
copper zone fills. KiCad 10 IPC-API plugin (kicad-python/kipy):
multi-layer via-coupled FDM solver, multi-part terminals via User.1/User.2
marker layers, pads as contacts, uniform-injection and equipotential
contact models, per-foil skin effect, optional solder/copper buildup on
mask openings. 54-case test suite incl. exact analytic references.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>