import numpy from numpy import pi from masque import layer_t, Pattern, Circle, Arc, Polygon, Ref from masque.repetition import Grid import masque.file.gdsii # Note that masque units are arbitrary, and are only given # physical significance when writing to a file. GDS_OPTS = dict( meters_per_unit = 1e-9, # GDS database unit, 1 nanometer logical_units_per_unit = 1e-3, # GDS display unit, 1 micron ) def hole( radius: float, layer: layer_t = (1, 0), ) -> Pattern: """ Generate a pattern containing a single circular hole. Args: radius: Circle radius. layer: Layer to draw the circle on. Returns: Pattern containing a circle. """ pat = Pattern() pat.shapes[layer].append( Circle(radius=radius, offset=(0, 0)) ) return pat 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 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: Pattern containing a triangle """ 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)), ]) * radius pat = Pattern() pat.polygon(layer, vertices=vertices) return pat def smile( radius: float, layer: layer_t = (1, 0), secondary_layer: layer_t = (1, 2) ) -> Pattern: """ 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: Pattern containing a smiley face """ # Make an empty pattern pat = Pattern() # Add all the shapes we want 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)), Arc( radii=(radius * 2 / 3, radius * 2 / 3), # Underlying ellipse radii angles=(7 / 6 * pi, 11 / 6 * pi), # Angles limiting the arc width=radius / 10, offset=(0, 0), ), ] return pat def main() -> None: lib = {} lib['hole'] = hole(1000) lib['smile'] = smile(1000) lib['triangle'] = triangle(1000) # Use a Grid to make many holes efficiently lib['grid'], lib['hole'] = hole_array(1000) masque.file.gdsii.writefile(lib, 'basic_shapes.gds', **GDS_OPTS) lib['triangle'].visualize() lib['grid'].visualize(lib) if __name__ == '__main__': main()