Ejemplo n.º 1
0
def tree():
    p1 = gdstk.Polygon(((0, 0), (0, 1), (1, 0)), 0, 0)
    p2 = gdstk.Polygon(((2, 0), (2, 1), (1, 0)), 1, 1)
    l1 = gdstk.Label("label1", (0, 0), layer=11)
    l2 = gdstk.Label("label2", (2, 1), layer=12)
    c1 = gdstk.Cell("tree1")
    c1.add(p1)
    c1.add(l1)
    c2 = gdstk.Cell("tree2")
    c2.add(l2)
    c2.add(p2)
    c2.add(gdstk.Reference(c1))
    c3 = gdstk.Cell("tree3")
    c3.add(gdstk.Reference(c2, (0, 0), columns=3, rows=2, spacing=(3, 3)))
    return c3, c2, c1
Ejemplo n.º 2
0
def test_properties():
    for obj in [
            gdstk.Polygon([-1 + 0j, -2j, 3 + 0j, 4j]),
            gdstk.FlexPath((0j, 1j), 0.1),
            gdstk.RobustPath(0j, 0.1),
            gdstk.Label("Label", 0j),
            gdstk.Reference("EMPTY"),
            gdstk.Cell("CELL"),
            gdstk.Library("Name"),
    ]:
        assert len(obj.properties) == 0
        assert obj.get_property("None") is None
        obj.set_property("FIRST", 1)
        obj.set_property("SECOND", 2.0)
        obj.set_property("THIRD", -3)
        obj.set_property("FOURTH", [1, 2.0, -3, "FO", b"UR\x00TH\x00"])
        obj.set_property("FIRST", -1)
        assert obj.get_property("FIRST") == [-1]
        obj.delete_property("THIRD")
        assert obj.properties == [
            ["FIRST", -1],
            ["FOURTH", 1, 2.0, -3, b"FO", b"UR\x00TH\x00"],
            ["SECOND", 2.0],
            ["FIRST", 1],
        ]
        obj.properties = (
            ("ONE", -1),
            ("TWO", -2.3e-4, "two"),
            ("Three", b"\xFF\xEE", 0),
        )
        assert obj.properties == [
            ["ONE", -1],
            ["TWO", -2.3e-4, b"two"],
            ["Three", b"\xFF\xEE", 0],
        ]
Ejemplo n.º 3
0
def test_copy_transform(proof_cells):
    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, simple_path=True,
                       layer=3).arc(2, 0, numpy.pi / 2))
    ref_cell1.add(
        gdstk.RobustPath(7.5 + 7j, 1, simple_path=True,
                         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()
    for path in cell_copy.paths:
        cell_copy.add(*path.to_polygons())
    assert_same_shape(proof_cells["Cell.copy"].polygons, cell_copy.polygons)
Ejemplo n.º 4
0
def test_filter():
    polys = [
        gdstk.rectangle((0, 0), (1, 1), layer=l, datatype=t)
        for t in range(3)
        for l in range(3)
    ]
    labels = [
        gdstk.Label("FILTER", (1, 1), layer=l, texttype=t)
        for t in range(3)
        for l in range(3)
    ]
    paths = [
        gdstk.FlexPath([0j, 1j], [0.1, 0.1, 0.1], 0.5, layer=[0, 1, 2], datatype=t)
        for t in range(3)
    ] + [
        gdstk.RobustPath(0j, [0.1, 0.1], 0.5, layer=[1, 2], datatype=t)
        for t in range(3)
    ]
    layers = [1, 2]
    types = [0]
    for op, test in [
        ("and", lambda a, b: a and b),
        ("or", lambda a, b: a or b),
        ("xor", lambda a, b: (a and not b) or (b and not a)),
        ("nand", lambda a, b: not (a and b)),
        ("nor", lambda a, b: not (a or b)),
        ("nxor", lambda a, b: not ((a and not b) or (b and not a))),
    ]:
        path_results = [
            [test(a in layers, b in types) for a, b in zip(path.layers, path.datatypes)]
            for path in paths
        ]
        cell = gdstk.Cell(op)
        cell.add(*polys, *labels, *paths)
        cell.filter(layers, types, op)

        cell_polys = cell.polygons
        for poly in polys:
            if test(poly.layer in layers, poly.datatype in types):
                assert poly not in cell_polys
            else:
                assert poly in cell_polys
        cell_labels = cell.labels
        for label in labels:
            if test(label.layer in layers, label.texttype in types):
                assert label not in cell_labels
            else:
                assert label in cell_labels
        cell_paths = cell.paths
        for path, results in zip(paths, path_results):
            if all(results):
                assert path not in cell_paths
            else:
                assert path in cell_paths
                assert len(path.layers) == len(results) - sum(results)
                assert all(
                    not test(a in layers, b in types)
                    for a, b in zip(path.layers, path.datatypes)
                )
Ejemplo n.º 5
0
def test_add_element():
    p = gdstk.Polygon(((0, 0), (1, 0), (0, 1)))
    l = gdstk.Label("label", (0, 0))
    c = gdstk.Cell("c_add_element")
    assert c.add(p) is c
    assert c.add(p, l) is c
    polygons = c.polygons
    assert len(polygons) == 2
    assert polygons[0] is p
    assert polygons[1] is p
    assert len(c.labels) == 1
    assert c.labels[0] is l
Ejemplo n.º 6
0
def bench_gdstk(output=None):
    c1 = gdstk.Cell("REF")
    c1.add(gdstk.rectangle((0, 0), (10, 10)))
    c1.add(
        gdstk.FlexPath([(0, 0), (10, 0), (10, 10), (0, 10)], [0.1, 0.1],
                       0.3,
                       layer=1))
    c1.add(gdstk.Label("Label", (5, 5), anchor='o'))
    c2 = gdstk.Cell("MAIN")
    c2.add(gdstk.Reference(c1, columns=3, rows=2, spacing=(20, 20)))
    c2.flatten()
    c1.remove(*c1.polygons, *c1.paths, *c1.labels)
    if output:
        c2.write_svg(output, 10)
Ejemplo n.º 7
0
def test_bb_label_repetition():
    lbl = gdstk.Label("label", (1, 2))
    lbl.repetition = gdstk.Repetition(x_offsets=(1, 3, -2))
    c_lbl = gdstk.Cell("A")
    c_lbl.add(lbl)
    assert_close(c_lbl.bounding_box(), ((-1, 2), (4, 2)))
    ref = gdstk.Reference(c_lbl)
    ref.repetition = gdstk.Repetition(y_offsets=(-1, 2, -4))
    c_ref = gdstk.Cell("B")
    c_ref.add(ref)
    assert_close(c_ref.bounding_box(), ((-1, -2), (4, 4)))
    ref.rotation = numpy.pi / 4
    a = (-1 + 2j) * numpy.exp(0.25j * numpy.pi)
    b = (4 + 2j) * numpy.exp(0.25j * numpy.pi)
    assert_close(c_ref.bounding_box(),
                 ((a.real, a.imag - 4), (b.real, b.imag + 2)))
Ejemplo n.º 8
0
def test_label_bounding_box():
    c = gdstk.Cell("CELL")
    l = gdstk.Label("Label", (2, 3))
    c.add(l)
    bb = c.bounding_box();
    assert bb[0][0] == 2 and bb[0][1] == 3
    assert bb[1][0] == 2 and bb[1][1] == 3
    ref = gdstk.Reference(c, (-1, 1))
    bb = ref.bounding_box()
    assert bb[0][0] == 1 and bb[0][1] == 4
    assert bb[1][0] == 1 and bb[1][1] == 4
    ang = numpy.pi / 4
    x = ref.origin[0] + l.origin[0] * numpy.cos(ang) - l.origin[1] * numpy.sin(ang)
    y = ref.origin[1] + l.origin[0] * numpy.sin(ang) + l.origin[1] * numpy.cos(ang)
    ref.rotation = ang
    bb = ref.bounding_box()
    assert_close(bb, ((x, y), (x, y)))
Ejemplo n.º 9
0
def init_image():
    frame = gdstk.rectangle((-2, -1), (2, 1), datatype=1)
    label_o = gdstk.Label("Center", (0, 0), rotation=numpy.pi / 6)
    label_n = gdstk.Label("North", (0, 1), "n")
    label_s = gdstk.Label("South", (0, -1), "s")
    label_e = gdstk.Label("East", (2, 0), "e")
    label_w = gdstk.Label("West", (-2, 0), "w")
    label_ne = gdstk.Label("Northeast", (2, 1), "ne")
    label_se = gdstk.Label("Southeast", (2, -1), "se")
    label_nw = gdstk.Label("Northwest", (-2, 1), "nw")
    label_sw = gdstk.Label("Southwest", (-2, -1), "sw")
    return gdstk.Cell("init").add(
        frame,
        label_o,
        label_n,
        label_s,
        label_e,
        label_w,
        label_ne,
        label_se,
        label_nw,
        label_sw,
    )
Ejemplo n.º 10
0
def test_properties():
    for obj in [
        gdstk.Polygon([-1 + 0j, -2j, 3 + 0j, 4j]),
        gdstk.FlexPath((0j, 1j), 0.1),
        gdstk.RobustPath(0j, 0.1),
        gdstk.Label("Label", 0j),
        gdstk.Reference("EMPTY"),
    ]:
        assert obj.get_property(12) is None
        assert obj.delete_property(12) is obj
        obj.set_property(13, "Property text")
        assert obj.get_property(12) is None
        assert obj.get_property(13) == "Property text"
        obj.delete_property(13)
        assert obj.get_property(13) is None
        obj.set_property(13, "Second text")
        obj.set_property(13, "Third text")
        assert obj.get_property(13) == "Third text"
Ejemplo n.º 11
0
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
Ejemplo n.º 12
0
def test_copy():
    p = gdstk.Polygon(((0, 0), (1, 0), (0, 1)))
    lbl = gdstk.Label("label", (0, 0))
    cref = gdstk.Cell("ref").add(gdstk.rectangle((-1, -1), (-2, -2)))
    ref = gdstk.Reference(cref)
    cell = gdstk.Cell("original")
    cell.add(p, lbl, ref)
    shallow_copy = cell.copy("copy_0", deep_copy=False)
    assert len(shallow_copy.polygons) == len(cell.polygons)
    assert p in shallow_copy.polygons
    assert len(shallow_copy.labels) == len(cell.labels)
    assert lbl in shallow_copy.labels
    assert len(shallow_copy.references) == len(cell.references)
    assert ref in shallow_copy.references
    deep_copy = cell.copy("copy_1")
    assert len(deep_copy.polygons) == len(cell.polygons)
    assert p not in deep_copy.polygons
    assert len(deep_copy.labels) == len(cell.labels)
    assert lbl not in deep_copy.labels
    assert len(deep_copy.references) == len(cell.references)
    assert ref not in deep_copy.references
    assert deep_copy.references[0].cell is ref.cell
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
def test_gds_properties():
    for obj in [
            gdstk.Polygon([-1 + 0j, -2j, 3 + 0j, 4j]),
            gdstk.FlexPath((0j, 1j), 0.1),
            gdstk.RobustPath(0j, 0.1),
            gdstk.Label("Label", 0j),
            gdstk.Reference("EMPTY"),
    ]:
        assert obj.get_gds_property(12) is None
        assert obj.delete_gds_property(12) is obj
        obj.set_gds_property(13, "Property text")
        assert obj.get_gds_property(12) is None
        assert obj.get_gds_property(13) == "Property text"
        obj.delete_gds_property(13)
        assert obj.get_gds_property(13) is None
        obj.set_gds_property(13, "Second text")
        obj.set_gds_property(13, "Third text")
        obj.set_gds_property(14, "Fourth text")
        assert obj.get_gds_property(13) == "Third text"
        assert obj.properties == [
            ["S_GDS_PROPERTY", 14, b"Fourth text\x00"],
            ["S_GDS_PROPERTY", 13, b"Third text\x00"],
        ]
Ejemplo n.º 15
0
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)}.")
Ejemplo n.º 16
0
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}%",
        )
Ejemplo n.º 17
0
        offset=[-0.25, 0.25, -0.75, 0.75],
    )
    rp.parametric(
        lambda u: numpy.array((4 * numpy.sin(6 * numpy.pi * u), 45 * u)),
        offset=[
            lambda u: -0.25 * numpy.cos(24 * numpy.pi * u),
            lambda u: 0.25 * numpy.cos(24 * numpy.pi * u),
            -0.75,
            0.75,
        ],
    )
    draw(gdstk.Cell("robust_paths").add(rp), path)

    # Text
    # Label centered at (1, 3)
    label = gdstk.Label("Sample label", (5, 3), texttype=2)

    # Horizontal text with height 2.25
    htext = gdstk.text("12345", 2.25, (0.25, 6))

    # Vertical text with height 1.5
    vtext = gdstk.text("ABC", 1.5, (10.5, 4), vertical=True)

    rect = gdstk.rectangle((0, 0), (10, 6), layer=10)
    draw(gdstk.Cell("text").add(*htext, *vtext, label, rect), path)

    # Boolean Operations
    # Create some text
    text = gdstk.text("GDSTK", 4, (0, 0))
    # Create a rectangle extending the text's bounding box by 1
    rect = gdstk.rectangle((-1, -1), (5 * 4 * 9 / 16 + 1, 4 + 1))