ThermoDraw
Thermal network diagrams for Python.
Emits SVG. No runtime dependencies.
Junction to still air — conduction, contact, then convection and radiation in parallel.
Eighteen symbols. Mechanism is carried by the interior texture, not by the outline.
The four box textures at twelve angles. A texture belongs to its block and turns with it.
Install
pip install thermodraw
Python 3.10 or later, no dependencies. From a checkout, pip install -e ..
Use
A diagram is data. Write it, or have a model write it, and render it:
from thermodraw import Diagram, save
d = Diagram.from_json(open("hero.json", encoding="utf-8").read())
save(d.svg(), "web.svg") # follows the reader's light/dark
save(d.svg("light"), "word.svg") # colours and font resolved, for Word and slides
The stages are there if you want them — render(layout(d)) is the SVG
before the theme, theme.with_variables and theme.bake are the two ways
to finish it — and a notebook shows a Diagram as its drawing. If your
readers know circuit notation, d.svg(notation="zigzags") draws every
resistance as a zigzag instead of a textured box; nothing else moves. A PNG needs a
rasteriser, which the library does not carry:
import cairosvg
cairosvg.svg2png(bytestring=d.svg("light").encode("utf-8"), write_to="out.png")
Or build it in Python:
from thermodraw import DiagramBuilder
d = (DiagramBuilder(R="K/W", T="°C", P="W")
.node("j", "Junction", 112, at=(200, 150), sub="j")
.node("c", "Case", 78, at=(424, 150), sub="c")
.branch("j", "c", "cond", "Die attach", "0.35")
.source("j", "diss", "Switching loss", 45, sub="d"))
open("out.svg", "w", encoding="utf-8").write(d.svg("light"))
Then find out whether it is any good, without opening it:
thermodraw check hero.json
hero.json: 11 labels placed, 0 errors, 0 warnings, 1 note
note: [parallel-pair-same-side] branch 2 s->amb and branch 3 s->amb run
between the same two nodes and both labels went to the same side
-> set `side` to "down" on the lower of the two
Twelve checks on how the drawing reads — text over text, a label shoved out
past the thing it names, a wire through a symbol, ink off the page. Exit 0
clean, 1 on a warning or an error, 2 when the file could not be read. A note
is advice and does not fail the run — the report above exits 0 — unless you
pass --strict. Every finding names the schema field that fixes it.
--physics asks a different question: whether the numbers agree with each
other — what arrives at each node against what its temperatures and
resistances say leaves. It is opt-in, because a sketch with placeholder
numbers is a diagram too; ask for it when you believe the numbers.
A clean report is not the same as the right diagram, so there is a second question:
thermodraw describe hero.json
hero.json: canvas 1042 x 431, 11 labels
placements: ground x1, node x4, symbol/cap x2, symbol/cond x1,
symbol/contact x1, symbol/conv x1, symbol/diss x1, symbol/rad x1,
wire x15
...then every node with its kind and place, and every label with the direction
it went. check grades the drawing; this says what is in it.
thermodraw render writes the SVG. thermodraw page writes the same drawing
as a self-contained HTML page with its controls — a repeated group of sixteen
draws two and an ellipsis, and the page lets a reader expand it without
anything being rebuilt. thermodraw solve writes a diagram back with every
node placed, to edit from: write the network without coordinates, solve it,
move what you would have put elsewhere. All five work as python -m thermodraw from a checkout.
python examples/render_demo.py # the three images above
python examples/render_reference.py # every symbol at every 45°
pytest
Where this sits
Drawing schematics from Python is not an empty field, and laying out a graph is a solved problem — Graphviz, D2 and Mermaid will place an arbitrary network for you, and schemdraw will draw it in circuit notation with a resistor zigzag for every path. What none of them does is the thing this exists for: say which mechanism each path is, in a notation a thermal engineer reads, and then say whether the drawing reads well and whether its numbers agree with each other.
So the parts that are ThermoDraw's own are the eighteen-symbol vocabulary and
the rule behind it, the label solver, check, describe and --physics.
Node coordinates are solved for a chain of nodes, which is what nearly every
network in this notation is. A general placer for anything else is the part
most likely to be someone else's solved problem, and the design record says
which of the twelve checks it must satisfy, which it minimises, and which it
makes redundant.
If you want circuit notation, use schemdraw. If you want a graph laid out and do not care what the boxes mean, use Graphviz. If you want a thermal network that a reviewer can read from the picture, this.
More
docs/schema.md — the whole format, written to be pasted into a prompt.
docs/stability.md — what 1.0 promises to keep, and what it does not.
docs/symbol-reference.html — every symbol at eight orientations, with the reasoning.
CLAUDE.md — the decisions, one line each.
docs/design-record.md — the argument behind each one.
The symbol vocabulary is settled; labels, wire runs, canvas size and, for a
chain of nodes, the coordinates are solved for you, and thermodraw check
reports what a reader would notice. A network that is not a chain still takes
its coordinates from you, and says so by name.
MIT. The bundled subset of IBM Plex Sans is OFL-1.1.
Metadata
Release files for thermodraw 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| thermodraw-1.0.0.tar.gz | 209.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| thermodraw-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 358.8 kB
Release files / thermodraw-1.0.0.tar.gz
| Download URL | thermodraw-1.0.0.tar.gz |
|---|---|
| Size | 209.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cafdd6af761e9f0c8a73a7ecf170678a37baac09055637e103c9ca70c0b47c73
|
|
BLAKE2b-256 checksum How to use checksums |
c8bfc8254ef7df4137b84db12c2372ef6d7262ce1e336d434f7746bc0ce4bd30
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency logRelease files / thermodraw-1.0.0-py3-none-any.whl
| Download URL | thermodraw-1.0.0-py3-none-any.whl |
|---|---|
| Size | 149.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9b8b4088e76310ec7405394f42abf1618917587224b754cbf67bab635d045f1c
|
|
BLAKE2b-256 checksum How to use checksums |
cb0d1a2a68be797e34dce7a5f5f1415fc1cfa322d207991c2b8df75993dd6fc7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency log