Layout Filters

A number of filters are defined that assist in GDSII file creation. These are used to make a layout adhere to GDSII standards, such as maximum length of a Path or Boundary element.

  • The TECH.GDSII.FILTER setting in the technology is typically a i3.ToggledCompoundFilter that contains several subfilters, such that Paths and Boundaries adhere to a maximum length and Path elements for optical waveguides are automatically converted to Boundaries so that perfect control over the sidewalls is achieved.

  • The TECH.GDSII.NAME_FILTER setting in the technology is typically a i3.NameScrambleFilter that ensures only valid characters are used in GDSII cell names and the cell names adhere to a maximum length.

Specific filters


Filter that cuts a closed shape into areas with a minimum number of vertices.


Filter that cuts a closed shape into areas with a minimum numer of vertices


Filter that converts Path elements into Boundary Elements


Filter that flattens all layout Reference Elements with a transformation that is not along Manhattan directions


Filter for removing invalid characters from a string (e.g.


Filter for scrambling a Structure's name.


Raise an error when a PCell or Library has a wrong name


Filter that lets all LayerElements pass that are on the supplied layer list.


Filter that blocks all LayerElements that are on the supplied layer list.


Filter object that removes all items where is_empty() returns True

Base classes


base class that processes any IPKISS primitive (does type checking where needed).


Compound filter in which filters can be turned on or off by doing filter['filter_name'] = True|False Only for named filters!


# Example of how to use layout filters
from ipkiss3 import all as i3
import numpy as np

route_layer = i3.Layer(0)
doc_layer = i3.Layer(1)

# Filter to be applied to GDSII export
# - Cut path elements that are longer than 50 vertices in smaller pieces
# - Remove the doc_layer

custom_filter = i3.ToggledCompoundFilter()
custom_filter += i3.PathCutFilter(
    grids_per_unit=int(i3.TECH.METRICS.UNIT / i3.TECH.METRICS.GRID),
custom_filter += i3.LayerFilterDelete(

# Make a long path
angles = np.linspace(0, np.pi, 100)
xs = 5 * np.sin(angles)
ys = 5 * np.cos(angles)
long_shape = i3.Shape(points=[(x, y) for (x, y) in zip(xs, ys)])

long_path = i3.LayoutCell(name="cell_long_path")
long_path.Layout(elements=[i3.Path(layer=i3.Layer(0), shape=long_shape, line_width=1)])

short_path = i3.LayoutCell(name="cell_short_path")
short_path.Layout(elements=[i3.Path(layer=i3.Layer(0), shape=[(0.0, 0.0), (10.0, 0.0), (10.0, 15.0)], line_width=0.5)])

top_cell = i3.LayoutCell(name="example_filters")
top_layout = top_cell.Layout(
        i3.SRef(long_path, (0.0, 0.0)),
        i3.SRef(short_path, (5.0, -10.0)),
        i3.Rectangle(layer=doc_layer, center=(8.0, -2.0), box_size=(20.0, 20.0)),


# Write GDSII with default filters
layer_map = i3.AutoGdsiiLayerOutputMap()
top_layout.write_gdsii("test_gds_default.gds", layer_map=layer_map)

# Write GDSII with our custom filter
top_layout.write_gdsii("test_gds_custom.gds", filter=custom_filter, layer_map=layer_map)

With default filter: Path converted to Boundary, not cut (not too long), two layers present.


With custom filter: Path not converted, but cut in pieces of max 50 vertices, layer 1 removed.