sp2Sch.py

Reads a SPICE deck and draws it as a schematic you can read, rearrange and save — so a manufacturer's model becomes a circuit you can follow.

Revision21Sep26b
LicenseMIT
RequiresPython 3.9+

Introduction

Licensing

sp2Sch.py is open source under the MIT license. Use it, change it, ship it, sell it — keep the copyright notice with it.

If you want a feature it does not have, or you would rather it behaved differently, change it. Your own edits, an AI's, or any mix of the two: that is what the license is for.

If you do modify it, add your own copyright line to the license block at the top of the script, under the existing one. The MIT license asks you to keep the original notice, not to replace it — both lines stand together, and the work you did is yours:

# Copyright © 2026 Carl L. Wuebker and Claude.ai
# Copyright © 2026 Your Name

Almost all of this source was written by Claude.ai. It is tested against the four decks below, but a program written this way can still be wrong in ways nobody has looked for yet. Check what it draws against the netlist before you trust it.

The MIT license

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Installation

1 — The script

sp2Sch.py is a single file. There is nothing to install and no third-party packages to fetch — just download it and keep it wherever you like.

Download sp2Sch.py

You need Python 3.9 or later, with Tk. Check what you have:

python3 --version          # Linux and macOS
python --version           # Windows

Anything below 3.9 will not run it. Tk (the tkinter module) is what draws the window; the test below should open a small empty window and print a version number:

python3 -m tkinter         # Linux and macOS
python -m tkinter          # Windows

2 — Linux

Most distributions ship Python 3 already but leave Tk out of the base install. If python3 -m tkinter fails:

sudo apt-get install -y python3-tk          # Debian, Ubuntu, Mint
sudo dnf install -y python3-tkinter         # Fedora, RHEL
sudo pacman -S tk                           # Arch

Then make the script executable and run it:

chmod +x sp2Sch.py
./sp2Sch.py LM324.lib -s LM324

3 — Windows 10 and 11

Untested. sp2Sch.py uses only the Python standard library and Tk, and it discovers a Windows KiCad install on purpose, so it is written to run here — but nobody has actually run it on Windows yet. Expect rough edges, and please report what you hit.
cd C:\Users\you\spice
python sp2Sch.py LM324.lib -s LM324

If python is not recognised, either the PATH box was not ticked during installation or you want the launcher instead:

py -3 sp2Sch.py LM324.lib -s LM324

4 — KiCad symbols

The bodies of the parts come from KiCad's symbol libraries, so you need two of them on disk:

Device Device.kicad_sym — resistors, capacitors, inductors, diodes, transistors.
Simulation_SPICE Simulation_SPICE.kicad_sym — the V, I, E, G and B source symbols and the switch. Without it, half a behavioral model draws as empty boxes.

Either KiCad 9 or KiCad 10.0.5 works. KiCad 10 splits each library into a Device.kicad_symdir/ directory instead of one file; sp2Sch.py detects the split layout and prefers it when both are present.

Getting them

KiCad's libraries are licensed separately from sp2Sch.py, so this page links to them rather than shipping copies. Get them from KiCad or from the library repository and keep whatever licence and attribution come with them.

Where sp2Sch.py looks

With no configuration, the search order is:

If your symbols live somewhere else, point SP2SCH_SYMBOL_DIR at them. It is searched first, ahead of even the current directory, so it overrides everything, and it takes a list separated by the platform's path separator — : on Linux and macOS, ; on Windows:

# Linux / macOS
export SP2SCH_SYMBOL_DIR=$HOME/kicad-symbols
export SP2SCH_SYMBOL_DIR=$HOME/kicad10/symbols:$HOME/extra-symbols

# Windows, PowerShell
$env:SP2SCH_SYMBOL_DIR = "C:\kicad-symbols"
$env:SP2SCH_SYMBOL_DIR = "C:\kicad-symbols;C:\extra-symbols"

# Windows, Command Prompt
set SP2SCH_SYMBOL_DIR=C:\kicad-symbols

sp2Sch.py also honours KiCad's own KICAD10_SYMBOL_DIR, KICAD9_SYMBOL_DIR and KICAD8_SYMBOL_DIR, so a machine whose KiCad is already configured usually needs no extra setup. Those rank below ., so a copy bundled with a project still wins.

5 — Test decks

These four are the decks the program is developed and regression-tested against. All four are vendor SPICE models; the download sits on the product page under Design & development or Tools & software.

These are the manufacturers' models, licensed separately from sp2Sch.py — which is why this page links to the product pages instead of carrying copies of the files. Each vendor sets its own terms for using and redistributing its model.

Expect to sign in. Most manufacturers put SPICE models behind a free account, and the sign-in can fail for reasons that have nothing to do with you — an outage, a blocked region, a browser the site dislikes. If a download refuses, try again later or from another browser; sp2Sch.py runs perfectly well on any SPICE deck you already have.
FileCircuitSource
LM324.lib Quad op-amp, behavioral macromodel — the smallest of the four and the easiest first run. ti.com/product/LM324
LM324.sub The same amplifier as a transistor-level model — a Darlington input pair, current mirrors and real supply rails. onsemi.com — LM324
LP2951.lib Adjustable low-dropout regulator, with an error amplifier, a reference and a comparator inside. ti.com/product/LP2951
OPAx197.LIB Precision op-amp. The largest deck, and the one most of the layout work is measured on. ti.com/product/OPA197

6 — Run it

Use ./sp2Sch.py on Linux and macOS, python sp2Sch.py on Windows. Everything after that is the same.

# open a file chooser
./sp2Sch.py

# open a deck and elaborate its largest .SUBCKT
./sp2Sch.py LM324.lib

# open one named .SUBCKT out of a file that defines several
./sp2Sch.py LM324.lib -s LM324
./sp2Sch.py OPAx197.LIB --subckt OPAX197
./sp2Sch.py LP2951.lib -s=LP2951

# ignore the saved LP2951.lib.LP2951.pr.json and place fresh
./sp2Sch.py -n LP2951.lib -s LP2951

# run the self-check harness on a deck and exit, no window
./sp2Sch.py -v OPAx197.LIB -s OPAX197
Do not name a single .kicad_sym file on the command line unless you mean it. sp2Sch.py accepts one, but it then loads only that library — and a single file never holds both the passives and the SPICE source symbols. Leave it off and the standard libraries are merged, which is what you normally want. ./sp2Sch.py -h lists every option.

How to use sp2Sch.py

The loop: place, correct, place again

The first placement is a guess built from the netlist alone. Everything you do afterwards is telling the placer something it could not work out, then asking it to try again.

A flow worth adopting: keep two files

Once you have corrected a circuit's net types and pin directions, that work is worth more than any one layout — it makes every future Place better, while a hand-tuned layout is just one arrangement you happened to like. Saving them as two separate files lets you keep both, and choose which one you start from.

Next time you open the deck, the default file loads by itself and hands the placer your corrected roles, but the layout is computed fresh — so you see what the placer now makes of the circuit, which is exactly what you want while you are still improving the roles. When you would rather have your own arrangement back, Open P&R… and pick the _place file.

There is no separate roles-only save. Save P&R… notices when nothing is placed and writes the file as roles only, so Forget placement followed by Save P&R… is how you get one.

Moving and orienting parts

Move a part Drag it with the left button. If it belongs to a selected group, the whole group moves with it.
Rotate a part Right-click it. Each click turns it 90° counter-clockwise, so four clicks return it to where it started.
Mirror a part Shift + right-click it. This flips it about its vertical axis — useful when a part is lying the right way round but its input pin faces the wrong side. The status line says flipped or unflipped.
Select several parts Drag in empty space to rubber-band. Every instance and T-symbol whose centre falls inside the rectangle joins the group, and dragging any member moves them all together.
Clear the selection Right-click in empty space, or press Esc.
Pull a group together Select the parts, then press Compact sel. They move up, then left, each stopping a small gap short of a selected part or of anything else in the way.
Make room in a group Select the parts, then press Spread sel. One typical part width opens between columns and one typical height between rows, so there is space to drop parts in. Order is kept.
Close empty bands Close gaps ↕ removes tall empty horizontal bands; everything below a band moves up together, so the drawing keeps its shape.
Undo your hand work Forget placement discards manual moves and rotations but keeps your net and pin roles. Press Place… for a fresh automatic layout.
Scroll and pan Mouse wheel scrolls vertically; drag with the middle button to pan in any direction.

Net names

A net name is a small label sitting on a flight line. A net with several connections gets one label by default, on the midpoint of its longest segment; you can add more wherever the drawing needs them.

Add a net name Left-click the flight line at the point where you want the label. A new label appears there.
Move a net name Drag the label with the left button.
Delete a net name Left-click the label. It disappears — a click on a label deletes, a click on the line adds.
Reset a net's labels Double-click the label, or the flight line, to put that net's labels back at their default position.

Net roles

A net's role is what tells the placer where the net belongs: inputs enter from the left, outputs leave to the right, +power goes to the top, ground and -power to the bottom.

There are five types and only four rotations. The five are +power, ground, -power, input and output; a T-symbol has four 90° positions. Ground and -power share one of them, because both belong at the bottom of the sheet and both are drawn the same way. That single overlap is the whole difference between the two ways of setting a role:

Rotating the T-symbol Sets four of the five: +power, input, output, and the bottom-of-sheet role. It cannot tell ground from -power, so a net you turn to the bottom position becomes ground.
The Nets button Sets all five, -power included. Any role you can reach by rotating you can also set here.

Both write the same setting, so use whichever is quicker for the net in front of you.

From the Nets dialog

By rotating the net's T-symbol

If a circuit has a genuine negative supply, set it from the Nets dialog. Left as ground it still lands at the bottom of the sheet and the drawing looks right, but the placer treats a negative rail and ground as the same thing, and a part that should sit between the two rails may not.

Pin roles: driver and receiver

Change a pin's role Ctrl + left-click the pin. Each click moves it one step round auto → driver → receiver → auto.
See what changed The arrow on the pin updates immediately, and an overridden pin is drawn with a coloured ring so you can tell your decisions from the placer's.
Make it count Press Place…. A forced role is authoritative — it is used to rank the columns, so it changes the layout, not just the arrow.

Click the dot as you see it on screen: a marker that has been nudged clear of its pin is still the thing you are clicking.

T-symbols

A T-symbol is the stub that carries a net off to a rail or a port instead of drawing a long wire across the sheet. One T can serve one pin or several — a whole ground rail can share a single stub, or every pin can have its own.

Move a T-symbol Drag it with the left button. It stays where you drop it; a T you have moved is not snapped back.
Merge two T-symbols Drag one onto the other and drop it there. They must be on the same net and at the same rotation — merging a +power stub into a ground one would be a worse error than leaving them apart, so it is refused. Dropping one on top of the other is an explicit instruction, so no distance threshold has to guess what you meant.
Split a shared T-symbol Double-click it. Every pin it was serving gets its own stub back. The status line reports how many it became, or says the T is not shared and there is nothing to split.
Change what it means Right-click it to rotate — see Net roles above.

Wires

Flight lines show what the netlist connects. Wires are something you draw yourself, on top, when you want a real route on the page.

Start a wire Left-click a pin.
Route it Each further click adds a Manhattan waypoint.
Finish it Double-click at the end point, or press Enter to commit at the last point. Ending away from a pin leaves a free end.
Cancel it Right-click while drawing, or press Esc.
Delete part of a wire Left-click a segment to select it, then press Delete or Backspace. Removing a middle segment splits the wire in two; removing an end segment shortens it.
Replace a flight line A wire that joins two pins, directly or through other wires, takes the place of the flight line between them: the dashed line and any crossings it caused are gone, and the crossing count drops to match. Delete the wire and the flight line comes back.

Feedback edges

The placer needs a circuit without loops to lay out left to right, so it picks some connections to treat as feedback and leaves them out of the ordering. When it picks the wrong one you can say so.

Force an edge to feedback Right-click the same flight line twice in a row, in the same spot. The edge turns red and is excluded from the next Place, though it is still drawn. Two more clicks force it back to forward.
What it affects Only the one segment you clicked. Other edges on the same net are untouched. The setting survives Forget placement and is written by Save P&R….
Arrow direction A single right-click on a flight line cycles its arrow auto → forward → reverse → none, which changes the drawing only.

Saving and reopening

Save P&R… Writes everything: positions, rotations, mirrors, T-symbols, wires, labels and all the net and pin roles.
Roles only Forget placement, then Save P&R…. With nothing placed the file holds the roles only, so your classification survives while the layout is derived fresh each time.
Automatic reopening Keep the file beside the deck under the name the save dialog suggests — <deck>.<SUBCKT>.pr.json — and the next run loads it without being asked. Each .SUBCKT in a file gets its own name, so placing two of them does not overwrite one with the other.
Open P&R… Loads a layout, or a roles-only file, from anywhere.
Start fresh Launch with -n to skip the automatic load. The saved file is left untouched and Open P&R… still loads it on demand.
A saved file is tied to the library it was made with. A file saved against KiCad 9 symbols needs KiCad 9 symbols to reload, and likewise for KiCad 10.

T-symbol orientations

Right-click cycles through these four. The rotation is the net's role.

Ground, or 0 rotation 0 Horizontal bar, stem going up, label below the bar.
+Power rotation 180 Horizontal bar, stem going down, label above the bar.
Input rotation 270 Vertical bar, stem going right, label to the left of the bar.
Output rotation 90 Vertical bar, stem going left, label to the right of the bar.

The toolbar

The toolbar wraps onto as many rows as the window needs, so the controls are listed here by group, in their left-to-right order. Help always sits at the right-hand end of the last row.

What is shown

FilterShow only the components whose reference name contains what you type. Useful on a deck of 200 parts.
ColsHow many columns the unplaced Grid view uses.
SUBCKTWhich .SUBCKT, or the top level, to display. Switching here re-reads the circuit.

Placing and files

Open P&R…Load a saved layout, or a roles-only file.
NetsOpen the net list and set net roles.
Pre-groupingGroup tightly connected parts before layering, so each group enters the placer as one unit. Off by default.
Sig TopoLay each cluster out both by signal order and by the default ordering, and keep the better. On by default.
1 chain/rowGive each signal subchain a row of its own.
Place…Run automatic placement now.
Forget placementDiscard manual moves and rotations; net and pin roles are kept.
Save P&R…Save the layout and the roles, or the roles only when nothing is placed.
GridLeave the schematic and show the parts as a plain row-by-row grid — a quick way to see everything the deck contains.
Pre-grouping, Sig Topo and 1 chain/row are inputs to the placer. Changing one never re-places by itself, so a hand layout is safe; the new setting takes effect at the next Place….

Tidying

Close gaps ↕Remove tall empty horizontal bands across the sheet and inside each group.
Compact selPull the selected parts together, up then left.
Spread selOpen space between the selected parts.

Analysis

Floating netsList the nets with no DC path to ground: reached only through capacitors, current sources, MOSFET gates or E and G control inputs. Click an entry to center the view on that net and paint it red. A real floating node is usually a mistake in the deck, or a node the model expects you to drive from outside.
D→R ListEvery net with its drivers and receivers, exactly as the placer classified them — the same classification that draws the pin arrows and orders the columns.
Hidden senseNets that reach an E or G source only through a sense inside its VALUE expression, with no pin to draw. They look under-connected on the sheet; this list says why.

Overlays and display

None of these change the circuit or the placement. They add or remove drawing, so you can see what the program is working from.

Flights Flight lines. The dashed lines showing what the netlist connects — not wires, just the connection drawn as a straight hop from pin to pin. A net with several pins is drawn as a minimum spanning tree, so each pin connects by its shortest route rather than every pin connecting to every other. On by default.
Boxes Clusters. A dotted rectangle around each group of parts the placer treats as one unit. Two parts land in the same cluster when they share a net that is private to them; supply rails and ports cut the circuit into separate clusters. A box overlapping its neighbor is a sign its own members were spread too far apart.
BBoxes Bounding boxes. A blue rectangle around each part showing the space the placer reserved for it: the symbol body, its reference and value text, any T-symbols it owns and their labels. If two parts are drawn touching, their blue boxes show whether the placer knew.
Self-X A magenta ring on any part whose own flight lines cross each other, with a dot on the crossing. On by default; usually empty.
Group boxes A red outline, with its id, around each tight group.
Crossings An orange ring on every counted flight-line crossing. The status bar says how many; the rings say where, which tells a miscount from a crossing that is simply hard to see.
Full text Show VALUE equations in full or truncated. With a group selected it toggles only those parts; with none it toggles all of them.
Help The same guide as this section, inside the app.

Keyboard

EscCancel the wire in progress, or clear the selection.
EnterCommit the wire in progress at its last point.
Delete / BackspaceRemove the selected wire segments.

Command-line options

-h, --helpPrint the usage message and exit.
-s, --subckt NAMEElaborate this .SUBCKT instead of the largest one. -s=NAME and --subckt=NAME also work.
-n, --no-prDo not auto-load the sibling .pr.json at startup; come up on a fresh Place.
-v, --verifyRun the self-check harness and exit. With a netlist, and -s, it verifies that circuit; with none it runs the built-in reference pair.
-g, --rank-gridLabel every part with its rank.order on a small orange chip, showing what the layering decided.
-p, --post-fixupsRun the post-placement fix-up passes. Off by default: what the coordinate assignment computes is what is drawn.
-B, --best-of-bkPlace once per Brandes-Köpf candidate and keep whichever draws the fewest crossings. Six placements instead of one.
-r, --slackPrint the recoverable-flight-line-length table after Place. A development diagnostic.
--svg PATHWrite a placed-block schematic preview to PATH.

Run ./sp2Sch.py -h for the full list, including the comparison switches --no-bk, --no-ports, --no-uncross and -G/--grade.