def write_svg_image(): poly1 = gdstk.ellipse((0, 0), (13, 10), datatype=1) # (layer, datatype) = (0, 1) poly2 = gdstk.ellipse((0, 0), (10, 7), layer=1) # (layer, datatype) = (1, 0) cell = gdstk.Cell("SVG") cell.add(poly1, poly2) # cell.write_svg( # "example.svg", # background="none", # style={(0, 1): {"fill": "none", "stroke": "black", "stroke-dasharray": "8,8"}}, # pad="5%", # ) cell.name = "write_svg" return cell
def ellipse_image(): circle = gdstk.ellipse((0, 0), 40) ellipse = gdstk.ellipse((100, 0), (40, 30), layer=1) ring = gdstk.ellipse((0, 100), 40, inner_radius=(30, 20), layer=2) circle_slice = gdstk.ellipse( (100, 100), 40, initial_angle=-numpy.pi / 4, final_angle=5 * numpy.pi / 4, layer=3, ) ring_slice = gdstk.ellipse( (50, 200), (70, 30), (60, 20), -3 * numpy.pi / 4, numpy.pi / 2, layer=4 ) return gdstk.Cell("ellipse").add(circle, ellipse, ring, circle_slice, ring_slice)
def slice_image(): triangle = gdstk.regular_polygon((-10, 0), 8, 3) ring = gdstk.ellipse((10, 0), 8, 5, layer=1) result = gdstk.slice([triangle, ring], (-10, -5, 0, 6, 14), "x") # print(len(result)) # print([len(polys) for polys in result]) return gdstk.Cell("slice").add(*[p for polys in result for p in polys])
def slice_image(): triangle = gdstk.regular_polygon((-10, 0), 8, 3) ring = gdstk.ellipse((10, 0), 8, 5, layer=1) result = gdstk.slice([triangle, ring], (-10, -5, 0, 6, 14), "x") assert len(result) == 6 assert all(len(polys) == s for polys, s in zip(result, [1, 1, 0, 1, 2, 1])) return gdstk.Cell("slice").add(*[p for polys in result for p in polys])
def boolean_image(): circle = gdstk.ellipse((0, 0), 50) path = gdstk.FlexPath((-50, 30), [5, 5], 10) path.interpolation([(20, 15), (0, 0), (-20, -15), (50, -30)], angles=[0.3, None, None, None, 0.3]) text = gdstk.text("GDSTK", 40, (-2.5 * 40 * 9 / 16, -40 / 2)) result = gdstk.boolean(circle, text + [path], "not") return gdstk.Cell("boolean").add(*result)
def make_second_lib(filename): lib = gdstk.Library("Second") main = lib.new_cell("Main") main.add(*gdstk.text("Second library", 10, (0, 0))) ref = lib.new_cell("Circle") ref.add(gdstk.ellipse((-10, 5), 5)) main.add(gdstk.Reference(ref)) lib.write_gds(filename)
def offset_image(): text = gdstk.text("#A", 10, (0, 0), datatype=1) circle = gdstk.ellipse( (5, 11), 5, initial_angle=0, final_angle=numpy.pi, datatype=1 ) path = gdstk.FlexPath([(0, -1), (5, -10), (10, -1)], 1, datatype=1) dilated = gdstk.offset(text + [circle, path], 0.4) eroded = gdstk.offset(text + [circle, path], -0.4, use_union=True, layer=1) return gdstk.Cell("offset").add(*text, circle, path, *dilated, *eroded)
def write_svg_image(): # (layer, datatype) = (0, 1) poly1 = gdstk.ellipse((0, 0), (13, 10), datatype=1) # (layer, datatype) = (1, 0) poly2 = gdstk.ellipse((0, 0), (10, 7), layer=1) (layer, texttype) = (3, 2) label = gdstk.Label("Example", (0, 0), layer=3, texttype=2) cell = gdstk.Cell("SVG") cell.add(poly1, poly2, label) # cell.write_svg( # "example.svg", # background="none", # style={(0, 1): {"fill": "none", "stroke": "black", "stroke-dasharray": "8,8"}}, # fontstyle={(3, 2): {"fill": "none", "stroke": "red", "font-size": "32px"}}, # pad="5%", # sort_function=lambda p1, p2: p1.layer < p2.layer, # ) cell.name = "write_svg" return cell
def make_first_lib(filename): lib = gdstk.Library("First") main = lib.new_cell("Main") main.add(*gdstk.text("First library", 10, (0, 0))) ref1 = lib.new_cell("Square") ref1.add(gdstk.rectangle((-15, 0), (-5, 10))) main.add(gdstk.Reference(ref1)) ref2 = lib.new_cell("Circle") ref2.add(gdstk.ellipse((0, 0), 4)) ref1.add(gdstk.Reference(ref2, (-10, 5))) lib.write_gds(filename)
def test_inside(): ring = gdstk.ellipse((0, 0), 1, inner_radius=0.5, tolerance=1e-3) circle = gdstk.ellipse((0, 0), 0.5, tolerance=1e-3) points = [(0, 0), (0.2, 0), (-0.1, -0.8), (0.9, 0.7), (-0.4, 0.4)] truth_ring = tuple([0.25 <= p[0]**2 + p[1]**2 <= 1 for p in points]) truth_circle = tuple([p[0]**2 + p[1]**2 <= 0.25 for p in points]) assert ring.contain(*points) == truth_ring assert ring.contain_all(*points) == all(truth_ring) assert ring.contain_any(*points) == any(truth_ring) assert circle.contain(*points) == truth_circle assert circle.contain_all(*points) == all(truth_circle) assert circle.contain_any(*points) == any(truth_circle) assert gdstk.inside(points, [ring, circle]) == tuple( [r or c for r, c in zip(truth_ring, truth_circle)]) assert gdstk.all_inside(points, [ring, circle]) == all( [r or c for r, c in zip(truth_ring, truth_circle)]) assert gdstk.any_inside(points, [ring, circle]) == any( [r or c for r, c in zip(truth_ring, truth_circle)]) polys = [ gdstk.rectangle((0, 0), (10, 10)), gdstk.rectangle((10, 0), (20, 10)) ] for pts, _any, _all in ( ([(1, 1), (-1, -1)], True, False), ([(2, 2), (-2, 2), (2, -2)], True, False), ([(5, 5), (10, 5)], True, True), ([(-1, -1), (-2, -2)], False, False), ([(2, 3)], True, True), ): assert gdstk.any_inside(pts, polys) == _any assert gdstk.all_inside(pts, polys) == _all
def sample_library(): lib = gdstk.Library("lib", unit=2e-3, precision=1e-5) c1 = gdstk.Cell("gl_rw_gds_1") c1.add(gdstk.rectangle((0, -1), (1, 2), 2, 4)) c1.add(gdstk.Label("label", (1, -1), "w", 10, 1.5, True, 5, 6)) c2 = gdstk.Cell("gl_rw_gds_2") c2.add(gdstk.ellipse((0, 0), 1)) c3 = gdstk.Cell("gl_rw_gds_3") c3.add(gdstk.Reference(c1, (0, 1), -90, 2, True)) c4 = gdstk.Cell("gl_rw_gds_4") c4.add( gdstk.Reference( c2, (-1, -2), columns=2, rows=3, spacing=(1, 4), rotation=numpy.pi, magnification=0.5, x_reflection=True, )) lib.add(c1, c2, c3, c4) return lib
def memory_benchmark(): proc = psutil.Process() total = 100000 print(f"\nMemory usage per object for {total} objects:\n") def print_row(*vals, hsep=False): columns = [20, 16, 16, 9] print( "|", vals[0].ljust(columns[0]), "|", " | ".join(v.center(c) for v, c in zip(vals[1:], columns[1:])), "|", ) if hsep: print( "|", ":" + "-" * (columns[0] - 1), "|", " | ".join(":" + "-" * (c - 2) + ":" for c in columns[1:]), "|", ) print_row( "Object", "Gdspy " + gdspy.__version__, "Gdstk " + gdstk.__version__, "Reduction", hsep=True, ) def mem_test(func): start_mem = proc.memory_info() r = [func(i) for i in range(total)] end_mem = proc.memory_info() return (end_mem.vms - start_mem.vms) / total, r data = [] gdspy_cell = gdspy.Cell("TEMP", exclude_from_current=True) gdstk_cell = gdstk.Cell("TEMP") for obj, gdspy_func, gdstk_func in [ ( "Rectangle", lambda i: gdspy.Rectangle((i, i), (i + 1, i + 1)), lambda i: gdstk.rectangle((i, i), (i + 1, i + 1)), ), ( "Circle (r = 10)", lambda i: gdspy.Round((0, 10 * i), 10), lambda i: gdstk.ellipse((0, 10 * i), 10), ), ( "FlexPath segment", lambda i: gdspy.FlexPath([(i, i + 1), (i + 1, i)], 0.1), lambda i: gdstk.FlexPath([(i, i + 1), (i + 1, i)], 0.1), ), ( "FlexPath arc", lambda i: gdspy.FlexPath([(10 * i, 0)], 0.1).arc(10, 0, numpy.pi), lambda i: gdstk.FlexPath([(10 * i, 0)], 0.1).arc(10, 0, numpy.pi), ), ( "RobustPath segment", lambda i: gdspy.RobustPath((i, i + 1), 0.1).segment((i + 1, i)), lambda i: gdstk.RobustPath((i, i + 1), 0.1).segment((i + 1, i)), ), ( "RobustPath arc", lambda i: gdspy.RobustPath((10 * i, 0), 0.1).arc(10, 0, numpy.pi), lambda i: gdstk.RobustPath((10 * i, 0), 0.1).arc(10, 0, numpy.pi), ), ( "Label", lambda i: gdspy.Label(str(i), (i, i)), lambda i: gdstk.Label(str(i), (i, i)), ), ( "Reference", lambda i: gdspy.CellReference(gdspy_cell, (0, 0)), lambda i: gdstk.Reference(gdstk_cell, (0, 0)), ), ( "Reference (array)", lambda i: gdspy.CellArray(gdspy_cell, (0, 0), 1, 1, (0, 0)), lambda i: gdstk.Reference(gdstk_cell, (0, 0), rows=1, columns=1), ), ( "Cell", lambda i: gdspy.Cell(str(i), exclude_from_current=True), lambda i: gdstk.Cell(str(i)), ), ]: gdspy_mem, gdspy_data = mem_test(gdspy_func) data.append(gdspy_data) gdstk_mem, gdstk_data = mem_test(gdstk_func) data.append(gdstk_data) print_row( obj, prefix_format(gdspy_mem, unit="B", base="bin"), prefix_format(gdstk_mem, unit="B", base="bin"), f"{100 - 100 * gdstk_mem / gdspy_mem:.0f}%", )
# Polygons # Create a polygon from a list of vertices points = [(0, 0), (2, 2), (2, 6), (-6, 6), (-6, -6), (-4, -4), (-4, 4), (0, 4)] poly = gdstk.Polygon(points) draw(gdstk.Cell("polygons").add(poly), path) # Holes # Manually connect the hole to the outer boundary cutout = gdstk.Polygon([(0, 0), (5, 0), (5, 5), (0, 5), (0, 0), (2, 2), (2, 3), (3, 3), (3, 2), (2, 2)]) draw(gdstk.Cell("holes").add(cutout), path) # Circles # Circle centered at (0, 0), with radius 2 and tolerance 0.1 circle = gdstk.ellipse((0, 0), 2, tolerance=0.01) # To create an ellipse, simply pass a list with 2 radii. # Because the tolerance is small (resulting a large number of # vertices), the ellipse is fractured in 2 polygons. ellipse = gdstk.ellipse((4, 0), [1, 2], tolerance=1e-4) # Circular arc example arc = gdstk.ellipse( (2, 4), 2, inner_radius=1, initial_angle=-0.2 * numpy.pi, final_angle=1.2 * numpy.pi, tolerance=0.01, )
from tutorial_images import draw import numpy import gdstk if __name__ == "__main__": # Rectangular repetition square = gdstk.regular_polygon((0, 0), 0.2, 4) square.repetition = gdstk.Repetition(3, 2, spacing=(1, 1)) # Regular repetition triangle = gdstk.regular_polygon((0, 2.5), 0.2, 3) triangle.repetition = gdstk.Repetition(3, 5, v1=(0.4, -0.3), v2=(0.4, 0.2)) # Explicit repetition circle = gdstk.ellipse((3.5, 0), 0.1) circle.repetition = gdstk.Repetition(offsets=[(0.5, 1), (2, 0), (1.5, 0.5)]) # X-explicit repetition vline = gdstk.FlexPath([(3, 2), (3, 3.5)], 0.1, gdsii_path=True) vline.repetition = gdstk.Repetition(x_offsets=[0.2, 0.6, 1.4, 3.0]) # Y-explicit repetition hline = gdstk.RobustPath((3, 2), 0.05, gdsii_path=True) hline.segment((6, 2)) hline.repetition = gdstk.Repetition(y_offsets=[0.1, 0.3, 0.7, 1.5]) main = gdstk.Cell("Main") main.add(square, triangle, circle, vline, hline) main.name = "repetitions" path = pathlib.Path(__file__).parent.absolute() / "how-tos"
###################################################################### from tutorial_images import draw import pathlib import numpy import gdstk if __name__ == "__main__": n = 3 # Number of unit cells around defect d = 0.2 # Unit cell size r = 0.05 # Circle radius s = 1.5 # Scaling factor # Create a simple unit cell unit_cell = gdstk.Cell("Unit Cell") unit_cell.add(gdstk.ellipse((0, 0), r, tolerance=1e-3)) # Build a resonator from a unit cell grid with a defect inside ressonator = gdstk.Cell("Resonator") patches = [ gdstk.Reference(unit_cell, (-n * d, -n * d), columns=2 * n + 1, rows=n, spacing=(d, d)), gdstk.Reference(unit_cell, (-n * d, d), columns=2 * n + 1, rows=n, spacing=(d, d)), gdstk.Reference(unit_cell, (-n * d, 0), columns=n, rows=1,
#!/usr/bin/env python # -*- coding: utf-8 -*- # Copyright 2020 Lucas Heitzmann Gabrielli. # This file is part of gdstk, distributed under the terms of the # Boost Software License - Version 1.0. See the accompanying # LICENSE file or <http://www.boost.org/LICENSE_1_0.txt> import gdspy import gdstk gdspy_ring = gdspy.Round((0, 0), 1, inner_radius=0.5, tolerance=1e-3, max_points=0) gdspy_circle = gdspy.Round((0, 0), 0.5, tolerance=1e-3, max_points=0) gdstk_ring = gdstk.ellipse((0, 0), 1, inner_radius=0.5, tolerance=1e-3) gdstk_circle = gdstk.ellipse((0, 0), 0.5, tolerance=1e-3) points = [(0, 0), (0.2, 0), (-0.1, -0.8), (0.9, 0.7), (-0.4, 0.4)] * 10 def bench_gdspy(): gdspy.inside(points, gdspy_ring) gdspy.inside([points], gdspy_ring, "any") gdspy.inside([points], gdspy_ring, "all") gdspy.inside(points, [gdspy_ring, gdspy_circle]) gdspy.inside([points], [gdspy_ring, gdspy_circle], "any") gdspy.inside([points], [gdspy_ring, gdspy_circle], "all") def bench_gdstk(): gdstk_ring.contain(*points) gdstk_ring.contain_any(*points) gdstk_ring.contain_all(*points)