Skip to main content

GDSII format reader/writer

Project description

klamath README

klamath is a Python module for reading and writing to the GDSII file format.

The goal is to keep this library simple:

  • Map data types directly wherever possible.
    • Presents an accurate representation of what is saved to the file.
    • Avoids excess copies / allocations for speed.
    • No "automatic" error checking, except when casting datatypes. If data integrity checks are provided at all, they must be explicitly run by the caller.
  • Low-level functionality is first-class.
    • Meant for use-cases where the caller wants to read or write individual GDS records.
    • Offers complete control over the written file.
  • Opinionated and limited high-level functionality.
    • Discards or ignores rarely-encountered data types.
    • Keeps functions simple and reusable.
    • Only de/encodes the file format, doesn't provide tools to modify the data itself.
    • Still requires explicit values for most fields.
  • No compilation
    • Uses numpy for speed, since it's commonly available / pre-built.
    • Building this library should not require a compiler.

klamath was built to provide a fast and versatile GDS interface for masque, which provides higher-level tools for working with hierarchical design data and supports multiple file formats.

Alternatives

  • gdspy
    • Provides abstractions and methods for working with design data outside of the I/O process (e.g. polygon clipping).
    • Requires compilation (C++) to build from source.
    • Focused on high-level API
  • python-gdsii
    • Pure-python implementation. Can easily be altered to use numpy for speed, but is limited by object allocation overhead.
    • Focused on high-level API

Links

Installation

Requirements:

  • python >= 3.7 (written and tested with 3.8)
  • numpy

Install with pip:

pip3 install klamath

Alternatively, install from git

pip3 install git+https://mpxd.net/code/jan/klamath.git@release

Examples

Low-level

Filter which polygons are read based on layer:

import io
import klamath
from klamath import records
from klamath.record import Record

def read_polygons(stream, filter_layer_tuple=(4, 5)):
    """
    Given a stream positioned at the start of a record,
     return the vertices of all BOUNDARY records which match
     the provided `filter_layer_tuple`, up to the next
     ENDSTR record.
    """
    polys = []
    while True:
        size, tag = Record.read_header(stream)
        stream.seek(size, io.SEEK_CUR)      # skip to next header

        if tag == records.ENDEL.tag:
            break                           # If ENDEL, we are done

        if tag != records.BOUNDARY.tag:
            continue                        # Skip until we find a BOUNDARY

        layer = records.LAYER.skip_and_read(stream)[0]  # skip to LAYER
        dtype = records.DATATYPE.read(stream)[0]

        if (layer, dtype) != filter_layer_tuple:
            continue                        # Skip reading XY unless layer matches

        xy = XY.read(stream).reshape(-1, 2)
        polys.append(xy)
    return polys

High-level

Write an example GDS file:

import klamath
from klamath.elements import Boundary, Text, Path, Reference

stream = open('example.gds', 'wb')

header = klamath.library.FileHeader(
                name=b'example',
                meters_per_db_unit=1e-9,      # 1 nm DB unit
                user_units_per_db_unit=1e-3)  # 1 um (1000nm) display unit
header.write(stream)

elements_A = [
    Boundary(layer=(4, 18),
             xy=[[0, 0], [10, 0], [10, 20], [0, 20], [0, 0]],
             properties={1: b'prop1string', 2: b'some other string'}),
    Text(layer=(5, 5),
         xy=[[5, 10]],
         string=b'center position',
         properties={},        # Remaining args are set to default values
         presentation=0,       #   and will be omitted when writing
         angle_deg=0,
         invert_y=False,
         width=0,
         path_type=0,
         mag=1),
    Path(layer=(4, 20),
         xy=[[0, 0], [10, 10], [0, 20]],
         path_type=0,
         width=0,
         extension=(0, 0),     # ignored since path_type=0
         properties={}),
    ]
klamath.library.write_struct(stream, name=b'my_struct', elements=elements_A)

elements_top = [
    Reference(struct_name=b'my_struct',
              xy=[[30, 30]],
              colrow=None,   # not an array
              angle_deg=0,
              invert_y=True,
              mag=1.5,
              properties={}),
    Reference(struct_name=b'my_struct',
              colrow=(3, 2),                    # 3x2 array at (0, 50)
              xy=[[0, 50], [60, 50], [30, 50]], #   with basis vectors
              angle_deg=30,                     #   [20, 0] and [0, 30]
              invert_y=False,
              mag=1,
              properties={}),
    ]
klamath.library.write_struct(stream, name=b'top', elements=elements_top)

klamath.records.ENDLIB.write(stream, None)
stream.close()

Read back the file:

import klamath

stream = open('example.gds', 'rb')
header = klamath.library.FileHeader.read(stream)

structs = {}

struct = klamath.library.try_read_struct(stream)
while struct is not None:
    name, elements = struct
    structs[name] = elements
    struct = klamath.library.try_read_struct(stream)

stream.close()

print(structs)

Read back a single struct by name:

import klamath

stream = open('example.gds', 'rb')

header = klamath.library.FileHeader.read(stream)
struct_positions = klamath.library.scan_structs(stream)

stream.seek(struct_positions[b'my_struct'])
elements_A = klamath.library.try_read_struct(stream)

stream.close()

print(elements_A)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

klamath-1.3.tar.gz (39.6 kB view details)

Uploaded Source

Built Distribution

klamath-1.3-py3-none-any.whl (55.4 kB view details)

Uploaded Python 3

File details

Details for the file klamath-1.3.tar.gz.

File metadata

  • Download URL: klamath-1.3.tar.gz
  • Upload date:
  • Size: 39.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.10.6

File hashes

Hashes for klamath-1.3.tar.gz
Algorithm Hash digest
SHA256 072024e1bc4f560ae2d3d0880340fed6b649a4a158c5102d7402d8401a54bfba
MD5 7930c7bc6ef0fb31e2e34a29dd43755d
BLAKE2b-256 9726effb1406464d25f285ee8e33d6f0bb11e1190c6cc9dc3dbf5c47e78e5349

See more details on using hashes here.

File details

Details for the file klamath-1.3-py3-none-any.whl.

File metadata

  • Download URL: klamath-1.3-py3-none-any.whl
  • Upload date:
  • Size: 55.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.10.6

File hashes

Hashes for klamath-1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 2f0d454e4902ff4dbf0ba0b05d8b2a275d6ee82f83644012e65b114d175689e2
MD5 1106d0cbdfd78da568165e8256092a1f
BLAKE2b-256 8aed267169e06e914aeb4477f73761029ec998e0b2879aa1651228ffac5e18e2

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page