Skip to content

jimsweeney/gdsnorm

Repository files navigation

gdsnorm - a canonical layout hash for gdsfactory

tests license

gdsnorm gives a GDS layout (or a gdsfactory Component) a stable content hash: the same value across runs and machines, regardless of the order polygons were drawn, which vertex a polygon starts on, which way it winds, or sub-grid float noise in the coordinates. Two layouts that draw the same shapes hash identically; a real change does not. That makes the hash a reproducible regression key for CI, and a fast way to ask "are these two layouts the same?" without a pixel diff.

What it is invariant to

  • polygon order within a cell, and cell/label/reference order,
  • the starting vertex of a polygon and its winding direction,
  • coordinate noise smaller than the database grid.

Install

pip install -r requirements.txt

numpy and gdstk are the dependencies. gdsfactory is optional and used only to read a Component; a GDS file works without it.

Use

From the command line, write a hash manifest for one layout, or compare two:

python cli.py layout.gds -o out/           # writes hashes.json and manifest.md
python cli.py a.gds b.gds                   # prints "canonically identical" or the first difference

The two-file form exits non-zero when the layouts differ, so it works as a CI gate.

From Python:

import load, cellhash, equivalence

a = load.from_gds("a.gds")
b = load.from_gds("b.gds")
print(cellhash.library_hashes(a)["library"])   # the stable library hash
print(equivalence.canonically_equal(a, b))     # (True, None) or (False, "cell 'x' differs")

# from a gdsfactory Component:
# cellhash.library_hashes(load.from_component(component))

A runnable example is in examples/quickstart.py: it builds one layout two ways (polygons reordered and nudged by less than a grid step) and shows the hashes match.

Modules

Module What it does
load.py read a GDS / Component into a model that keeps the geometry
canon.py snap to grid and put each polygon in a canonical vertex order and winding; sort everything
cellhash.py a stable sha256 of the canonical form, per cell and per library
equivalence.py compare two layouts and name the first differing cell
report.py a hash manifest and a comparison verdict as JSON and Markdown
cli.py python cli.py a.gds [b.gds] end to end

Test

python run_checks.py validate <name>   # one module's self-check
python run_checks.py validate-all      # every module's self-check
python run_checks.py suite             # pytest tests/

The canonicaliser is validated by giving it the same square reordered, reverse-wound, and with sub-grid noise and confirming all forms collapse to one canonical tuple, while a real shift changes it. The hash is validated by adding the same two rectangles in either order and confirming the hash matches, then moving one and confirming it does not.

Scope and performance

gdsnorm canonicalises and hashes geometry; it does not diff or render (for a human-readable structural diff see a layout review tool) and it is not a DRC. The canonicalisation is a plain Python pass per polygon: that is deliberate, since polygons are usually small and very many, and per-polygon numpy vectorisation measured about three times slower. The cost scales with polygon count (tens of thousands of polygons in well under a second), so the read of a large GDS can dominate.

About

Canonical layout hash for reproducible CI on GDS layouts

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages