Skip to content

Releases: klinkdev2026/klayout-klink

0.4.1 — a missing klayout says what to install

Choose a tag to compare

@klinkdev2026 klinkdev2026 released this 19 Aug 01:43

A follow-up to 0.4.0, found by a blind test on the published wheel.

A missing klayout now says what to install. Every other optional
dependency in the imaging domain already failed instructively — numpy,
scipy and pillow all name the pip command. klayout did not, and it is
the hardest of them to diagnose.

An empty klayout directory left somewhere on the path (a stale
install, a py.typed-only folder) is a valid NAMESPACE package, so
import klayout succeeds and only klayout.db fails. The bare error
reads "no module named klayout.db", which tells you the package is
installed and merely incomplete — so you go looking for a broken
sub-module instead of an absent package.

The error now names the interpreter, gives the pip command, and when a
shim really is shadowing the package it says where that directory is
and why the message mentioned klayout.db.

0.4.0 的后续修复,来自对已发布 wheel 的盲测。

缺 klayout 时的报错现在会指路。同一个域里 numpy/scipy/pillow 缺失
都有指路文案,唯独 klayout 本体没有,而它恰恰最难自己诊断:一个空的
klayout 目录留在 path 上就是个合法的 namespace 包,于是 import klayout 成功、只有 klayout.db 失败,报错看起来像"包装了、只是缺个
子模块",把人引向错误的方向。现在报错会点名解释器、给出 pip 命令,
并在确实有空壳顶包时告诉你那个目录在哪、以及为什么报错说的是
klayout.db。

If you are upgrading from 0.3.x, read the 0.4.0 notes — that is where the breaking change is.

0.4.0 — the imaging exits stop shipping a look, and rulers become data

Choose a tag to compare

@klinkdev2026 klinkdev2026 released this 19 Aug 01:43

This release breaks every existing call to the four imaging tools.
They each take a new required style argument. Nothing else changes —
if you do not use imaging.*, upgrading is a no-op.

本版对四个 imaging 工具是破坏性变更:每个都多了必填的 style 参数。
其余部分不受影响,不用 imaging.* 的话升级无感。

Why / 为什么

klink is the mechanism layer. It knew how to build a Principled BSDF, stage a camera, dilate an SEM rim and lay out a page — and it also held the numbers: sun energy, camera lens, film transform, beam blur, grain, page colour, the colour of every atom in a lattice figure. Those are not mechanism. They are taste, tuned by one person against one device, and a library that ships them is deciding what your process looks like.

So klink now ships none of them, and refuses to guess. A render with no style declared is an error naming the file to copy, rather than a picture drawn with somebody else's judgement.

klink 是机制层。它知道怎么搭 BSDF、怎么架相机、怎么画 SEM 边缘增亮、怎么排版一张图——但它同时还攥着一堆数字:太阳能量、镜头焦距、胶片色彩管理、束流模糊、颗粒、页面配色、晶格图里每个原子的颜色。那些不是机制,是某个人对着某台设备调出来的审美;一个库把它们随包发出去,就是在替你的工艺决定长什么样。

所以 klink 现在一个都不带,也不猜。没有声明 style 的渲染会直接报错并指出该抄哪个文件,而不是用别人的判断画一张图给你。

Upgrading in three steps / 三步升级

1. Get the style files. They ship with the package:

klink update            # refreshes example_template/, touches nothing of yours

You now have four files under example_template/imaging/:

file exit
section_style.py imaging.xsection_run (only when render=true)
sem_style.py imaging.sem_top
viewer_style.py imaging.render3d
blender_style.py imaging.blender

Each is a documented walkthrough: every number says what it controls, what happens if you raise or lower it, and where it came from. Copy the ones you need out of example_template/ before editing — klink update refreshes that directory.

2. Turn one into JSON. The MCP tools take a path, not a Python object, and each style file writes its own:

python sem_style.py        # -> sem_style.json

From Python you can skip this and pass the object directly.

3. Pass it.

  imaging.sem_top {
      stack: "stack.json",
+     style: "sem_style.json",
      output_dir: "figs"
  }
- render_sem_png(gds, STACK, "sem.png", out_color="sem_c.png")
+ render_sem_png(gds, STACK, "sem.png", STYLE, out_color="sem_c.png")

A section GDS has no look, so imaging.xsection_run without render still needs no style at all.

三步:klink update 刷出四个 style 文件 → python sem_style.py 生成 JSON → 调用时加 style=。
截面只要 GDS(不加 render)时完全不需要 style。

Two more things that will bite / 另外两个会绊人的地方

Stack layers need a colour. A VisualStack layer must declare color, unless it is kind="lattice" and drawn as atoms. There is no default colour any more.

Lattice figures need their species declared. blender_style.lattice.species must contain an entry for each atom the motif produces (C, or Mo and S). A missing one is an error naming the species and listing the ones you did declare.

层必须声明 color(画成原子的 kind="lattice" 层除外);晶格图必须声明每个原子物种的颜色和半径。

Also new / 顺带新增

  • SEM views get a scale bar. There was previously no way to ask for one, in a picture calling itself an SEM view. It rounds to a 1/2/5 length and sits on a contrast plate so it stays readable over bright metal.
  • window_um magnifies. width_px only ever added pixels to the same field of view — which is why the scale bar never changed with it. A window changes the field, and the bar follows.
  • z_window_um and axis reach the cross-section tool. Without a window the engine's multi-micron substrate fills the frame and your device is a hairline across the top. This is the single most common reason a section looks wrong.
  • Rulers are data. annotation.list / get / insert / update / delete / clear / measure. A ruler lives in the view, not the layout — invisible to selection.get and to any saved GDS — so these are the only way to read one. imaging.xsection_run cut_from_ruler=true sections along the ruler you drew. A multi-segment ruler is refused with its segments listed rather than quietly flattened to a line you never drew.

Fixed / 修复

  • The die render decided for itself what was metal. A luminance guess metallised 11 of 15 materials in a plain CMOS stack — the pale things there are substrate, wells, implants and oxides, while tungsten and silicide are dark — and since a metallic surface does not read as see-through it also defeated declared transparency, hiding every plug inside an opaque dielectric.
  • A Chinese step name rendered as tofu boxes, silently, into the PNG, the film strip, the GIF and the sidecar hash. Labels now resolve a CJK-capable face by asking the font whether it actually has the glyphs, and report any character no installed font can draw.
  • Step names that sanitise to nothing no longer leave dangling underscores in filenames.

If something used to work and now does not / 报错对照

error what it means
style=... is required this change — follow the three steps; the message names the exact file
'noise' is missing grain a hand-written style JSON; every field is required, start from the example
color is required (#RRGGBB) a stack layer without a colour
this motif contains a 'S' atom and the style declares no lattice.species['S'] add the species to your blender style

Two blind tests ran against this release before it was tagged — one on a fresh klink init project, one through the MCP tools against a live KLayout session — and the defects they surfaced are fixed in it.