def test_transforms(proof_cells): for scale_width in [True, False]: path0 = gdstk.RobustPath( 0j, [0.1, 0.2], 0.3, tolerance=1e-4, scale_width=scale_width, ) path0.vertical(1).horizontal(0.5).turn(0.4, -numpy.pi, [0.2, 0.1]).segment( (-0.2, 0), relative=True) paths = [ path0, path0.copy().mirror((1.5, 0)), path0.copy().mirror((1.5, 0), (1.5, 1)), path0.copy().scale(2, (3, 0)), path0.copy().scale(-2, (-1, 0)), path0.copy().rotate(numpy.pi / 2, (2, 1)).translate(0.2, -0.3), ] assert_same_shape( proof_cells[f"RobustPath: scale_width {scale_width}"].polygons, paths, 3e-3)
def make_proof_lib(): lib = gdstk.Library("Test Library", unit=1e-6, precision=1e-12) cell = lib.new_cell("Polygon.fillet") p1 = gdstk.Polygon([(0, 0), (1.2, 0), (1.2, 0.3), (1, 0.3), (1.5, 1), (0, 1.5)]) p2 = p1.copy().translate(2, 0) cell.add(p1.fillet(0.3, tolerance=1e-3)) cell.add(p2.fillet([0.3, 0, 0.1, 0, 0.5, 10], tolerance=1e-3)) for scale_width in [True, False]: cell = lib.new_cell(f"FlexPath: scale_width {scale_width}") path0 = gdstk.FlexPath( (0j, 1j, 0.5 + 1j), [0.1, 0.2], 0.3, tolerance=1e-4, scale_width=scale_width, ) path0.turn(0.4, -numpy.pi, [0.2, 0.1]).segment((-0.2, 0), relative=True) path1 = path0.copy().mirror((1.5, 0)) path1.set_layers(1, 1) path2 = path0.copy().mirror((1.5, 0), (1.5, 1)) path2.set_layers(2, 2) path3 = path0.copy().scale(2, (3, 0)) path3.set_layers(3, 3) path4 = path0.copy().scale(-2, (-1, 0)) path4.set_layers(4, 4) path5 = path0.copy().rotate(numpy.pi / 2, (2, 1)).translate(0.2, -0.3) path5.set_layers(5, 5) cell.add(path0, path1, path2, path3, path4, path5) for scale_width in [True, False]: cell = lib.new_cell(f"RobustPath: scale_width {scale_width}") path0 = gdstk.RobustPath( 0j, [0.1, 0.2], 0.3, tolerance=1e-4, scale_width=scale_width, ) path0.vertical(1).horizontal(0.5).turn(0.4, -numpy.pi, [0.2, 0.1]).segment( (-0.2, 0), relative=True) path1 = path0.copy().mirror((1.5, 0)) path1.set_layers(1, 1) path2 = path0.copy().mirror((1.5, 0), (1.5, 1)) path2.set_layers(2, 2) path3 = path0.copy().scale(2, (3, 0)) path3.set_layers(3, 3) path4 = path0.copy().scale(-2, (-1, 0)) path4.set_layers(4, 4) path5 = path0.copy().rotate(numpy.pi / 2, (2, 1)).translate(0.2, -0.3) path5.set_layers(5, 5) cell.add(path0, path1, path2, path3, path4, path5) ref_cell1 = gdstk.Cell("Reference 1") ref_cell1.add(*gdstk.text("F.", 10, (0, 0))) ref_cell1.add(gdstk.Label("LaBeL", (2.4, 8.7), "s")) ref_cell1.add(gdstk.FlexPath(8 + 4j, 1, layer=3).arc(2, 0, numpy.pi / 2)) ref_cell1.add( gdstk.RobustPath(7.5 + 7j, 1, layer=4).bezier([-2 + 1j, -2 + 3j, 4j, 6j, -3 + 6j], relative=True)) ref_cell2 = gdstk.Cell("Reference 2") ref_cell2.add(*gdstk.text("^", 10, (0, 5), layer=1)) ref_cell2.add(gdstk.Reference(ref_cell1)) cell = gdstk.Cell("Original cell") cell.add(gdstk.rectangle((-1, -0.5), (1, 0.5), layer=2)) cell.add(gdstk.Reference(ref_cell2)) cell.add(gdstk.Reference(ref_cell1, (10, 7), numpy.pi / 4, 0.5, True)) cell.add( gdstk.Reference(ref_cell1, (-7, 15), -numpy.pi / 3, 0.5, True, 3, 2, (5, 4))) cell.add( gdstk.Reference(ref_cell2, (-7, 23), numpy.pi / 3, 0.5, True, 3, 2, (5, 8))) cell_copy = cell.copy("Cell.copy", (-10, -10), numpy.pi / 2, 2, True).flatten() lib.add(cell_copy) gds_outfile = pathlib.Path(__file__).parent / "proof_lib.gds" if gds_outfile.exists(): print(f"Test library {str(gds_outfile)} already exists.") else: lib.write_gds(gds_outfile) print(f"Test library saved as {str(gds_outfile)}.") oas_outfile = pathlib.Path(__file__).parent / "proof_lib.oas" if oas_outfile.exists(): print(f"Test library {str(oas_outfile)} already exists.") else: lib.write_oas(oas_outfile) print(f"Test library saved as {str(oas_outfile)}.")
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}%", )
draw(gdstk.Cell("flexible_paths_2").add(fp3, fp4), path) # Flexible Paths 2 # Straight segment showing the possibility of width and offset changes fp5 = gdstk.FlexPath((0, 0), [0.5, 0.5], 1) fp5.horizontal(2) fp5.horizontal(4, width=0.8, offset=1.8) fp5.horizontal(6) draw(gdstk.Cell("flexible_paths_3").add(fp5), path) # Robust Paths # Create 4 parallel paths in different layers rp = gdstk.RobustPath( (0, 50), [2, 0.5, 1, 1], [0, 0, -1, 1], ends=["extended", "round", "flush", "flush"], layer=[1, 0, 2, 2], ) rp.segment((0, 45)) rp.segment( (0, 5), width=[lambda u: 2 + 16 * u * (1 - u), 0.5, 1, 1], offset=[ 0, lambda u: 8 * u * (1 - u) * numpy.cos(12 * numpy.pi * u), lambda u: -1 - 8 * u * (1 - u), lambda u: 1 + 8 * u * (1 - u), ], ) rp.segment((0, 0))
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" path.mkdir(parents=True, exist_ok=True) draw(main, path)
def arc_image(): path = gdstk.RobustPath((0, 0), [0.2, 0.3], 0.4, tolerance=1e-3) path.vertical(5) path.arc(2.5, numpy.pi, 0) path.arc((3, 5), -numpy.pi, -numpy.pi / 2) return gdstk.Cell("arc").add(path)
def cubic_smooth_image(): path = gdstk.RobustPath((0, 0), 0.2, tolerance=1e-3) path.cubic([(0.5, 0.8), (0.5, 2.2), (0, 3)]) path.cubic_smooth([(3.5, 0.8), (3, 0)], relative=True) path.cubic_smooth([(-0.5, -2.2), (0, -3)], relative=True) return gdstk.Cell("cubic_smooth").add(path)
# 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 pathlib from tutorial_images import draw import numpy import gdstk if __name__ == "__main__": main = gdstk.Cell("Main") # Create a path path = gdstk.RobustPath((0, 0), 0.5) path.segment((8, 0)) path.interpolation( [(2, -4), (-2, -6), (-5, -8), (-4, -12)], angles=[0, None, None, None, -numpy.pi / 4], relative=True, ) path.segment((3, -3), relative=True) main.add(path) # Major and minor markers major = gdstk.regular_polygon((0, 0), 0.5, 6, layer=1) minor = gdstk.rectangle((-0.1, -0.5), (0.1, 0.5), layer=1) for s in range(path.size): # A major marker is added at the start of each path section m = major.copy() m.translate(path.position(s))
# 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 pathlib from tutorial_images import draw import numpy import gdstk if __name__ == "__main__": # X-explicit repetition vline = gdstk.FlexPath([(3, 2), (3, 3.5)], 0.1, simple_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, simple_path=True) hline.segment((6, 2)) hline.repetition = gdstk.Repetition(y_offsets=[0.1, 0.3, 0.7, 1.5]) # Create all copies vlines = vline.apply_repetition() hlines = hline.apply_repetition() # Include original elements for boolean operation vlines.append(vline) hlines.append(hline) result = gdstk.boolean(vlines, hlines, "or") main = gdstk.Cell("Main") main.add(*result)
# Boost Software License - Version 1.0. See the accompanying # # LICENSE file or <http://www.boost.org/LICENSE_1_0.txt> # # # ###################################################################### import pathlib from tutorial_images import draw import numpy import gdstk if __name__ == "__main__": main = gdstk.Cell("Main") # Create a path path = gdstk.RobustPath((0, 0), 0.5, layer=2) path.segment((8, 0)) path.interpolation( [(2, -4), (-2, -6), (-5, -8), (-4, -12)], angles=[0, None, None, None, -numpy.pi / 4], relative=True, ) path.segment((3, -3), relative=True) main.add(path) # Major and minor markers major = gdstk.regular_polygon((0, 0), 0.5, 6, layer=1) minor = gdstk.rectangle((-0.1, -0.5), (0.1, 0.5), layer=1) for s in range(path.size): # A major marker is added at the start of each path section m = major.copy()