def connect_lineShape(cell, pos_start, len): path = gdspy.Path(w_wg, pos_start) path.segment(len, **layer_FETCH_COR) cell.add(path) path = gdspy.Path(w_wg_cld, pos_start) path.segment(len, **layer_FETCH_CLD) cell.add(path)
def Heater(l_heater2): # define heater w_heater = 3 w_port = 10 w_wire = w_port * 2 cell = lib.new_cell('heater') # add middle long rect heater = gdspy.Rectangle((0, w_heater / 2), (l_heater2, -w_heater / 2), **layer_heater) cell.add(heater) # add left rect and wire heater = gdspy.Rectangle((-w_port / 2, w_port / 2), (w_port / 2, -w_port / 2), **layer_heater) cell.add(heater) heater = gdspy.Rectangle((-w_wire / 2, w_wire / 2), (w_wire / 2, -w_wire / 2), **layer_wire) cell.add(heater) # add right rect and wire heater = gdspy.Rectangle((l_heater2 - w_port / 2, w_port / 2), (l_heater2 + w_port / 2, -w_port / 2), **layer_heater) cell.add(heater) heater = gdspy.Rectangle((l_heater2 - w_wire / 2, w_wire / 2), (l_heater2 + w_wire / 2, -w_wire / 2), **layer_wire) cell.add(heater) path1 = gdspy.Path(w_wg) path1.segment(l_heater2) path2 = gdspy.Path(w_wg_cld) path2.segment(l_heater2) cell.add(gdspy.boolean(path2, path1, 'xor', **layer_FETCH_COR)) return cell
def endgap(self): gapwid = self.gapwid tracewid = self.tracewid if (self.x == self.paths[0].x) & (self.y == self.paths[0].y): dirction = self.paths[0].direction endctrpt = (self.paths[0].x, self.paths[0].y) rightend = addtup( addtup( endctrpt, scalartup(0.5 * gapwid, (numpy.cos(dirction + numpy.pi), numpy.sin(dirction + numpy.pi)))), scalartup(0.5 * (tracewid + 2 * gapwid), (numpy.cos(dirction - numpy.pi / 2), numpy.sin(dirction - numpy.pi / 2)))) endcap = gdspy.Path(gapwid, rightend) endcap.segment(tracewid + 2 * gapwid, dirction + numpy.pi / 2) self.paths.append(endcap) else: dirction = self.paths[0].direction endctrpt = (self.paths[0].x, self.paths[0].y) rightend = addtup( addtup( endctrpt, scalartup(0.5 * gapwid, (numpy.cos(dirction), numpy.sin(dirction)))), scalartup(0.5 * (tracewid + 2 * gapwid), (numpy.cos(dirction - numpy.pi / 2), numpy.sin(dirction - numpy.pi / 2)))) endcap = gdspy.Path(gapwid, rightend) endcap.segment(tracewid + 2 * gapwid, dirction + numpy.pi / 2) self.paths.append(endcap)
def __init__(self, leaddist, leadlen, leadwid, squidheight, layer=0, datatype=1): self.spec_side = {'layer': layer, 'datatype': datatype} self.spec_mid = {'layer': layer + 1, 'datatype': datatype} self.LeadDist = leaddist self.LeadWid = leadwid self.SquidHeight = squidheight self.LeadLen = leadlen midlead = gdspy.Path(leadwid, (0, 0)) midlead.segment(leadlen, -numpy.pi / 2, **(self.spec_mid)) midlead.segment(leadlen, -numpy.pi / 2, final_width=0, **(self.spec_mid)) sideleads = gdspy.Path(leadwid, (0, -squidheight), number_of_paths=2, distance=leaddist) sideleads.segment(leadlen, numpy.pi / 2, **(self.spec_side)) sideleads.segment(leadlen, numpy.pi / 2, final_width=0, **(self.spec_side)) self.paths = [midlead, sideleads]
def __build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell # Add waveguide s-bend wg = gdspy.Path(self.wgt.wg_width, (0, 0)) wg.parametric( self.__sine_function, tolerance=self.wgt.grid / 2.0, max_points=199, **self.wg_spec ) self.add(wg) # Add cladding s-bend for i in range(len(self.wgt.waveguide_stack) - 1): cur_width = self.wgt.waveguide_stack[i + 1][0] cur_spec = { "layer": self.wgt.waveguide_stack[i + 1][1][0], "datatype": self.wgt.waveguide_stack[i + 1][1][1], } clad = gdspy.Path(cur_width, (0, 0)) clad.parametric( self.__sine_function, tolerance=self.wgt.grid / 2.0, max_points=199, **cur_spec ) self.add(clad)
def DC(lib, cellName='DC', l_Coupler=20, spacing=0.6, radius_bend=10, l_ver=10, w_wg=0.5): l_PortIn = 10 cell = lib.new_cell(cellName) path_dc = gdspy.Path(w_wg, (0,0)) path_dc.segment(l_PortIn) path_dc.turn(radius_bend,'r') path_dc.segment(l_ver) path_dc.turn(radius_bend,'l') path_dc.segment(l_Coupler) path_dc.turn(radius_bend,'l') path_dc.segment(l_ver) path_dc.turn(radius_bend,'r') path_dc.segment(l_PortIn) cell.add(path_dc) path_dc = gdspy.Path(w_wg, (0, -(l_ver*2+radius_bend*4+spacing))) path_dc.segment(l_PortIn) path_dc.turn(radius_bend,'l') path_dc.segment(l_ver) path_dc.turn(radius_bend,'r') path_dc.segment(l_Coupler) path_dc.turn(radius_bend,'r') path_dc.segment(l_ver) path_dc.turn(radius_bend,'l') path_dc.segment(l_PortIn) cell.add(path_dc) return cell
def __build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # then add it to the Cell num_teeth = int(self.length // self.period) """ Create a straight grating GratingCoupler """ gap = self.period - (self.period * self.dc) path = gdspy.Path(self.wgt.wg_width, (0, 0)) path.segment(self.taper_length, direction="+x", final_width=self.width, **self.wg_spec) teeth = gdspy.L1Path(( gap + self.taper_length + 0.5 * (num_teeth - 1 + self.dc) * self.period, -0.5 * self.width, ), "+y", self.period * self.dc, [self.width], [], num_teeth, self.period, **self.wg_spec) clad_path = gdspy.Path(self.wgt.wg_width + 2 * self.wgt.clad_width, (0, 0)) clad_path.segment(self.taper_length, direction="+x", final_width=self.width + 2 * self.wgt.clad_width, **self.clad_spec) clad_path.segment(self.length, direction="+x", **self.clad_spec) self.add(teeth) self.add(path) self.add(clad_path)
def spiral(cell, w=0.5, pitch=2, r_min=10, r_max=40): """ cell: is the reference of cell \n w is the width of waveguide \n pitch is the min distance between two waveguides. \n """ path1 = gdspy.Path(w, (0, 0)) path2 = gdspy.Path(w, (0, 0)) path3 = gdspy.Path(w, (-r_min, 0)) a = r_min k = r_max - r_min N = k/pitch def spiral1(u): theta = N * numpy.pi * u r = a + k*theta/( N * numpy.pi) x = r * numpy.cos(theta) y = r * numpy.sin(theta) return (x, y) def spiral2(u): theta = (N+1) * numpy.pi * u r = -( a + k*theta/( N * numpy.pi) ) x = r * numpy.cos(theta) y = r * numpy.sin(theta) return (x, y) def dspiral_dt(u): theta = N * numpy.pi * u dx_dt = -numpy.sin(theta) dy_dt = numpy.cos(theta) # dx_dt = k*numpy.cos(theta) - (a + k*u)*N*numpy.pi*numpy.sin(theta) # dy_dt = k*numpy.sin(theta) + (a + k*u)*N*numpy.pi*numpy.cos(theta) return (dx_dt, dy_dt) def dspiral_dt2(u): theta = (N+1) * numpy.pi * u dx_dt = -numpy.sin(theta) dy_dt = numpy.cos(theta) # dx_dt = k*numpy.cos(theta) - (a + k*u)*N*numpy.pi*numpy.sin(theta) # dy_dt = k*numpy.sin(theta) + (a + k*u)*N*numpy.pi*numpy.cos(theta) return (dx_dt, dy_dt) # Add the parametric spiral to the path path1.parametric(spiral1, dspiral_dt) path2.parametric(spiral2, dspiral_dt2) path3.turn(r_min/2, 'rr') path3.turn(r_min/2, 'll') path3.rotate(numpy.pi/2, (-r_min, 0)) cell.add(path1) cell.add(path2) cell.add(path3)
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # then add it to the Cell num_teeth = int(self.length//self.period) if self.focus_distance < self.width/2.0 - self.period: raise ValueError("Warning! The focus_distance is smaller than the allowed value of width/2.0 - period.") neff = self.wavelength / float(self.period) + self.sin_theta qmin = int(self.focus_distance / float(self.period) + 0.5) max_points = 199 c3 = neff**2 - self.sin_theta**2 w = 0.5 * self.width path = gdspy.Path(self.wgt.clad_width, self.port, number_of_paths=2, distance=self.wgt.wg_width + self.wgt.clad_width) teeth = gdspy.Path(self.period * self.dc, self.port) for q in range(qmin, qmin + num_teeth): c1 = q * self.wavelength * self.sin_theta c2 = (q * self.wavelength)**2 teeth.parametric(lambda t: (self.width * t - w, (c1 + neff * np.sqrt(c2 - c3 * (self.width * t - w)**2)) / c3), number_of_evaluations=self.evaluations, max_points=max_points, **self.wg_spec) teeth.x = self.port[0] teeth.y = self.port[1] teeth.polygons[0] = np.vstack( (teeth.polygons[0][:self.evaluations, :], ([(self.port[0] + 0.5 * self.wgt.wg_width, self.port[1]), (self.port[0] - 0.5 * self.wgt.wg_width, self.port[1])]))) teeth.fracture() clad_path = gdspy.Path(self.wgt.wg_width + 2*self.wgt.clad_width, self.port) clad_path.segment(self.focus_distance, direction='+y', final_width=self.width+2*self.wgt.clad_width, **self.clad_spec) clad_path.segment(self.length, direction='+y', **self.clad_spec) if self.direction=="WEST": teeth.rotate(np.pi/2.0, self.port) path.rotate(np.pi/2.0, self.port) clad_path.rotate(np.pi/2.0, self.port) if self.direction=="SOUTH": teeth.rotate(np.pi, self.port) path.rotate(np.pi, self.port) clad_path.rotate(np.pi, self.port) if self.direction=="EAST": teeth.rotate(-np.pi/2.0, self.port) path.rotate(-np.pi/2.0, self.port) clad_path.rotate(-np.pi/2.0, self.port) elif isinstance(self.direction, float): teeth.rotate(self.direction - np.pi/2.0, self.port) path.rotate(self.direction -np.pi/2.0, self.port) clad_path.rotate(self.direction-np.pi/2.0, self.port) self.add(teeth) self.add(path) self.add(clad_path)
def test_slice(): poly = gdspy.Path(1, (1, 0), 2, 3).segment(2, "-x") left = gdspy.Path(1, (0, 0), 2, 3).segment(1, "-x") right = gdspy.Path(1, (1, 0), 2, 3).segment(1, "-x") result = gdspy.slice(poly, 0, 0) assert equals(result[0], left) assert equals(result[1], right) bot = gdspy.Path(1, (1, -1.5)).segment(2, "-x") top = gdspy.Path(1, (1, 1.5)).segment(2, "-x") result = gdspy.slice(poly, [0.1, -0.1], 1) assert equals(result[0], bot) assert equals(result[2], top) assert result[1] is None
def gc_line(cell, gc, origin=(0, 0), l=200): cell.add(gdspy.CellReference(gc, origin)) cell.add(gdspy.CellReference(gc, (l + origin[0], origin[1]), rotation=180)) path_connect = gdspy.Path(w_wg) path_connect.segment(l) path_connect2 = gdspy.Path(w_wg + 6) path_connect2.segment(l) path_connect_positive = gdspy.boolean(path_connect, path_connect2, 'xor', layer=1, datatype=1) cell.add(path_connect_positive) return cell
def connect_zShape(cell, pos_start=(0, 0), pos_end=(0, 0), direction=1, w=w_wg, layer=1, datatype=1): ''' pos_end is relative to the pos_start ''' path = gdspy.Path(w, pos_start) path.segment(len_port_ext, layer=layer, datatype=datatype) if direction == 1: path.turn(radius, 'r', layer=layer, datatype=datatype) else: path.turn(radius, 'l', layer=layer, datatype=datatype) path.segment(abs(pos_end[1] - pos_start[1]) - 2 * radius, layer=layer, datatype=datatype) if direction == 1: path.turn(radius, 'l', layer=layer, datatype=datatype) else: path.turn(radius, 'r', layer=layer, datatype=datatype) path.segment(pos_end[0] - 2 * radius - len_port_ext, layer=layer, datatype=datatype) # cell.add(path) return path
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell angle = tk.get_angle(self.trace[0], self.trace[1]) # Add waveguide taper path = gdspy.Path(self.wgt.wg_width, self.trace[0]) path.segment(tk.dist(self.trace[0], self.trace[1]), direction=angle, final_width=self.end_width, **self.wg_spec) # Cladding for waveguide taper path2 = gdspy.Path(2*self.wgt.clad_width+self.wgt.wg_width, self.trace[0]) path2.segment(tk.dist(self.trace[0], self.trace[1]), direction=angle, final_width=2*self.end_clad_width+self.end_width, **self.clad_spec) path2.segment(self.extra_clad_length, **self.clad_spec) self.add(path) self.add(path2)
def dose_test(geometry, wf_size, biggest_feature=0.1): """ generate a dose test for the given geometry Args: geometry: gdspy.PolygonSet wf_size: target writefield size biggest_feature: largest feature as a percentage of the writefield size """ smlfeats = [] for i, p in enumerate(geometry.polygons): if p.shape[0] == 4: # only use rectangular features X, Y = np.sort(p[:, 0]), np.sort(p[:, 1]) smlfeats += [np.abs(X[-1] - X[0]), np.abs(Y[-1] - Y[0])] smallest_feature = np.min(smlfeats) N_tests = round(1.0 / biggest_feature) tests = [] for i in range(N_tests): test_atom = gdspy.Path(width = wf_size*biggest_feature)\ .segment(0.1*wf_size, '+y')\ .translate(wf_size*biggest_feature/2, 0)\ .segment(0.3*wf_size, '+y', final_width = smallest_feature)\ .segment(0.1*wf_size, '+y')\ .translate(i*wf_size/N_tests, 0) if i % 2: tests.append(test_atom.mirror((1, 0)).translate(0, wf_size)) else: tests.append(test_atom) pattern = union(tests) change_layer(pattern, 10) return pattern
def test_gather(): def same_points(x, y): for px, py in zip(x, y): for ptx, pty in zip(px, py): for cx, cy in zip(ptx, pty): if cx != cy: return False return True pts = [(0, 0), (1, 1), (1, 0)] ps1 = gdspy.Round((10, 10), 1, inner_radius=0.2) ps2 = gdspy.Path(0.1, (-1, -1), 2, 1).segment(2, "-x") c = gdspy.Cell("C1").add(gdspy.Rectangle((-4, 3), (-5, 4))) cr = gdspy.CellReference(c, (10, -10)) ca = gdspy.CellArray(c, 2, 1, (2, 0)) assert gdspy.operation._gather_polys(None) == [] assert same_points(gdspy.operation._gather_polys([pts]), [pts]) assert same_points(gdspy.operation._gather_polys(ps1), ps1.polygons) assert same_points(gdspy.operation._gather_polys(ps2), ps2.polygons) assert same_points(gdspy.operation._gather_polys(cr), cr.get_polygons()) assert same_points(gdspy.operation._gather_polys(ca), ca.get_polygons()) result = [pts] result.extend(ps2.polygons) result.extend(cr.get_polygons()) assert same_points(gdspy.operation._gather_polys([pts, ps2, cr]), result)
def build_DC(w, laayer=1, datatype=1): path_dc = gdspy.Path(w, (0, 0)) path_dc.segment(l_PortIn) path_dc.turn(radius_bend, 'r') path_dc.segment(spacing_FA / 2 - gap / 2 - w_wg / 2 - 2 * radius_bend) path_dc.turn(radius_bend, 'l') path_dc.segment(l_DC) path_dc.turn(radius_bend, 'l') path_dc.segment(l_ver) path_dc.turn(radius_bend, 'r') path_dc.segment(l_heater) path_dc.turn(radius_bend, 'r') path_dc.segment(l_ver) path_dc.turn(radius_bend, 'l') path_dc.segment(l_DC) path_dc.turn(radius_bend, 'l') path_dc.segment(l_ver) path_dc.turn(radius_bend, 'r') path_dc.segment(l_heater) path_dc.turn(radius_bend, 'r') path_dc.segment(l_ver) path_dc.turn(radius_bend, 'l') path_dc.segment(l_DC) path_dc.turn(radius_bend, 'l') path_dc.segment(l_ver + spacing_wg) path_dc.turn(radius_bend, 'l') path_dc.segment(l_MZIs) path_dc.turn(radius_bend, 'l') path_dc.segment(l_ver + spacing_wg + gap / 2 + w_wg / 2 - spacing_FA * 3 / 2) path_dc.turn(radius_bend, 'r') path_dc.segment(l_PortOut) return path_dc
def gds(self, filename=None, view=False, extra=0, units='nms'): #check to make sure the geometry isn't an array if len(self.clean_args(None)[0]) != 1: raise ValueError( "You have changing geometries, making gds doesn't make sense") if units == 'nms': scale = 1 elif units == 'microns': scale = 10**-3 else: raise ValueError('Invalid units') #scale to proper units sc_radius = self.radius * scale sc_gap = self.gap * scale sc_width = self.width * scale sc_length = self.length * scale #write to GDS pathTop = gdspy.Path(sc_width, (sc_radius + sc_length / 2, sc_radius + sc_width / 2 + sc_gap / 2 + extra)) pathTop.segment(extra, '-y') pathTop.arc(sc_radius, 0, -np.pi / 2) pathTop.segment(sc_length, '-x') pathTop.arc(sc_radius, -np.pi / 2, -np.pi) pathTop.segment(extra, '+y') pathBottom = gdspy.Path(sc_width, (-sc_radius - sc_width / 2 - sc_length / 2 - extra, -sc_gap / 2 - sc_width / 2)) pathBottom.segment( 2 * (sc_radius + sc_width / 2) + sc_length + 2 * extra, '+x') gdspy.current_library = gdspy.GdsLibrary() path_cell = gdspy.Cell('C0') path_cell.add(pathTop) path_cell.add(pathBottom) if view: gdspy.LayoutViewer(cells='C0') if filename is not None: writer = gdspy.GdsWriter(filename, unit=1.0e-6, precision=1.0e-9) writer.write_cell(path_cell) writer.close()
def addlauncher(self, final_TraceWid, final_GapWid, final_Length, tran_Length): if (self.x == self.paths[0].x) & (self.y == self.paths[0].y): dirction = self.paths[0].direction self.addsegment(dirction + numpy.pi, tran_Length, final_TraceWid, final_GapWid) self.addsegment(dirction + numpy.pi, final_Length) endctrpt = (self.paths[0].x, self.paths[0].y) rightend = addtup( addtup( endctrpt, scalartup(0.5 * final_GapWid, (numpy.cos(dirction + numpy.pi), numpy.sin(dirction + numpy.pi)))), scalartup(0.5 * (final_TraceWid + 2 * final_GapWid), (numpy.cos(dirction - numpy.pi / 2), numpy.sin(dirction - numpy.pi / 2)))) pathlaunch = gdspy.Path(final_GapWid, rightend) pathlaunch.segment(final_TraceWid + 2 * final_GapWid, dirction + numpy.pi / 2) self.paths[0].x = self.x self.paths[0].y = self.y self.paths[0].distance = self.tracewid + self.gapwid self.paths[0].w = self.gapwid / 2 self.paths.append(pathlaunch) else: self.finalx = self.paths[0].x self.finaly = self.paths[0].y dirction = self.paths[0].direction self.addsegment(dirction, tran_Length, final_TraceWid, final_GapWid) self.addsegment(dirction, final_Length) endctrpt = (self.paths[0].x, self.paths[0].y) rightend = addtup( addtup( endctrpt, scalartup(0.5 * final_GapWid, (numpy.cos(dirction), numpy.sin(dirction)))), scalartup(0.5 * (final_TraceWid + 2 * final_GapWid), (numpy.cos(dirction - numpy.pi / 2), numpy.sin(dirction - numpy.pi / 2)))) pathlaunch = gdspy.Path(final_GapWid, rightend) pathlaunch.segment(final_TraceWid + 2 * final_GapWid, dirction + numpy.pi / 2) self.paths[0].x = self.finalx self.paths[0].y = self.finaly self.paths.append(pathlaunch)
def build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell angle = tk.get_exact_angle(self.trace[0], self.trace[1]) angle_opp = tk.get_exact_angle(self.trace[1], self.trace[0]) # Add strip waveguide taper path_strip = gdspy.Path(self.wgt_strip.wg_width, self.trace[0]) path_strip.segment(self.length, final_width=self.end_strip_width, direction=angle, **self.wg_spec) # Add slot waveguide taper path_slot = gdspy.Path(self.wgt_slot.rail, self.trace[1], number_of_paths=2, distance=self.wgt_slot.rail_dist) path_slot.segment(self.length, final_width=self.end_slot_width, final_distance=(self.wgt_strip.wg_width + 2 * self.d + self.end_slot_width), direction=angle_opp, **self.wg_spec) # Cladding for waveguide taper path_clad = gdspy.Path( 2 * self.wgt_strip.clad_width + self.wgt_strip.wg_width, self.trace[0]) path_clad.segment(self.length, final_width=2 * self.wgt_slot.clad_width + self.wgt_slot.wg_width, direction=angle, **self.clad_spec) if not self.input_strip: center_pt = ((self.trace[0][0] + self.trace[1][0]) / 2.0, (self.trace[0][1] + self.trace[1][1]) / 2.0) path_strip.rotate(np.pi, center_pt) path_slot.rotate(np.pi, center_pt) path_clad.rotate(np.pi, center_pt) self.add(path_strip) self.add(path_slot) self.add(path_clad)
def addwires(self, wirewids, extralen=0): squidheight = self.SquidHeight midlead = gdspy.Path(wirewids[0], (-self.LeadDist / 2 - extralen, -2 * self.LeadLen + wirewids[0] / 2)) midlead.segment(self.LeadDist + extralen * 2, 0, **(self.spec_mid)) sidelead1 = gdspy.Path( wirewids[1], (-self.LeadDist / 2, -squidheight + 1 * self.LeadLen)) sidelead1.segment( self.SquidHeight - 4 * self.LeadLen + self.LeadLen + extralen, numpy.pi / 2, **(self.spec_side)) sidelead2 = gdspy.Path( wirewids[2], (self.LeadDist / 2, -squidheight + 1 * self.LeadLen)) sidelead2.segment( self.SquidHeight - 4 * self.LeadLen + self.LeadLen + extralen, numpy.pi / 2, **(self.spec_side)) self.paths = self.paths + [midlead, sidelead1, sidelead2]
def create_cavity(x,y,width,separation_of_first,width_of_first): length=(width_of_first*separation_of_first)/width cavity_pair.add(gdspy.Rectangle((-Op_Cav_Width/2+x,-Op_Cav_Len/2+y),(Op_Cav_Width/2+x,Op_Cav_Len/2+y),**spec1)) ynew=length+Pill_Cav_Len/2+Op_Cav_Len/2 cavity_pair.add(gdspy.Rectangle((-Op_Cav_Width/2+x,-Op_Cav_Len/2+y+ynew),(Op_Cav_Width/2+x,Op_Cav_Len/2+y+ynew),**spec1)) path1=gdspy.Path(width,(x,y+Op_Cav_Len/2)) path1.segment(length,'+y',**spec1) cavity_pair.add(path1)
def __init__(self, w, d): # w is the width of center conductor, d is the width of gap self.w = w self.d = d self.D = d + w self.path1 = gs.Path(d, (0, 0), number_of_paths=2, distance=self.D) # self.path2=gs.Path(d) self.length = 0
def gc_line(cell, gc, origin=(0,0), l=200, w_wg=0.5, w_etch=3): """ cell: cell in Gdspy \n w_gc: width of grating coupler \n w_wg: width of waveguide\n w_etch: width of etch """ cell.add(gdspy.CellReference(gc, origin)) cell.add(gdspy.CellReference(gc, (l+origin[0], origin[1]), rotation=180)) path_connect = gdspy.Path(w_wg) path_connect.segment(l) path_connect2 = gdspy.Path(w_wg+w_etch*2) path_connect2.segment(l) path_connect_positive = gdspy.boolean(path_connect, path_connect2,'xor',layer=1, datatype=1) cell.add(path_connect_positive) return cell
def RouteStraight(p1, p2, layer, path_type='straight', width_type='straight'): """ Routes a straight polygon between two ports. Example ------- >>> R = RouteStraight() """ point_a = p1.midpoint point_b = p2.midpoint width_input = p1.width width_output = p2.width if ug.angle_diff(p2.orientation, p1.orientation) != 180: raise ValueError('Ports do not face eachother.') separation = np.array([point_b[0], point_b[1]]) - np.array( [point_a[0], point_a[1]]) distance = norm(separation) rotation = np.arctan2(separation[1], separation[0]) * constants.RAD2DEG angle = rotation - p1.orientation xf = distance * np.cos(angle * constants.DEG2RAD) yf = distance * np.sin(angle * constants.DEG2RAD) if path_type == 'straight': curve_fun = lambda t: [xf * t, yf * t] curve_deriv_fun = lambda t: [xf + t * 0, 0 + t * 0] if path_type == 'sine': curve_fun = lambda t: [xf * t, yf * (1 - np.cos(t * np.pi)) / 2] curve_deriv_fun = lambda t: [ xf + t * 0, yf * (np.sin(t * np.pi) * np.pi) / 2 ] if width_type == 'straight': width_fun = lambda t: (width_output - width_input) * t + width_input if width_type == 'sine': width_fun = lambda t: (width_output - width_input) * (1 - np.cos( t * np.pi)) / 2 + width_input route_path = gdspy.Path(width=width_input, initial_point=(0, 0)) route_path.parametric(curve_fun, curve_deriv_fun, final_width=width_fun) port1 = Port(name='I1', midpoint=(0, 0), width=width_input, orientation=180, process=layer.process) port2 = Port(name='I2', midpoint=(xf, yf), width=width_output, orientation=0, process=layer.process) route_shape = RouteShape(path=route_path) R = Route(shape=route_shape, p1=port1, p2=port2, layer=layer) T = vector_match_transform(v1=R.ports[0], v2=p1) R.transform(T) return R
def build_cell(self): #Sequentially build all the geometric shapes using gdspy path functions #then add it to the Cell num_teeth = int(self.length // self.period) """ Create a straight grating GratingCoupler """ gap = self.period - (self.period * self.dc) path = gdspy.Path(self.wgt.wg_width, self.port) path.segment(self.taper_length, direction='+y', final_width=self.width, **self.wg_spec) teeth = gdspy.L1Path( (self.port[0] - 0.5 * self.width, gap + self.taper_length + self.port[1] + 0.5 * (num_teeth - 1 + self.dc) * self.period), '+x', self.period * self.dc, [self.width], [], num_teeth, self.period, **self.wg_spec) clad_path = gdspy.Path(self.wgt.wg_width + 2 * self.wgt.clad_width, self.port) clad_path.segment(self.taper_length, direction='+y', final_width=self.width + 2 * self.wgt.clad_width, **self.clad_spec) clad_path.segment(self.length, direction='+y', **self.clad_spec) if self.direction == "WEST": teeth.rotate(np.pi / 2.0, self.port) path.rotate(np.pi / 2.0, self.port) clad_path.rotate(np.pi / 2.0, self.port) elif self.direction == "SOUTH": teeth.rotate(np.pi, self.port) path.rotate(np.pi, self.port) clad_path.rotate(np.pi, self.port) elif self.direction == "EAST": teeth.rotate(-np.pi / 2.0, self.port) path.rotate(-np.pi / 2.0, self.port) clad_path.rotate(-np.pi / 2.0, self.port) elif isinstance(self.direction, float): teeth.rotate(self.direction - np.pi / 2.0, self.port) path.rotate(self.direction - np.pi / 2.0, self.port) clad_path.rotate(self.direction - np.pi / 2.0, self.port) self.add(teeth) self.add(path) self.add(clad_path)
def bc(w_wg=0.5, l_bc=100, w_bc=127 / 2, tolerance=0.01): ''' w_wg is the width of waveguide \n l_bc is length of bezier curve \n w_bc is the width of bezier curve''' path = gdspy.Path(w_wg, (0, 0)) v = [(l_bc / 2, 0), (l_bc / 2, w_bc), (l_bc, w_bc)] # the first point (0, 0) is omiited path.bezier(v, tolerance=tolerance) return path
def __init__(self, ct, ch, fillet=0, layer=0, datatype=0): self.spec = {'layer': layer, 'datatype': datatype} Harm = gdspy.Path(ct, (-ch / 2, 0)) Harm.segment(ch, 0, **(self.spec)) Varm = gdspy.Path(ct, (0, -ch / 2)) Varm.segment(ch, numpy.pi / 2, **(self.spec)) self.paths = [Harm, Varm] if (fillet != 0): filletwid = fillet * numpy.sqrt(2) filletlen = filletwid / 2 + fillet for psign in [-1, 1]: for qsign in [-1, 1]: for len1 in [ct / 2, ch / 2]: for len2 in [ct / 2, ch / 2]: pt = (psign * len1, qsign * len2) if (len1 == ch / 2) & (len2 == ch / 2): continue elif (len1 == ct / 2) & (len2 == ct / 2): direction = (-psign / numpy.sqrt(2), -qsign / numpy.sqrt(2)) p = gdspy.Path( filletwid, (pt[0] - direction[0] * filletwid / 2, pt[1] - direction[1] * filletwid / 2)) #p=gdspy.Path(filletwid,pt) p.segment(filletlen, numpy.arctan2( direction[1], direction[0]), final_width=0) self.paths.append(p) else: direction = (psign / numpy.sqrt(2), qsign / numpy.sqrt(2)) p = gdspy.Path( filletwid, (pt[0] - direction[0] * filletwid / 2, pt[1] - direction[1] * filletwid / 2)) #p=gdspy.Path(filletwid,pt) p.segment(filletlen, numpy.arctan2( direction[1], direction[0]), final_width=0) self.paths.append(p)
def __build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell # Uncomment below to plot the function (useful for debugging) # import matplotlib.pyplot as plt # tvals = np.linspace(0,1,5000) # xy = [self.__euler_s_function(tv) for tv in tvals] # plt.scatter(*zip(*xy)) # plt.show() if self.wgt.wg_type == "strip": wg = gdspy.Path(self.start_width, (0, 0)) elif self.wgt.wg_type == "slot": wg = gdspy.Path( self.wgt.rail, (0, 0), number_of_paths=2, distance=self.wgt.rail_dist ) wg.parametric( self.__euler_s_function, final_width=self.end_width, tolerance=self.wgt.grid / 2.0, max_points=199, **self.wg_spec ) self.add(wg) # Add cladding for i in range(len(self.wgt.waveguide_stack) - 1): cur_width = self.wgt.waveguide_stack[i + 1][0] cur_spec = { "layer": self.wgt.waveguide_stack[i + 1][1][0], "datatype": self.wgt.waveguide_stack[i + 1][1][1], } clad = gdspy.Path(cur_width, (0, 0)) clad.parametric( self.__euler_s_function, tolerance=self.wgt.grid / 2.0, max_points=199, **cur_spec ) self.add(clad)
def __build_cell(self): # Sequentially build all the geometric shapes using gdspy path functions # for waveguide, then add it to the Cell # Add strip waveguide taper path_strip = gdspy.Path(self.wgt_strip.wg_width, (0, 0)) path_strip.segment(self.length, final_width=self.end_strip_width, direction=0, **self.wg_spec) # Add slot waveguide taper path_slot = gdspy.Path( self.wgt_slot.rail, (self.length, 0), number_of_paths=2, distance=self.wgt_slot.rail_dist, ) path_slot.segment(self.length, final_width=self.end_slot_width, final_distance=(self.wgt_strip.wg_width + 2 * self.d + self.end_slot_width), direction=np.pi, **self.wg_spec) # Cladding for waveguide taper path_clad = gdspy.Path( 2 * self.wgt_strip.clad_width + self.wgt_strip.wg_width, (0, 0)) path_clad.segment(self.length, final_width=2 * self.wgt_slot.clad_width + self.wgt_slot.wg_width, direction=0, **self.clad_spec) if not self.input_strip: center_pt = (self.length / 2.0, 0) path_strip.rotate(np.pi, center_pt) path_slot.rotate(np.pi, center_pt) path_clad.rotate(np.pi, center_pt) self.add(path_strip) self.add(path_slot) self.add(path_clad)
def start(self, start = [0, 0], direction = None): ### Start a CPW path specified by start coordinates and a direction ### direction: {+x, -x, +y, -y} or angle (in radians) if direction is not None: # Get direction from CPW class self.initalDirection = direction # Define the distance d = self.width + self.gap self.path = gdspy.Path(self.gap,(start[0],start[1]),number_of_paths = 2, distance=d)