KLayout is a high performance layout viewer and editor that supports GDS and OASIS files and more formats
—
Core functionality for layout database management, geometric primitive creation and manipulation, and fundamental operations for IC layout design and analysis.
The Layout class serves as the top-level container for all layout data, managing cells, layers, and metadata.
class Layout:
def __init__(self):
"""Create a new empty layout."""
def create_cell(self, name: str) -> Cell:
"""
Create a new cell in the layout.
Parameters:
- name: Unique name for the cell
Returns:
Cell: The newly created cell object
"""
def cell(self, name: str) -> Cell:
"""
Retrieve an existing cell by name.
Parameters:
- name: Name of the cell to retrieve
Returns:
Cell: The cell object, or None if not found
"""
def read(self, filename: str, options: LoadLayoutOptions = None) -> None:
"""
Read layout data from a file.
Parameters:
- filename: Path to the layout file
- options: Optional loading configuration
"""
def write(self, filename: str, options: SaveLayoutOptions = None) -> None:
"""
Write layout data to a file.
Parameters:
- filename: Output file path
- options: Optional save configuration
"""
def layer(self, layer_info: LayerInfo) -> int:
"""
Get or create a layer index for the given layer info.
Parameters:
- layer_info: Layer specification (layer number and datatype)
Returns:
int: Internal layer index
"""
def insert_layer(self, layer_info: LayerInfo) -> int:
"""Insert a new layer and return its index."""
def delete_layer(self, layer_index: int) -> None:
"""Delete a layer by its index."""
def layer_info(self, layer_index: int) -> LayerInfo:
"""Get layer info for a given layer index."""Cells are the basic building blocks of hierarchical layout designs, containing shapes and instances of other cells.
class Cell:
@property
def name(self) -> str:
"""Get the cell name."""
@property
def cell_index(self) -> int:
"""Get the cell's index in the layout."""
def shapes(self, layer: int) -> Shapes:
"""
Get the shapes container for a specific layer.
Parameters:
- layer: Layer index
Returns:
Shapes: Container for geometric shapes on this layer
"""
def insert(self, instance: CellInstArray) -> CellInstArray:
"""
Insert a cell instance into this cell.
Parameters:
- instance: Cell instance to insert
Returns:
CellInstArray: The inserted instance
"""
def move(self, transformation: Trans) -> None:
"""Move all content of the cell by the given transformation."""
def transform(self, transformation: CplxTrans) -> None:
"""Transform all content with complex transformation."""
def copy_tree(self, target_layout: Layout) -> Cell:
"""Copy this cell and its hierarchy to another layout."""
def flatten(self, levels: int = -1) -> None:
"""
Flatten the cell hierarchy by the specified number of levels.
Parameters:
- levels: Number of levels to flatten (-1 for all)
"""class Point:
def __init__(self, x: int, y: int):
"""
Create an integer coordinate point.
Parameters:
- x: X coordinate (database units)
- y: Y coordinate (database units)
"""
x: int
y: int
def distance(self, other: Point) -> float:
"""Calculate distance to another point."""
def moved(self, vector: Vector) -> Point:
"""Return a new point moved by the vector."""
class DPoint:
def __init__(self, x: float, y: float):
"""Create a double precision point."""
x: float
y: float
class Vector:
def __init__(self, x: int, y: int):
"""Create an integer vector."""
x: int
y: int
def length(self) -> float:
"""Calculate vector length."""
def angle(self) -> float:
"""Calculate vector angle in radians."""
class DVector:
def __init__(self, x: float, y: float):
"""Create a double precision vector."""
x: float
y: floatclass Box:
def __init__(self, left: int, bottom: int, right: int, top: int):
"""
Create an integer coordinate box.
Parameters:
- left: Left coordinate
- bottom: Bottom coordinate
- right: Right coordinate
- top: Top coordinate
"""
left: int
bottom: int
right: int
top: int
def width(self) -> int:
"""Get box width."""
def height(self) -> int:
"""Get box height."""
def area(self) -> int:
"""Calculate box area."""
def center(self) -> Point:
"""Get box center point."""
def moved(self, vector: Vector) -> Box:
"""Return box moved by vector."""
def enlarged(self, dx: int, dy: int = None) -> Box:
"""Return enlarged box."""
class DBox:
def __init__(self, left: float, bottom: float, right: float, top: float):
"""Create a double precision box."""
left: float
bottom: float
right: float
top: floatclass Polygon:
def __init__(self, points: list[Point] = None):
"""
Create a polygon from a list of points.
Parameters:
- points: List of points defining the polygon vertices
"""
def area(self) -> float:
"""Calculate polygon area."""
def perimeter(self) -> int:
"""Calculate polygon perimeter."""
def bbox(self) -> Box:
"""Get bounding box."""
def is_clockwise(self) -> bool:
"""Check if vertices are in clockwise order."""
def holes(self) -> int:
"""Get number of holes in polygon."""
def each_point_hull(self):
"""Iterate over hull points."""
def each_point_hole(self, hole_index: int):
"""Iterate over points of a specific hole."""
def moved(self, vector: Vector) -> Polygon:
"""Return polygon moved by vector."""
def transformed(self, trans: Trans) -> Polygon:
"""Return transformed polygon."""
class DPolygon:
def __init__(self, points: list[DPoint] = None):
"""Create a double precision polygon."""
def area(self) -> float:
"""Calculate polygon area."""
class SimplePolygon:
def __init__(self, points: list[Point] = None):
"""Create a simple (non-self-intersecting) polygon."""class Path:
def __init__(self, points: list[Point] = None, width: int = 0):
"""
Create a path with specified width.
Parameters:
- points: List of points defining the path centerline
- width: Path width in database units
"""
def width(self) -> int:
"""Get path width."""
def set_width(self, width: int) -> None:
"""Set path width."""
def length(self) -> int:
"""Calculate path length."""
def polygon(self) -> Polygon:
"""Convert path to polygon representation."""
def each_point(self):
"""Iterate over path points."""
class DPath:
def __init__(self, points: list[DPoint] = None, width: float = 0.0):
"""Create a double precision path."""class Edge:
def __init__(self, p1: Point, p2: Point):
"""
Create an edge between two points.
Parameters:
- p1: Start point
- p2: End point
"""
p1: Point
p2: Point
def length(self) -> float:
"""Calculate edge length."""
def dx(self) -> int:
"""Get X displacement."""
def dy(self) -> int:
"""Get Y displacement."""
def bbox(self) -> Box:
"""Get bounding box."""
def moved(self, vector: Vector) -> Edge:
"""Return edge moved by vector."""
class DEdge:
def __init__(self, p1: DPoint, p2: DPoint):
"""Create a double precision edge."""class Text:
def __init__(self, text: str, trans: Trans = None):
"""
Create a text annotation.
Parameters:
- text: Text string
- trans: Transformation (position, rotation, etc.)
"""
@property
def string(self) -> str:
"""Get text string."""
def set_string(self, text: str) -> None:
"""Set text string."""
def transform(self) -> Trans:
"""Get text transformation."""
def bbox(self) -> Box:
"""Get text bounding box."""
class DText:
def __init__(self, text: str, trans: DTrans = None):
"""Create a double precision text annotation."""class Shapes:
def insert(self, shape) -> None:
"""
Insert a shape into the container.
Parameters:
- shape: Any geometric shape (Box, Polygon, Path, Text, etc.)
"""
def erase(self, shape) -> None:
"""Remove a shape from the container."""
def clear(self) -> None:
"""Remove all shapes."""
def size(self) -> int:
"""Get number of shapes in container."""
def empty(self) -> bool:
"""Check if container is empty."""
def each(self):
"""Iterate over all shapes."""
def each_overlapping(self, region: Box):
"""Iterate over shapes overlapping the given region."""import klayout.db as db
# Create layout and top cell
layout = db.Layout()
top_cell = layout.create_cell("TOP")
# Define layers
metal1 = layout.layer(db.LayerInfo(1, 0))
via1 = layout.layer(db.LayerInfo(2, 0))
# Create geometric shapes
rect = db.Box(0, 0, 1000, 500)
circle_points = []
import math
for i in range(32):
angle = 2 * math.pi * i / 32
x = int(500 + 200 * math.cos(angle))
y = int(250 + 200 * math.sin(angle))
circle_points.append(db.Point(x, y))
circle = db.Polygon(circle_points)
# Add shapes to layers
top_cell.shapes(metal1).insert(rect)
top_cell.shapes(via1).insert(circle)
# Save layout
layout.write("simple_layout.gds")import klayout.db as db
layout = db.Layout()
# Create cells
top_cell = layout.create_cell("TOP")
sub_cell = layout.create_cell("SUBCELL")
# Add content to subcell
layer = layout.layer(db.LayerInfo(1, 0))
sub_cell.shapes(layer).insert(db.Box(0, 0, 100, 100))
# Create instances of subcell in top cell
for x in range(0, 1000, 200):
for y in range(0, 500, 150):
trans = db.Trans(db.Point(x, y))
instance = db.CellInstArray(sub_cell.cell_index, trans)
top_cell.insert(instance)
layout.write("hierarchical_layout.gds")Install with Tessl CLI
npx tessl i tessl/pypi-klayout