Custom tools and overlays
Run your own tools on a project and draw their results on the board; the add-on API.
A field overlay is a regular grid drawn over the board as a colour-mapped layer, with a legend and probes. Electronics Designer: Load simulation overlay… loads one by hand:
- JSON:
{ "name", "unit", "origin": [x, y], "pitch": [dx, dy], "cols", "rows", "values": [...] }in board mm (originis the corner of cell 0 at min x / min y; values row by row). Seeexamples/sample-project/sim/thermal.json. - CSV:
x,y,valueorx,y,vx,vyrows.
A custom tool runs a program on the board and draws what it produces. Declare tools in the workspace
settings (softforge.edsnx.tools) or in a kicad-tools.json next to the project:
{
"tools": [
{
"id": "thermal",
"name": "Thermal (toy model)",
"command": "node",
"args": ["sim/thermal.mjs", "${board}", "${outputDir}"],
"triggers": ["manual", "onSave"],
"overlays": [{ "kind": "field", "file": "thermal.json", "unit": "°C", "colormap": "inferno" }]
}
]
}Tools appear in the Tools view and run on demand or on their triggers (onSave, onOpen, onChange,
onDrc), with progress, cancel and a log. ${board}, ${schematic}, ${projectDir}, ${outputDir}
(default sim/<tool id>), ${netlist}, ${gerbers}, ${python}, ${kicadCli} and more are substituted.
Overlay kinds: field (JSON, CSV, VTK, openEMS HDF5), markers (DRC-style markers), geometry (lines and
polygons), heat (per-point values splatted into a map), panel (charts) and webview (the tool’s own
HTML panel). The settings editor validates the configuration and completes it. Extensions can register
tools and overlay importers through the extension’s API (docs/architecture.md §7, §7b).
Field-solver tools (2.1.0). The extension registers two runnable tools through the same API: openEMS ·
S-parameters of the net and Elmer · E field of the net (they run on the nets selected in the editor). Each detects
its solver when the editor starts (openEMS: the openEMS executable or its Python bindings; Elmer: ElmerSolver and
ElmerGrid, with gmsh). When it is not installed the tool is listed as (not installed) with the reason and an owner
note — what to install (openEMS from docs.openems.de, Elmer FEM from elmerfem.org and gmsh), these are external
installs the Electronics Designer does not bundle — and running it reports that instead of producing a fake result. Installed, the
openEMS tool writes the hand-off of the selected nets, runs it and reads the port voltage and current probes back
into S-parameters (shown in the S-parameter card); the Elmer tool runs the case and loads the newest VTU result as a
field overlay. The examples/tools/openems-antenna and elmer-thermal scripts follow the same pattern: --detect
prints what is installed (exit 3 when not), --require-solver refuses to fall back to their synthetic demo output.
The add-on API#
Other VS Code extensions extend this one through the object its activate() returns. Besides overlays, tools,
timeline and edsnx, it has documents (list the open KiCad documents with their model and text, apply edit
intents as undoable edits, undo, onDidChange), models3d (registerProvider: supply the 3D models kicad-cli
cannot find, as a file, a URL or bytes; cached), libraries (list, search, preview and read symbols and
footprints), checks (run ERC/DRC, the last report, onReport) and interop (2.0.0: registerImporter /
registerExporter for more file formats, importers(), exporters(), import(), export(); see
Import and export). The typings are published as
@softforge/edsnx-api/addon; examples/addon-sample is a complete add-on (a field importer, a tool, a 3D model
provider and report logging).
Time axes and live frames#
A field with several frames (a transient, a frequency sweep, solver steps) plays on the editor’s timeline
(see Playback). timeAxis on an overlay describes its frames:
{ "id": "e", "kind": "field", "file": "efield.h5", "unit": "V/m",
"timeAxis": { "kind": "time", "unit": "ns", "label": "t", "interpolation": "linear", "offset": 0, "scale": 1 } }kind:time(default),frequency,steporphase;unit:s,ms,us,ns,ps,Hz,kHz,MHz,GHz,deg,rad(the frame times in the file are in this unit).interpolation:linearblends the two frames around the playhead (fields),nearestpicks the closer one,holdkeeps the last frame at or before the playhead (markers, geometry).offsetandscaleplace the overlay on the shared timeline: timeline t = file t × scale + offset (in seconds, Hz or steps), so two runs with different start times play side by side.log: truedraws the scrub bar on a log scale (frequency sweeps).true/falseand a column name still work:trueis a plain time axis,falsekeeps the last frame only.
Live frames. With "live": true the overlay shows frames while the tool still runs; the timeline grows
and its LIVE badge follows the newest frame. A tool sends frames in either way:
- a line on stdout per frame:
@kicad frame {"overlay": "e", "t": 1.2e-9, "file": "frames/e_0012.vtk"}(path relative to the output folder, any field format; its last frame is used) or with the samples inline:@kicad frame {"overlay": "e", "t": 1.2e-9, "values": [...]}; the first inline frame of an overlay also carries the grid ("cols","rows","origin","pitch", optionally"components","nz","name","unit"). - numbered files appearing in the output folder that match the overlay’s
fileglob ("file": "frames/e_*.vtk"): each file is taken once its size stops changing; t is the file’s own time when it has one, else the last number in its name.
When the run ends the overlay becomes a normal series (no LIVE). Extensions push frames with
api.overlays.pushFrame(board, overlayId, { t, values | file, field? }) (docs/architecture.md §7b). See
examples/tools/live-gaussian (live) and examples/tools/openems-antenna (a frequency axis).
Files with many frames. HDF5 (openEMS dumps, chunked datasets), VTK series (.pvd, numbered .vtk /
.vti / .vtr / .vts / .vtu files: point the overlay’s file at the .pvd or a glob), CSV with a
t column and JSON with one values array per frame all play. Series larger than
softforge.edsnx.overlays.inlineFramesMb (32 MB) stay on the extension host, which reads frames on demand
(overlays.hostCacheMb, 512 MB of decoded frames); the editor keeps a window of frames around the
playhead (overlays.memoryMb, 256 MB) and receives them as 32-bit floats, half floats or 8-bit
(overlays.frameEncoding, auto by default). overlays.defaultInterpolation sets how fields blend
frames when the overlay does not say. A numbered series whose mesh changes from file to file (adaptive
meshing) is read with each file’s own mesh and resampled onto the first file’s grid (bilinear in the plane,
the nearest plane in z, empty outside the mesh); a live frame on another grid is resampled the same way.
Unstructured grids (.vtu, legacy UNSTRUCTURED_GRID) carry point data and cell data (a value per cell,
placed at the cell centroid). HDF5 datasets with an unlimited dimension (extensible-array and v2 B-tree chunk
indexes, filtered or not) are read like fixed-size chunked ones. Complex fields streamed from the host are
probed lazily: a probe asks the host for its point over every frame instead of waiting for the frames to load.