2021-05-16 19:04:31 -07:00
|
|
|
|
2022-02-23 16:24:22 -08:00
|
|
|
import numpy
|
2021-05-16 19:04:31 -07:00
|
|
|
from numpy import pi
|
|
|
|
|
|
2026-02-16 17:58:34 -08:00
|
|
|
from masque import layer_t, Pattern, Circle, Arc, Ref
|
2026-02-15 20:05:38 -08:00
|
|
|
from masque.repetition import Grid
|
2021-05-16 19:04:31 -07:00
|
|
|
import masque.file.gdsii
|
|
|
|
|
|
2022-02-27 21:21:44 -08:00
|
|
|
|
|
|
|
|
# Note that masque units are arbitrary, and are only given
|
|
|
|
|
# physical significance when writing to a file.
|
2023-01-24 23:25:10 -08:00
|
|
|
GDS_OPTS = dict(
|
|
|
|
|
meters_per_unit = 1e-9, # GDS database unit, 1 nanometer
|
|
|
|
|
logical_units_per_unit = 1e-3, # GDS display unit, 1 micron
|
|
|
|
|
)
|
2021-05-16 19:04:31 -07:00
|
|
|
|
|
|
|
|
|
2022-02-23 11:00:40 -08:00
|
|
|
def hole(
|
|
|
|
|
radius: float,
|
|
|
|
|
layer: layer_t = (1, 0),
|
|
|
|
|
) -> Pattern:
|
2021-05-16 19:04:31 -07:00
|
|
|
"""
|
|
|
|
|
Generate a pattern containing a single circular hole.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
radius: Circle radius.
|
2022-02-27 21:21:44 -08:00
|
|
|
layer: Layer to draw the circle on.
|
2021-05-16 19:04:31 -07:00
|
|
|
|
|
|
|
|
Returns:
|
2023-01-24 23:25:10 -08:00
|
|
|
Pattern containing a circle.
|
2021-05-16 19:04:31 -07:00
|
|
|
"""
|
2023-07-17 20:22:04 -07:00
|
|
|
pat = Pattern()
|
|
|
|
|
pat.shapes[layer].append(
|
|
|
|
|
Circle(radius=radius, offset=(0, 0))
|
|
|
|
|
)
|
2021-05-16 19:04:31 -07:00
|
|
|
return pat
|
|
|
|
|
|
|
|
|
|
|
2026-02-15 20:05:38 -08:00
|
|
|
def hole_array(
|
|
|
|
|
radius: float,
|
|
|
|
|
num_x: int = 5,
|
|
|
|
|
num_y: int = 3,
|
|
|
|
|
pitch: float = 2000,
|
|
|
|
|
layer: layer_t = (1, 0),
|
|
|
|
|
) -> Pattern:
|
|
|
|
|
"""
|
|
|
|
|
Generate an array of circular holes using `Repetition`.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
radius: Circle radius.
|
|
|
|
|
num_x, num_y: Number of holes in x and y.
|
|
|
|
|
pitch: Center-to-center spacing.
|
|
|
|
|
layer: Layer to draw the holes on.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Pattern containing a grid of holes.
|
|
|
|
|
"""
|
|
|
|
|
# First, make a pattern for a single hole
|
|
|
|
|
hpat = hole(radius, layer)
|
|
|
|
|
|
|
|
|
|
# Now, create a pattern that references it multiple times using a Grid
|
|
|
|
|
pat = Pattern()
|
|
|
|
|
pat.refs['hole'] = [
|
|
|
|
|
Ref(
|
|
|
|
|
offset=(0, 0),
|
|
|
|
|
repetition=Grid(a_vector=(pitch, 0), a_count=num_x,
|
|
|
|
|
b_vector=(0, pitch), b_count=num_y)
|
|
|
|
|
)]
|
|
|
|
|
|
|
|
|
|
# We can also add transformed references (rotation, mirroring, etc.)
|
|
|
|
|
pat.refs['hole'].append(
|
|
|
|
|
Ref(offset=(0, -pitch), rotation=pi / 4, mirrored=True)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return pat, hpat
|
|
|
|
|
|
|
|
|
|
|
2022-02-27 21:21:44 -08:00
|
|
|
def triangle(
|
|
|
|
|
radius: float,
|
|
|
|
|
layer: layer_t = (1, 0),
|
|
|
|
|
) -> Pattern:
|
|
|
|
|
"""
|
|
|
|
|
Generate a pattern containing a single triangular hole.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
radius: Radius of circumscribed circle.
|
|
|
|
|
layer: Layer to draw the circle on.
|
|
|
|
|
|
|
|
|
|
Returns:
|
2023-01-24 23:25:10 -08:00
|
|
|
Pattern containing a triangle
|
2022-02-27 21:21:44 -08:00
|
|
|
"""
|
|
|
|
|
vertices = numpy.array([
|
|
|
|
|
(numpy.cos( pi / 2), numpy.sin( pi / 2)),
|
|
|
|
|
(numpy.cos(pi + pi / 6), numpy.sin(pi + pi / 6)),
|
|
|
|
|
(numpy.cos( - pi / 6), numpy.sin( - pi / 6)),
|
2023-01-24 23:25:10 -08:00
|
|
|
]) * radius
|
2022-02-27 21:21:44 -08:00
|
|
|
|
2023-07-17 20:22:04 -07:00
|
|
|
pat = Pattern()
|
2026-02-15 20:05:38 -08:00
|
|
|
pat.polygon(layer, vertices=vertices)
|
2022-02-27 21:21:44 -08:00
|
|
|
return pat
|
|
|
|
|
|
|
|
|
|
|
2022-02-23 11:00:40 -08:00
|
|
|
def smile(
|
|
|
|
|
radius: float,
|
|
|
|
|
layer: layer_t = (1, 0),
|
|
|
|
|
secondary_layer: layer_t = (1, 2)
|
|
|
|
|
) -> Pattern:
|
2021-05-16 19:04:31 -07:00
|
|
|
"""
|
|
|
|
|
Generate a pattern containing a single smiley face.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
radius: Boundary circle radius.
|
|
|
|
|
layer: Layer to draw the outer circle on.
|
|
|
|
|
secondary_layer: Layer to draw eyes and smile on.
|
|
|
|
|
|
|
|
|
|
Returns:
|
2023-01-24 23:25:10 -08:00
|
|
|
Pattern containing a smiley face
|
2021-05-16 19:04:31 -07:00
|
|
|
"""
|
|
|
|
|
# Make an empty pattern
|
2023-01-24 23:25:10 -08:00
|
|
|
pat = Pattern()
|
2021-05-16 19:04:31 -07:00
|
|
|
|
|
|
|
|
# Add all the shapes we want
|
2023-07-17 20:22:04 -07:00
|
|
|
pat.shapes[layer] += [
|
|
|
|
|
Circle(radius=radius, offset=(0, 0)), # Outer circle
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
pat.shapes[secondary_layer] += [
|
|
|
|
|
Circle(radius=radius / 10, offset=(radius / 3, radius / 3)),
|
|
|
|
|
Circle(radius=radius / 10, offset=(-radius / 3, radius / 3)),
|
2023-01-24 23:25:10 -08:00
|
|
|
Arc(
|
|
|
|
|
radii=(radius * 2 / 3, radius * 2 / 3), # Underlying ellipse radii
|
2021-05-16 19:04:31 -07:00
|
|
|
angles=(7 / 6 * pi, 11 / 6 * pi), # Angles limiting the arc
|
|
|
|
|
width=radius / 10,
|
|
|
|
|
offset=(0, 0),
|
2023-01-24 23:25:10 -08:00
|
|
|
),
|
2021-05-16 19:04:31 -07:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
return pat
|
|
|
|
|
|
|
|
|
|
|
2022-02-27 21:21:44 -08:00
|
|
|
def main() -> None:
|
2023-01-24 23:25:10 -08:00
|
|
|
lib = {}
|
2021-05-16 19:04:31 -07:00
|
|
|
|
2023-01-24 23:25:10 -08:00
|
|
|
lib['hole'] = hole(1000)
|
|
|
|
|
lib['smile'] = smile(1000)
|
|
|
|
|
lib['triangle'] = triangle(1000)
|
2021-05-16 19:04:31 -07:00
|
|
|
|
2026-02-15 20:05:38 -08:00
|
|
|
# Use a Grid to make many holes efficiently
|
|
|
|
|
lib['grid'], lib['hole'] = hole_array(1000)
|
|
|
|
|
|
2023-01-24 23:25:10 -08:00
|
|
|
masque.file.gdsii.writefile(lib, 'basic_shapes.gds', **GDS_OPTS)
|
2022-02-27 21:21:44 -08:00
|
|
|
|
2023-01-24 23:25:10 -08:00
|
|
|
lib['triangle'].visualize()
|
2026-02-15 20:05:38 -08:00
|
|
|
lib['grid'].visualize(lib)
|
2021-05-16 19:04:31 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2022-02-27 21:21:44 -08:00
|
|
|
main()
|