def translate_from_center(self, offset): from math import pi, cos, sin, acos, sqrt from .utils import angle_vector pts = [pt for pt in self.get_dpoints()] tpts = [pt for pt in self.get_dpoints()] for i in range(0, len(pts)): if i == 0: u = pts[i] - pts[i + 1] v = -u elif i == (len(pts) - 1): u = pts[i - 1] - pts[i] v = -u else: u = pts[i - 1] - pts[i] v = pts[i + 1] - pts[i] if offset < 0: o1 = pya.DPoint(abs(offset) * cos(angle_vector(u) * pi / 180 - pi / 2), abs(offset) * sin(angle_vector(u) * pi / 180 - pi / 2)) o2 = pya.DPoint(abs(offset) * cos(angle_vector(v) * pi / 180 + pi / 2), abs(offset) * sin(angle_vector(v) * pi / 180 + pi / 2)) else: o1 = pya.DPoint(abs(offset) * cos(angle_vector(u) * pi / 180 + pi / 2), abs(offset) * sin(angle_vector(u) * pi / 180 + pi / 2)) o2 = pya.DPoint(abs(offset) * cos(angle_vector(v) * pi / 180 - pi / 2), abs(offset) * sin(angle_vector(v) * pi / 180 - pi / 2)) p1 = u + o1 p2 = o1 p3 = v + o2 p4 = o2 d = (p1.x - p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x - p4.x) if round(d, 10) == 0: tpts[i] += p2 else: tpts[i] += pya.DPoint(((p1.x * p2.y - p1.y * p2.x) * (p3.x - p4.x) - (p1.x - p2.x) * (p3.x * p4.y - p3.y * p4.x)) / d, ((p1.x * p2.y - p1.y * p2.x) * (p3.y - p4.y) - (p1.y - p2.y) * (p3.x * p4.y - p3.y * p4.x)) / d) if self.__class__ == pya.Path: return pya.Path([pya.Point(pt.x, pt.y) for pt in tpts], self.width) elif self.__class__ == pya.DPath: return pya.DPath(tpts, self.width)
def remove_colinear_points(self, verbose=False): """ remove all but 1 colinear point """ from SiEPIC.utils import pt_intersects_segment, angle_b_vectors, angle_vector if self.__class__ == pya.Path: pts = self.get_points() else: pts = self.get_dpoints() for i in range(1,len(pts)-1): turn = ((angle_b_vectors(pts[i]-pts[i-1],pts[i+1]-pts[i])+90)%360-90)/90 angle = angle_vector(pts[i]-pts[i-1])/90 if verbose: print('%s, %s' %(turn, angle)) # this version removed all colinear points, which doesn't make sense for a path self.points = [pts[0]] + [pts[i] for i in range(1, len(pts) - 1) if not pt_intersects_segment(pts[i + 1], pts[i - 1], pts[i])] + [pts[-1]] return self
def produce_impl(self): from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal from math import cos, sin, pi, sqrt import pya from SiEPIC.extend import to_itype print("GSiP.Wireguide") TECHNOLOGY = get_technology_by_name( 'GSiP') if op_tag == "GUI" else Tech.load_from_xml( lyp_filepath).layers dbu = self.layout.dbu wg_width = to_itype(self.width, dbu) path = self.path.to_itype(dbu) if not (len(self.layers) == len(self.widths) and len(self.layers) == len(self.offsets) and len(self.offsets) == len(self.widths)): raise Exception( "There must be an equal number of layers, widths and offsets") path.unique_points() turn = 0 for lr in range(0, len(self.layers)): layer = self.layout.layer(TECHNOLOGY[self.layers[lr]]) width = to_itype(self.widths[lr], dbu) offset = to_itype(self.offsets[lr], dbu) pts = path.get_points() wg_pts = [pts[0]] for i in range(1, len(pts) - 1): turn = ((angle_b_vectors(pts[i] - pts[i - 1], pts[i + 1] - pts[i]) + 90) % 360 - 90) / 90 dis1 = pts[i].distance(pts[i - 1]) dis2 = pts[i].distance(pts[i + 1]) angle = angle_vector(pts[i] - pts[i - 1]) / 90 pt_radius = self.radius # determine the radius, based on how much space is available if len(pts) == 3: pt_radius = min(dis1, dis2, pt_radius) else: if i == 1: if dis1 <= pt_radius: pt_radius = dis1 elif dis1 < 2 * pt_radius: pt_radius = dis1 / 2 if i == len(pts) - 2: if dis2 <= pt_radius: pt_radius = dis2 elif dis2 < 2 * pt_radius: pt_radius = dis2 / 2 # wireguide bends: if (self.adiab): wg_pts += Path( arc_bezier( pt_radius, 270, 270 + inner_angle_b_vectors( pts[i - 1] - pts[i], pts[i + 1] - pts[i]), self.bezier, DevRec='DevRec' in self.layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points() else: wg_pts += Path( arc_xy(-pt_radius, pt_radius, pt_radius, 270, 270 + inner_angle_b_vectors( pts[i - 1] - pts[i], pts[i + 1] - pts[i]), DevRec='DevRec' in self.layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points() wg_pts += [pts[-1]] wg_pts = pya.Path(wg_pts, 0).unique_points().get_points() wg_polygon = Path(wg_pts, wg_width) self.cell.shapes(layer).insert(wg_polygon) # insert the wireguide #if self.layout.layer(TECHNOLOGY['Wireguide']) == layer: waveguide_length = wg_polygon.area() / self.width * dbu**2 pts = path.get_points() LayerPinRecN = self.layout.layer(TECHNOLOGY['PinRecM']) # insert pins to wireguide t1 = Trans(angle_vector(pts[0] - pts[1]) / 90, False, pts[0]) self.cell.shapes(LayerPinRecN).insert( Path([Point(-50, 0), Point(50, 0)], wg_width).transformed(t1)) self.cell.shapes(LayerPinRecN).insert(Text("pin1", t1, 0.3 / dbu, -1)) t = Trans(angle_vector(pts[-1] - pts[-2]) / 90, False, pts[-1]) self.cell.shapes(LayerPinRecN).insert( Path([Point(-50, 0), Point(50, 0)], wg_width).transformed(t)) self.cell.shapes(LayerPinRecN).insert(Text("pin2", t, 0.3 / dbu, -1)) LayerDevRecN = self.layout.layer(TECHNOLOGY['DevRec']) # Compact model information angle_vec = angle_vector(pts[0] - pts[1]) / 90 halign = 0 # left angle = 0 pt2 = pts[0] pt3 = pts[0] if angle_vec == 0: # horizontal halign = 2 # right angle = 0 pt2 = pts[0] + Point(0, wg_width) pt3 = pts[0] + Point(0, -wg_width) if angle_vec == 2: # horizontal halign = 0 # left angle = 0 pt2 = pts[0] + Point(0, wg_width) pt3 = pts[0] + Point(0, -wg_width) if angle_vec == 1: # vertical halign = 2 # right angle = 1 pt2 = pts[0] + Point(wg_width, 0) pt3 = pts[0] + Point(-wg_width, 0) if angle_vec == -1: # vertical halign = 0 # left angle = 1 pt2 = pts[0] + Point(wg_width, 0) pt3 = pts[0] + Point(-wg_width, 0)
def produce_impl(self): from SiEPIC.utils.layout import layout_waveguide2 from SiEPIC.utils import angle_vector from math import cos, sin, pi, sqrt import pya from SiEPIC.extend import to_itype # print("GSiP.Waveguide") from SiEPIC.utils import get_technology_by_name TECHNOLOGY = get_technology_by_name('GSiP') dbu = self.layout.dbu wg_width = to_itype(self.width, dbu) path = self.path.to_itype(dbu) if not (len(self.layers) == len(self.widths) and len(self.layers) == len(self.offsets) and len(self.offsets) == len(self.widths)): raise Exception( "There must be an equal number of layers, widths and offsets") path.unique_points() pts = path.get_points() # Draw the waveguide geometry, new in SiEPIC-Tools v0.3.64 waveguide_length = layout_waveguide2(TECHNOLOGY, self.layout, self.cell, self.layers, self.widths, self.offsets, pts, self.radius, self.adiab, self.bezier) pts = path.get_points() LayerPinRecN = self.layout.layer(TECHNOLOGY['PinRec']) t1 = Trans(angle_vector(pts[0] - pts[1]) / 90, False, pts[0]) self.cell.shapes(LayerPinRecN).insert( Path([Point(-50, 0), Point(50, 0)], wg_width).transformed(t1)) self.cell.shapes(LayerPinRecN).insert(Text("pin1", t1, 0.3 / dbu, -1)) t = Trans(angle_vector(pts[-1] - pts[-2]) / 90, False, pts[-1]) self.cell.shapes(LayerPinRecN).insert( Path([Point(-50, 0), Point(50, 0)], wg_width).transformed(t)) self.cell.shapes(LayerPinRecN).insert(Text("pin2", t, 0.3 / dbu, -1)) LayerDevRecN = self.layout.layer(TECHNOLOGY['DevRec']) # Compact model information angle_vec = angle_vector(pts[0] - pts[1]) / 90 halign = 0 # left angle = 0 if angle_vec == 0: # horizontal halign = 2 # right angle = 0 dpt = Point(0, 0.2 * wg_width) if angle_vec == 2: # horizontal halign = 0 # left angle = 0 dpt = Point(0, 0.2 * wg_width) if angle_vec == 1: # vertical halign = 2 # right angle = 1 dpt = Point(0.2 * wg_width, 0) if angle_vec == -1: # vertical halign = 0 # left angle = 1 dpt = Point(0.2 * wg_width, 0) pt2 = pts[0] + dpt pt3 = pts[0] - dpt pt4 = pts[0] - 2 * dpt pt5 = pts[0] + 2 * dpt t = Trans(angle, False, pt5) text = Text('cellName=%s' % self.cellName, t, 0.1 * wg_width, -1) text.halign = halign shape = self.cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt3) text = Text('Lumerical_INTERCONNECT_library=Design kits/%s' % self.CML, t, 0.1 * wg_width, -1) text.halign = halign shape = self.cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt2) text = Text('Component=%s' % self.model, t, 0.1 * wg_width, -1) text.halign = halign shape = self.cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pts[0]) pts_txt = str( [[round(p.to_dtype(dbu).x, 3), round(p.to_dtype(dbu).y, 3)] for p in pts]).replace(', ', ',') text = Text ( \ 'Spice_param:wg_length=%.3fu wg_width=%.3fu points="%s" radius=%s' %\ (waveguide_length, self.width, pts_txt,self.radius ), t, 0.1*wg_width, -1 ) text.halign = halign shape = self.cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt4) text = Text ( \ 'Length=%.3fu' %(waveguide_length), t, 0.5*wg_width, -1 ) text.halign = halign shape = self.cell.shapes(LayerDevRecN).insert(text)
def layout_waveguide2(TECHNOLOGY, layout, cell, layers, widths, offsets, pts, radius, adiab, bezier): ''' Create a waveguide, in a specific technology inputs - TECHNOLOGY, layout, cell: from SiEPIC.utils import get_layout_variables TECHNOLOGY, lv, layout, cell = get_layout_variables() - layers: list of text names, e.g., ['Waveguide'] - widths: list of floats in units Microns, e.g., [0.50] - offsets: list of floats in units Microns, e.g., [0] - pts: a list of pya.Points, e.g. L=15/dbu pts = [Point(0,0), Point(L,0), Point(L,L)] - radius: in Microns, e.g., 5 - adiab: 1 = Bezier curve, 0 = radial bend (arc) - bezier: the bezier parameter, between 0 and 0.45 (almost a radial bend) Note: bezier parameters need to be simulated and optimized, and will depend on wavelength, polarization, width, etc. TM and rib waveguides don't benefit from bezier curves most useful for TE ''' from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal from SiEPIC.extend import to_itype from pya import Path, Polygon, Trans dbu = layout.dbu width=widths[0] turn=0 waveguide_length = 0 for lr in range(0, len(layers)): wg_pts = [pts[0]] layer = layout.layer(TECHNOLOGY[layers[lr]]) width = to_itype(widths[lr],dbu) offset = to_itype(offsets[lr],dbu) for i in range(1,len(pts)-1): turn = ((angle_b_vectors(pts[i]-pts[i-1],pts[i+1]-pts[i])+90)%360-90)/90 dis1 = pts[i].distance(pts[i-1]) dis2 = pts[i].distance(pts[i+1]) angle = angle_vector(pts[i]-pts[i-1])/90 pt_radius = to_itype(radius,dbu) # determine the radius, based on how much space is available if len(pts)==3: pt_radius = min (dis1, dis2, pt_radius) else: if i==1: if dis1 <= pt_radius: pt_radius = dis1 elif dis1 < 2*pt_radius: pt_radius = dis1/2 if i==len(pts)-2: if dis2 <= pt_radius: pt_radius = dis2 elif dis2 < 2*pt_radius: pt_radius = dis2/2 # waveguide bends: if abs(turn)==1: if(adiab): wg_pts += Path(arc_bezier(pt_radius, 270, 270 + inner_angle_b_vectors(pts[i-1]-pts[i], pts[i+1]-pts[i]), bezier, DevRec='DevRec' in layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points() else: wg_pts += Path(arc_xy(-pt_radius, pt_radius, pt_radius, 270, 270 + inner_angle_b_vectors(pts[i-1]-pts[i], pts[i+1]-pts[i]),DevRec='DevRec' in layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points() wg_pts += [pts[-1]] wg_pts = pya.Path(wg_pts, 0).unique_points().get_points() wg_polygon = Polygon(translate_from_normal(wg_pts, width/2 + (offset if turn > 0 else - offset))+translate_from_normal(wg_pts, -width/2 + (offset if turn > 0 else - offset))[::-1]) cell.shapes(layer).insert(wg_polygon) if layout.layer(TECHNOLOGY['Waveguide']) == layer: waveguide_length = wg_polygon.area() / width * dbu return waveguide_length
def layout_waveguide2(TECHNOLOGY, layout, cell, layers, widths, offsets, pts, radius, adiab, bezier): from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal from SiEPIC.extend import to_itype from pya import Path, Polygon, Trans dbu = layout.dbu width = widths[0] turn = 0 waveguide_length = 0 for lr in range(0, len(layers)): wg_pts = [pts[0]] layer = layout.layer(TECHNOLOGY[layers[lr]]) width = to_itype(widths[lr], dbu) offset = to_itype(offsets[lr], dbu) for i in range(1, len(pts) - 1): turn = ( (angle_b_vectors(pts[i] - pts[i - 1], pts[i + 1] - pts[i]) + 90) % 360 - 90) / 90 dis1 = pts[i].distance(pts[i - 1]) dis2 = pts[i].distance(pts[i + 1]) angle = angle_vector(pts[i] - pts[i - 1]) / 90 pt_radius = to_itype(radius, dbu) # determine the radius, based on how much space is available if len(pts) == 3: pt_radius = min(dis1, dis2, pt_radius) else: if i == 1: if dis1 <= pt_radius: pt_radius = dis1 elif dis1 < 2 * pt_radius: pt_radius = dis1 / 2 if i == len(pts) - 2: if dis2 <= pt_radius: pt_radius = dis2 elif dis2 < 2 * pt_radius: pt_radius = dis2 / 2 # waveguide bends: if abs(turn) == 1: if (adiab): wg_pts += Path( arc_bezier( pt_radius, 270, 270 + inner_angle_b_vectors( pts[i - 1] - pts[i], pts[i + 1] - pts[i]), float(bezier), DevRec='DevRec' in layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points() else: wg_pts += Path( arc_xy(-pt_radius, pt_radius, pt_radius, 270, 270 + inner_angle_b_vectors( pts[i - 1] - pts[i], pts[i + 1] - pts[i]), DevRec='DevRec' in layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points() wg_pts += [pts[-1]] wg_pts = pya.Path(wg_pts, 0).unique_points().get_points() wg_polygon = Polygon( translate_from_normal( wg_pts, width / 2 + (offset if turn > 0 else -offset)) + translate_from_normal( wg_pts, -width / 2 + (offset if turn > 0 else -offset))[::-1]) cell.shapes(layer).insert(wg_polygon) if layout.layer(TECHNOLOGY['Waveguide']) == layer: waveguide_length = wg_polygon.area() / width * dbu return waveguide_length
def translate_from_normal2(pts, trans, trans2=None): ''' Translate each point in the array pts, by its local normal by a distance that varies linearly starting at 'trans' and ending 'trans2' Useful for making an S-bend with different waveguide widths at the ends Author: Lukas Chrostowski Inputs: pts: DPoint array, length at least 3 trans: float trans2: float Output: tpts: DPoint array Example, SBend Waveguide with variable width: from SiEPIC.utils.geometry import bezier_parallel w1 = 0.15 # input waveguide width wo = 0.35 # output waveguide width l = 5 # horizontal length offset = 2# vertical offset p = bezier_parallel(DPoint(0,0), DPoint(l,offset), 0) pt1 = translate_from_normal2(p,w1/2,wo/2) pt2 = translate_from_normal2(p,-w1/2, -wo/2) pt = pt1+pt2[::-1] from SiEPIC.utils import get_layout_variables TECHNOLOGY, lv, ly, cell = get_layout_variables() layer = cell.layout().layer(TECHNOLOGY['Waveguide']) poly = pya.DPolygon(pt) cell.shapes(layer).insert(poly) ''' if trans2 == None: trans2 = trans if len(pts) < 2: return pts length = 0 # total length for i in range(1, len(pts) - 1): length += (pts[i + 1] - pts[i - 1]).length() transv = [] # translation vector, linearly varying along the length lengthc = 0 # cumulative length for i in range(1, len(pts) - 1): lengthc += (pts[i + 1] - pts[i - 1]).length() transv.append((lengthc / length) * trans2 + (1 - lengthc / length) * trans) from math import cos, sin, pi from SiEPIC.utils import angle_vector d = 1. / (len(pts) - 1) a = angle_vector(pts[1] - pts[0]) * pi / 180 + (pi / 2 if trans > 0 else -pi / 2) tpts = [pts[0] + pya.DPoint(abs(trans) * cos(a), abs(trans) * sin(a))] for i in range(1, len(pts) - 1): dpt = (pts[i + 1] - pts[i - 1]) * (2 / d) tpts.append(pts[i] + pya.DPoint(-dpt.y, dpt.x) * (transv[i - 1] / 1 / dpt.abs())) a = angle_vector(pts[-1] - pts[-2]) * pi / 180 + (pi / 2 if trans > 0 else -pi / 2) tpts.append(pts[-1] + pya.DPoint(abs(trans2) * cos(a), abs(trans2) * sin(a))) # Make ends manhattan if abs(tpts[0].x - pts[0].x) > abs(tpts[0].y - pts[0].y): tpts[0].y = pts[0].y else: tpts[0].x = pts[0].x if abs(tpts[-1].x - pts[-1].x) > abs(tpts[-1].y - pts[-1].y): tpts[-1].y = pts[-1].y else: tpts[-1].x = pts[-1].x return tpts
def layout_waveguide2(TECHNOLOGY, layout, cell, layers, widths, offsets, pts, radius, adiab, bezier): from SiEPIC.utils import arc_xy, arc_bezier, angle_vector, angle_b_vectors, inner_angle_b_vectors, translate_from_normal from SiEPIC.extend import to_itype from pya import Path, Polygon, Trans dbu = layout.dbu if 'Errors' in TECHNOLOGY: error_layer = layout.layer(TECHNOLOGY['Errors']) else: error_layer = None width = widths[0] turn = 0 waveguide_length = 0 for lr in range(0, len(layers)): wg_pts = [pts[0]] layer = layout.layer(TECHNOLOGY[layers[lr]]) width = to_itype(widths[lr], dbu) offset = to_itype(offsets[lr], dbu) for i in range(1, len(pts) - 1): turn = ( (angle_b_vectors(pts[i] - pts[i - 1], pts[i + 1] - pts[i]) + 90) % 360 - 90) / 90 dis1 = pts[i].distance(pts[i - 1]) dis2 = pts[i].distance(pts[i + 1]) angle = angle_vector(pts[i] - pts[i - 1]) / 90 pt_radius = to_itype(radius, dbu) error_seg1 = False error_seg2 = False # determine the radius, based on how much space is available if len(pts) == 3: # simple corner, limit radius by the two edges if dis1 < pt_radius: error_seg1 = True if dis2 < pt_radius: error_seg2 = True pt_radius = min(dis1, dis2, pt_radius) else: if i == 1: # first corner, limit radius by first edge, or 1/2 of second one if dis1 < pt_radius: error_seg1 = True if dis2 / 2 < pt_radius: error_seg2 = True pt_radius = min(dis1, dis2 / 2, pt_radius) elif i == len(pts) - 2: # last corner, limit radius by second edge, or 1/2 of first one if dis1 / 2 < pt_radius: error_seg1 = True if dis2 < pt_radius: error_seg2 = True pt_radius = min(dis1 / 2, dis2, pt_radius) else: if dis1 / 2 < pt_radius: error_seg1 = True if dis2 / 2 < pt_radius: error_seg2 = True pt_radius = min(dis1 / 2, dis2 / 2, pt_radius) if error_seg1 or error_seg2: if not error_layer: # we have an error, but no Error layer print('- SiEPIC:layout_waveguide2: missing Error layer') # and pt_radius < to_itype(radius,dbu): elif layer == layout.layer(TECHNOLOGY['Waveguide']): # add an error polygon to flag the incorrect bend if error_seg1: error_pts = pya.Path([pts[i - 1], pts[i]], width) cell.shapes(error_layer).insert(error_pts) if error_seg2: error_pts = pya.Path([pts[i], pts[i + 1]], width) cell.shapes(error_layer).insert(error_pts) # error_pts = pya.Path([pts[i-1], pts[i], pts[i+1]], width) # cell.shapes(error_layer).insert(error_pts) # waveguide bends: if abs(turn) == 1: if (adiab): wg_pts += Path( arc_bezier( pt_radius, 270, 270 + inner_angle_b_vectors( pts[i - 1] - pts[i], pts[i + 1] - pts[i]), float(bezier), DevRec='DevRec' in layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points() else: wg_pts += Path( arc_xy(-pt_radius, pt_radius, pt_radius, 270, 270 + inner_angle_b_vectors( pts[i - 1] - pts[i], pts[i + 1] - pts[i]), DevRec='DevRec' in layers[lr]), 0).transformed(Trans(angle, turn < 0, pts[i])).get_points() wg_pts += [pts[-1]] wg_pts = pya.Path(wg_pts, 0).unique_points().get_points() wg_polygon = Polygon( translate_from_normal( wg_pts, width / 2 + (offset if turn > 0 else -offset)) + translate_from_normal( wg_pts, -width / 2 + (offset if turn > 0 else -offset))[::-1]) cell.shapes(layer).insert(wg_polygon) if layout.layer(TECHNOLOGY['Waveguide']) == layer: waveguide_length = wg_polygon.area() / width * dbu return waveguide_length
def layout_waveguide3(cell, pts, params, debug=True): if debug: print('SiEPIC.utils.layout.layout_waveguide3: ') layout = cell.layout() dbu = layout.dbu technology_name = layout.technology_name from SiEPIC.utils import get_technology_by_name TECHNOLOGY = get_technology_by_name(technology_name) from SiEPIC.extend import to_itype wg_width = to_itype(params['width'], dbu) radius = float(params['radius']) model = params['model'] cellName = 'Waveguide2' CML = params['CML'] if debug: print(' - waveguide params: %s' % (params)) if 'compound_waveguide' in params: print('error: this function cannot handle compound waveguides') raise Exception( 'error: this function cannot handle compound waveguides (%s)' % waveguide_type) # draw the waveguide waveguide_length = layout_waveguide2( TECHNOLOGY, layout, cell, [wg['layer'] for wg in params['component']], [wg['width'] for wg in params['component']], [wg['offset'] for wg in params['component']], pts, radius, params['adiabatic'], params['bezier']) # Draw the marking layers from SiEPIC.utils import angle_vector LayerPinRecN = layout.layer(TECHNOLOGY['PinRec']) make_pin(cell, 'opt1', pts[0], wg_width, LayerPinRecN, angle_vector(pts[0] - pts[1]) % 360) make_pin(cell, 'opt2', pts[-1], wg_width, LayerPinRecN, angle_vector(pts[-1] - pts[-2]) % 360) from pya import Trans, Text, Path, Point ''' t1 = Trans(angle_vector(pts[0]-pts[1])/90, False, pts[0]) cell.shapes(LayerPinRecN).insert(Path([Point(-10, 0), Point(10, 0)], wg_width).transformed(t1)) cell.shapes(LayerPinRecN).insert(Text("opt1", t1, 0.3/dbu, -1)) t = Trans(angle_vector(pts[-1]-pts[-2])/90, False, pts[-1]) cell.shapes(LayerPinRecN).insert(Path([Point(-10, 0), Point(10, 0)], wg_width).transformed(t)) cell.shapes(LayerPinRecN).insert(Text("opt2", t, 0.3/dbu, -1)) ''' LayerDevRecN = layout.layer(TECHNOLOGY['DevRec']) # Compact model information angle_vec = angle_vector(pts[0] - pts[1]) / 90 halign = 0 # left angle = 0 dpt = Point(0, 0) if angle_vec == 0: # horizontal halign = 2 # right angle = 0 dpt = Point(0, 0.2 * wg_width) if angle_vec == 2: # horizontal halign = 0 # left angle = 0 dpt = Point(0, 0.2 * wg_width) if angle_vec == 1: # vertical halign = 2 # right angle = 1 dpt = Point(0.2 * wg_width, 0) if angle_vec == -1: # vertical halign = 0 # left angle = 1 dpt = Point(0.2 * wg_width, 0) pt2 = pts[0] + dpt pt3 = pts[0] - dpt pt4 = pts[0] - 6 * dpt pt5 = pts[0] + 2 * dpt t = Trans(angle, False, pt3) text = Text('Lumerical_INTERCONNECT_library=Design kits/%s' % CML, t, 0.1 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt2) text = Text('Component=%s' % model, t, 0.1 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt5) text = Text('cellName=%s' % cellName, t, 0.1 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pts[0]) pts_txt = str([[round(p.to_dtype(dbu).x, 3), round(p.to_dtype(dbu).y, 3)] for p in pts]).replace(', ', ',') text = Text( 'Spice_param:wg_length=%.9f wg_width=%.3g points="%s" radius=%.3g' % (waveguide_length * 1e-6, wg_width * 1e-9, pts_txt, radius * 1e-6), t, 0.1 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) t = Trans(angle, False, pt4) text = Text('Length=%.3f (microns)' % (waveguide_length), t, 0.5 * wg_width, -1) text.halign = halign shape = cell.shapes(LayerDevRecN).insert(text) return waveguide_length