def addTestLines(lib, width=5, length=300, name="LINES5", offset=[0, 0], alignment='top', layer=0, textSize=50): spacing = width tempCell = lib.new_cell(name) if alignment == 'top': texti = gdspy.Text(str(width) + 'u', textSize, [offset[0], offset[1] - textSize], layer=layer) tempCell.add(texti) for i in range(5): linei = gdspy.Rectangle( [offset[0] + i * width + i * spacing, offset[1] - textSize], [ offset[0] + (i + 1) * width + i * spacing, offset[1] - textSize - length ], layer=layer) tempCell.add(linei) tempCell.add(texti) return tempCell else: raise NotImplementedError
def addCapacitorStructures(lib, width=[50, 100, 200, 400, 800], spacing=100, name="CAPS", offset=[0, 0], alignment='top', textSize=50, layer=2): tempCell = lib.new_cell(name) if alignment == 'top': for i in range(len(width)): texti = gdspy.Text(str(width[i]) + 'u', textSize, [ offset[0] + i * spacing + sum(width[0:i]), offset[1] - textSize ], layer=layer) capi = gdspy.Rectangle([ offset[0] + i * spacing + sum(width[0:i]), offset[1] - textSize ], [ offset[0] + i * spacing + sum(width[0:i + 1]), offset[1] - textSize - width[i] ], layer=layer) tempCell.add(texti) tempCell.add(capi) return tempCell else: raise NotImplementedError
def text_rect(bounding_box, box_length, box_width, txt_label, txt_height, layer, rect_shift, extra_text=None): """creates a bounding rectangle with text subtracted from it. returns a cell. """ # get the bounding box # add a 1um offset from the rest of the pattern offset = box_length / 2 + 1 xshift, yshift = rect_shift print(xshift) test1 = offset + xshift # add the text vtext = gdspy.Text(txt_label, txt_height, (offset + xshift, box_width / 2 + yshift), horizontal=False, **layer) # first subtract the interior rectangle from the exterior rectangle sub = gdspy.boolean(bounding_box, vtext, 'not') return sub
def addTLMStructures(lib, width=100, spacing=[50, 100, 150, 200], padding=5, name="TLM", offset=[0, 0], alignment='top', textSize=50): tempCell = lib.new_cell(name) if alignment == 'top': for i in range(len(spacing) + 1): if (i < len(spacing)): texti = gdspy.Text( str(spacing[i]) + 'u', textSize, [ offset[0] + i * width + sum(spacing[0:i]) + width / 2 + spacing[i] / 2, offset[1] - textSize ], layer=2) tempCell.add(texti) contacti = gdspy.Rectangle([ offset[0] + padding + i * width + sum(spacing[0:i]), offset[1] - padding - textSize ], [ offset[0] + padding + (i + 1) * width + sum(spacing[0:i]), offset[1] - textSize - padding - width ], layer=2) tempCell.add(contacti) filmRegion = gdspy.Rectangle([offset[0], offset[1] - textSize], [ offset[0] + 2 * padding + 5 * width + sum(spacing), offset[1] - textSize - 2 * padding - width ], layer=1) widthText = gdspy.Text( str(width) + 'u', textSize, [offset[0] - textSize * 4, offset[1] - textSize - width / 2], layer=2) tempCell.add(filmRegion) tempCell.add(widthText) return tempCell else: raise NotImplementedError
def make_x_label(name, struct_list, x=0, y=50, text_size=5, layer=0): # type checks if type(name) != str: print("ERROR: first argument must be a string\n") return struct_list label = gp.Text(name, text_size, (x, y), layer=layer) struct_list.append(label) return struct_list
def makeGrid(conf: DefaultConfig, parts): dX, dY = getSize(parts) / 2 dx, dy = conf.gridSize layer = conf.gridLayer numX, numY = int(np.ceil(dX / dx)), int(np.ceil(dY / dy)) rectangles = [] for i in range(-numX, numX + 1): for j in range(-numY, numY + 1): rectangles.append(myRectangle([dx, dy], layer, [i * dx, j * dy])) texts = [ gdspy.Text('Extent %s' % str([dX, dY]), dy, [-numX * dx, numY * dy + dy * 2], layer=layer), gdspy.Text('Field Size %s' % str([dx, dy]), dy, [-numX * dx, numY * dy + dy], layer=layer), ] return rectangles + texts
def markerL(conf: DefaultConfig, text='', rotation=0): dx, w, ts = conf.markerLSize[0], conf.markerLWidth, conf.markerLTextSize markerL = gdspy.FlexPath([(0, -dx), (0, 0), (dx, 0)], w, layer=conf.markerLayer).to_polygonset() text = gdspy.Text(text, ts, [w, w], layer=conf.markerLayer).rotate(-pi / 2) if rotation == -pi / 2: text.translate(-dx, 0) return [markerL.rotate(rotation), text]
def text(self, pos, size, text, angle, horizontal, **kwargs): pos, size = parse_entry(pos, size) name = kwargs["name"] layer = kwargs["layer"] poly1 = gdspy.Text(text, size, pos, horizontal=horizontal, angle=angle, layer=layer) self.gds_object_instances[name] = poly1 self.cell.add(poly1)
def numerate(self, name, number, coordinate): size = 70 layer = 51 vtext = gdspy.Text(name + str(number), size, coordinate, horizontal=True, layer=layer) # label = gdspy.Label(name + str(number), coordinate, texttype=25) self.label_cell.add(vtext)
def generateBarcodeText(cls, barcodeString="test", barcodeLayer=4): barcodeString = barcodeString.upper() cls.validateString(barcodeString) textCell = gdspy.Cell('BARCODE_TEXT') textHeight = 3*cls.mm labelText = gdspy.Text(barcodeString, textHeight, (0,0),layer=barcodeLayer) labelSize = labelText.get_bounding_box() x1 = labelSize[1,0] y1 = labelSize[1,1] labelText.translate(-x1/2,-y1/2) # Center the text textCell.add(labelText) return textCell
def make_y_label(name, struct_list, x=-50, y=0, text_size=5, layer=0, align_right=True): # type checks if type(name) != str: print("ERROR: first argument must be a string\n") return struct_list label = gp.Text(name, text_size, (x, y), layer=layer) box = label.get_bounding_box() if align_right == True: x_shift = box[0][0] - box[1][0] label.translate(x_shift, 0) struct_list.append(label) return struct_list
def make_title(name, cell, x=0, y=100, text_size=10, layer=0): """ :param name: str :param cell: gp.Cell :param x: float :param y: float :param text_size: float :param layer: float :return: gp.Cell """ # type checks if type(name) != str: print("ERROR: first argument must be a string\n") return cell if type(cell) != gp.Cell: print("ERROR: second argument must be a gdspy Cell\n") return cell title = gp.Text(name, text_size, (x, y), layer=layer) cell.add(title) return cell
# Cells can contain references to other cells. ref_cell = gdspy.Cell('REFS') ref_cell.add(gdspy.CellReference(poly_cell, (0, 30), x_reflection=True)) ref_cell.add(gdspy.CellReference(poly_cell, (25, 0), rotation=180)) # References can be whole arrays. Add an array of the operations cell # with 2 lines and 3 columns and 1st element at (25, 10). ref_cell.add( gdspy.CellArray('OPERATIONS', 3, 2, (35, 30), (25, 10), magnification=1.5)) # Text are also sets of polygons. They have edges parallel to 'x' and # 'y' only. ref_cell.add( gdspy.Text('Created with gsdpy ' + gdspy.__version__, 7, (-7, -35), layer=6)) # Labels are special text objects which don't define any actual # geometry, but can be used to annotate the drawing. Rotation, # magnification and reflection of the text are not supported by the # included GUI, but they are included in the resulting GDSII file. ref_cell.add( gdspy.Label('Created with gdspy ' + gdspy.__version__, (-7, -36), 'nw', layer=6)) # ------------------------------------------------------------------ # # Translation # ------------------------------------------------------------------ #
devices = lib.new_cell("Devices") x_position = 0 for w_wg in temp_w_wg: # Geometry must be placed in cells. devices.add( gdspy.CellReference(Cell_all['Compensation' + str(int(w_wg * 1000))], origin=(x_position, 1))) x_position = x_position + 1500 row = '1234' column = 'ABC' x0 = -550 y0 = 50 # (x_steo, y_step) is the next Text's postion, eg 'A2' x_step = 1500 y_step = -1000 for i in range(len(row)): for j in range(len(column)): text = column[j] + row[i] com = lib.new_cell(text) com.add( gdspy.Text(text, 40, (x0 + j * x_step, y0 + i * y_step), **ld_fulletch)) ref = gdspy.CellReference(com) devices.add(ref) # Save the library in a file called 'first.gds'. lib.write_gds('Compensation_10-30nm_SiO2.gds') gdspy.LayoutViewer()
lp.smooth([(5, 10)], angles=[0.5 * numpy.pi, 0], width=0.5, offset=[-0.25, 0.25, -0.75, 0.75]) lp.parametric(lambda u: numpy.array( (45 * u, 4 * numpy.sin(6 * numpy.pi * 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(gdspy.Cell('robust_paths').add(lp)) # Boolean Operations # Create some text text = gdspy.Text('GDSPY', 4, (0, 0)) # Create a rectangle extending the text's bounding box by 1 bb = numpy.array(text.get_bounding_box()) rect = gdspy.Rectangle(bb[0] - 1, bb[1] + 1) # Subtract the text from the rectangle inv = gdspy.boolean(rect, text, 'not') draw(gdspy.Cell('boolean_operations').add(inv)) # Slice Operation ring1 = gdspy.Round((-6, 0), 6, inner_radius=4) ring2 = gdspy.Round((0, 0), 6, inner_radius=4) ring3 = gdspy.Round((6, 0), 6, inner_radius=4) # Slice the first ring across x=-3, the second ring across x=-3 # and x=3, and the third ring across x=3
def router(cell, fr_str, fr_ep, to_str, to_ep, width, bmul, grid_s=1, xr=False, yr=False, uniform_width=False, precision=0.001, pref='y', switch_pref=False, layer=0, debug=False, nop=21, dist_multi=2, pathmethod='poly', detect='native'): fr = fr_str.endpoints[fr_ep] to = to_str.endpoints[to_ep] border_s = bmul * grid_s box = [fr, to] # Make sure first box coord is always the top-left corner and add additional border points xs = [box[0][0], box[1][0]] ys = [box[0][1], box[1][1]] box = [[min(xs) - border_s, max(ys) + border_s], [max(xs) + border_s, min(ys) - border_s]] # Build list of gridpoints that are outside all structures in cell lxr = int((box[1][0] - box[0][0]) / grid_s) + 1 lyr = int((box[0][1] - box[1][1]) / grid_s) + 1 if type(xr) not in [list, np.ndarray]: xr = np.linspace(box[0][0], box[1][0], lxr) else: lxr = len(xr) if type(yr) not in [list, np.ndarray]: yr = np.linspace(box[0][1], box[1][1], lyr) else: lyr = len(yr) p = [] p_d_to = [] p_d_fr = [] for y in yr: for x in xr: c = (x, y) p.append(c) # Compute squared Euclidean distance from to and fr coords for each gridpoint # For optimization we don't need to sqrt() since minimal in squared is minimal in sqrt dist_fr = (x - fr[0])**2 + (y - fr[1])**2 dist_to = (x - to[0])**2 + (y - to[1])**2 p_d_fr.append(dist_fr) p_d_to.append(dist_to) p_i = np.array(p) p_d_fr = np.array(p_d_fr) p_d_to = np.array(p_d_to) # Build list of points that are inside a structure cell_ref = gd.CellReference(cell) if detect == 'native': inside = np.array(gd.inside(p, cell_ref, precision=precision)) elif detect == 'custom': inside = np.array( gtools.funcs.inside(p, cell_ref, dist=dist_multi * grid_s, nop=nop, precision=precision)) else: raise ValueError( 'Parameter \'detect\' is only allowed to have values [\'native\', \'custom\'], cannot continue' ) p_d_fr_min = np.min(p_d_fr[np.argwhere(inside == False)]) p_d_to_min = np.min(p_d_to[np.argwhere(inside == False)]) # Get p_i index of starting values start_i = np.argwhere(p_d_fr == p_d_fr_min).tolist() end_i = np.argwhere(p_d_to == p_d_to_min).tolist() start_i = [item for sublist in start_i for item in sublist] end_i = [item for sublist in end_i for item in sublist] start = p_i[start_i] end = p_i[end_i] # Now start stepping from start to end, labelling all gridpoints accordingly by the number of steps required from starting point to reach it n = [0] * 4 lp = len(p) p_g = [0] * lp path_found = False k = 0 while not path_found and start_i: k += 1 next_start_i = [] if debug: print(start_i) for i in start_i: # Look up, down, left and right, store the index n = lookaround(i, lxr, pref=pref) # Check if any of the neighbouring points are not in a structure and not in p_g for nb in n: if nb in end_i: path_found = True p_g[nb] = k final_index = nb if debug: # Visualize circ = gd.Round(p[nb], 0.1, layer=10) cell.add(circ) txt = gd.Text(str(k), 0.5, p[nb], layer=11) cell.add(txt) break # Point is out of bounds, marked as structure (< 0) or already has a step value (> 0) if nb < 0 or nb >= lp or p_g[nb] != 0 or ( i % lxr == 0 and nb % lxr == 1) or (i % lxr == 1 and nb % lxr == 0): continue # Skip this iteration if inside[nb]: p_g[nb] = -1 else: p_g[nb] = k next_start_i.append(nb) if debug: # Visualize circ = gd.Round(p[nb], 0.1, layer=1) cell.add(circ) txt = gd.Text(str(k), 0.5, p[nb], layer=2) cell.add(txt) start_i = copy.copy(next_start_i) # Routing ended, checking whether we succeeded if not path_found: print('>> ERROR: No existing route was found.') return False print('>> Found a route in ' + str(k) + ' steps.') # Backtrace path this_index = final_index backtraced = [to, p[final_index]] switched = False for this_k in range(k, -1, -1): # Change move preference after switch_pref moves if switch_pref and not switched and this_k < switch_pref * k: pref = 'x' if pref == 'y' else 'y' switched = True n = lookaround(this_index, lxr, pref=pref) for nb in n: if nb < lp and p_g[nb] == this_k: this_index = nb backtraced.append(p[nb]) break backtraced.append(fr) if debug: print('>> Points of found route:') print(backtraced) # Generate list of widths for the route if not uniform_width: to_w = to_str.endpoint_dims[to_ep] fr_w = fr_str.endpoint_dims[fr_ep] ws = [to_w if to_w != None else width] * 2 + [width] * ( len(backtraced) - 4) + [fr_w if fr_w != None else width] * 2 else: ws = width # Create backtraced path if pathmethod == 'poly': r = gd.PolyPath(backtraced, ws, layer=layer) elif pathmethod == 'flex': r = gd.FlexPath(backtraced, ws, corners='smooth', layer=layer) else: raise ValueError( 'Parameter \'pathmethod\' only has allowed values [\'poly\', \'flex\']' ) ends = {'A': backtraced[0], 'B': backtraced[-1]} epsz = { 'A': ws[0] if not uniform_width else width, 'B': ws[-1] if not uniform_width else width } structure = gtools.classes.GDStructure(r, ends, epsz) # Connect to 'to' and 'from' structures fr_str.next['AUTOROUTE_A'] = structure to_str.next['AUTOROUTE_B'] = structure structure.prev['AUTOROUTE_A'] = fr_str structure.prev['AUTOROUTE_B'] = to_str return structure
def nanowire_binary(number, width, pitch, length, n, m, is_interrupt, device_shape, pals_length, itr, elec_width, pin_length=60): """ 用于绘制任意大小,并联根数的纳米线版图,python版本:2.7.14,3.3,只画方形器件 长度单位:μm width 单根纳米线宽度 length 纳米线长度,同时是纳米线区域的半径 pitch 纳米线周期宽度 itr 计数纳米线根数 n:并联纳米线根数 m:二级并联根数 pals_length:二级并联长度 elec_width MA6光刻电极宽度 """ length = float(length) width = float(width) pitch = float(pitch) n = int(n) is_interrupt = int(is_interrupt) device_shape = int(device_shape) pals_length = float(pals_length) elec_width = int(elec_width) pin_length = float(pin_length) minedge = 10 maxdiameter = length + 2 * minedge #外围结构为5um,设置纳米线电子束曝光尺寸大小 Cellname = "nanowire" + str(itr) single_cell = gdspy.Cell(Cellname, exclude_from_current=True) mark = itr #gdspy.GdsLibrary.add(single_cell,overwrite_duplication = True) if is_interrupt == 1 and pals_length < pitch - width: print("并联长度过小") return single_cell if length + minedge > maxdiameter: print("纳米线长度设置应小于等于50μm") return single_cell #返回空的cell if is_interrupt == 1 and pals_length > length: print("纳米线并联长度应小于直径") return single_cell #返回空的cell total = int(length / pitch) """ #根据并联纳米线根数和纳米线间距来微调纳米线直径 """ if n < 1 or m < 1: print("纳米线小于1,n应该>=1") return single_cell elif type(n) == float: print('纳米线并联数应为>=1的整数') return single_cell unnece = total % (n * m) #多余的纳米线根数 itr = int(total / n / m) #纳米线周期 if unnece > int(n / 2): total = (itr + 1) * n * m else: total = itr * n * m a = (elec_width - length) / pin_length / 2 if a - int(a) > 0.8: a = int(a) + 2 else: a = int(a) + 1 oldl = length length = total * pitch print("对纳米线" + Cellname + "长度进行了微调:原始值{},微调后值{},".format(oldl, total * pitch)) # length = total*pitch # total1 = total half = total / 2 """ 绘制纳米线核心区域 两步绘制: 计算调整圆的直径,确定圆的刻蚀线终点 1 绘制中心圆区域 2,绘制隔离线 """ #步骤一1 if device_shape == 0: edge = shape.circle(pitch * total, width, pitch, total, half) # iso = shape.circleiso(length,width,n) # equ_area = shape.circle_equ(length,maxdiameter,width,pitch,total,half) elif device_shape == 1: edge = shape.squire(pitch * total, width, pitch, total, half) # iso = shape.squireiso(length,width,n) # equ_area = shape.squire_equ(length,maxdiameter,width,pitch,total,half) # single_cell.add(iso[0]) # single_cell.add(iso[1]) # # #绘制外围等效曝光区 # for i in equ_area: # for j in i: # single_cell.add(gdspy.Rectangle(*j,layer = 1,datatype = 1)) # #纳米线核心区域点阵 startpoint = edge[0] finalpoint = edge[1] i = 0 location = numpy.linspace(0, total, int(total / n) + 1) #二级并联线位置 location1 = numpy.linspace(0, total, int(total / n / m) + 1) #隔离线位置 j = 1.0 #direction max_length = 0 m1 = m while i < len(startpoint) - n * 2: #调整并联单元长度相等 m = 0 while m < n and i < len(startpoint): if i == 0: #保证0点的线存在 startpoint[i] = (startpoint[i - m + 1][0], startpoint[i][1]) finalpoint[i] = (finalpoint[i - m + 1][0], finalpoint[i][1]) startpoint[i] = (startpoint[i - m][0], startpoint[i][1]) finalpoint[i] = (finalpoint[i - m][0], finalpoint[i][1]) m = m + 1 i = i + 1 i = 0 while i < len(startpoint): #计算最大圆直径 if is_interrupt == 1 and n > 1: step = pals_length # single_length = abs(finalpoint[i][0] - startpoint[i][0]) if (int(single_length / step) + 1) * step - length < n * pitch: single_length = int(single_length / step + 1) * step else: single_length = int(single_length / step) * step if numpy.sqrt(single_length**2 / 4 + startpoint[i][1]**2 ) > max_length and device_shape == 0: #圆形的隔离圆大小需要修改 max_length = numpy.sqrt( (single_length**2 / 4 + startpoint[i][1]**2)) startpoint[i] = (-single_length / 2, startpoint[i][1]) finalpoint[i] = (single_length / 2, finalpoint[i][1]) i = i + 1 max_length = 2 * max_length if max_length < pitch * total: max_length = pitch * total #保证外切圆直径为离散值后的最大直径 maxdiameter = max_length + 2 * minedge #调整最大曝光区域 if maxdiameter <= pin_length: maxdiameter = pin_length i = 0 while i < len(startpoint): #i=0,和total对应在x=0位置 if 0 == 1: j = -j else: #每隔30um绘制一个断点 if is_interrupt == 1 and n > 1: step = pals_length # k = 0 if i not in location: while (k + 1) * step < finalpoint[i][0] - startpoint[i][0]: steppoint1 = (startpoint[i][0] + k * step, startpoint[i][1]) steppoint2 = (startpoint[i][0] + (k + 1) * step - width * (n - 1), finalpoint[i][1]) polym = gdspy.Rectangle(steppoint1, steppoint2, layer=1, datatype=1) polym.fillet(pitch - width, points_per_2pi=20) single_cell.add(polym) k = k + 1 else: steppoint1 = (startpoint[i][0] + k * step, startpoint[i][1]) steppoint2 = finalpoint[i] polym = gdspy.Rectangle(steppoint1, steppoint2, layer=1, datatype=1) polym.fillet(pitch - width, points_per_2pi=20) single_cell.add(polym) else: if i not in location: polym = gdspy.Rectangle(startpoint[i], finalpoint[i], layer=1, datatype=1) polym.fillet((pitch - width) / 2, points_per_2pi=20) single_cell.add(polym) if i in location: if i in location1: startpoint[i] = (j * startpoint[i][0], startpoint[i][1]) if device_shape == 0: finalpoint[i] = (j * numpy.sqrt((max_length / 2 + 3)**2 - ((half - i) * pitch)**2), finalpoint[i][1]) elif device_shape == 1: finalpoint[i] = (j * (max_length / 2 + 3), finalpoint[i][1]) j = -j polym = gdspy.Rectangle(startpoint[i], finalpoint[i], layer=1, datatype=1) polym.fillet((pitch - width) / 2, points_per_2pi=20) single_cell.add(polym) i = i + 1 if device_shape == 0: iso = shape.circleiso(max_length, width, n) equ_area = shape.circle_equ(max_length, maxdiameter, width, pitch, total, half) elif device_shape == 1: iso = shape.squireiso(max_length, width, n) equ_area = shape.squire_equ(max_length, maxdiameter, width, pitch, total, half) single_cell.add(iso[0]) single_cell.add(iso[1]) #绘制外围等效曝光区 layer = {'layer': 1, 'datatype': 1} #定义图层 for i in equ_area: for j in i: single_cell.add(gdspy.Rectangle(*j, **layer)) #纳米线核心区域点阵 startpoint = edge[0] finalpoint = edge[1] """ 电极线结构 pitch 纳米线间距,即周期 width:纳米线宽度 length 纳米线长度,电极宽度设置为2um,在并联纳米线总宽宽度>1μm后, 电极宽度调整为(n+4)*width 预曝光区域,宽度设置为5μm 曝光长度设置为length/2+5,pitch与纳米线一致 """ length = max_length #将length改为划出纳米线调整后的最大直径 total = int((maxdiameter / 2 - length / 2 - 1) / pitch) i = 0 m = m1 if n * m * width >= 1: half_elecwidth = (n * m + 4) * width else: half_elecwidth = 1 old = half_elecwidth while i <= total - 1: if i <= int(n * m * width / pitch) + 1: half_elecwidth = max_length / 2 + 3 else: half_elecwidth = old elec1 = gdspy.Rectangle( (half_elecwidth, i * pitch + length / 2), (maxdiameter / 2, i * pitch + length / 2 + pitch - width), **layer) single_cell.add(elec1) elec2 = gdspy.Rectangle( (-half_elecwidth, i * pitch + length / 2), (-maxdiameter / 2, i * pitch + length / 2 + pitch - width), **layer) single_cell.add(elec2) elec3 = gdspy.Rectangle( (-half_elecwidth, (-i - 1) * pitch - length / 2), (-maxdiameter / 2, -i * pitch - length / 2 - (pitch - width)), **layer) single_cell.add(elec3) elec4 = gdspy.Rectangle( (half_elecwidth, (-i - 1) * pitch - length / 2), (maxdiameter / 2, -i * pitch - length / 2 - (pitch - width)), **layer) single_cell.add(elec4) i = i + 1 """ 隔离线,宽度1um,伸出纳米线区域elec_width/2+pin_ength """ # length = oldl #需要原始直径值 if elec_width / 2 > length / 2 + pin_length - 10: a = (elec_width / 2 - length / 2 - pin_length) / pin_length if a - int(a) > 0.9: a = int(a) + 2 else: a = int(a) + 1 halflen = pin_length * (a + 1) + length / 2 else: halflen = length / 2 + pin_length edgelen = maxdiameter / 2 #纳米线区域边界 insulate1 = gdspy.Rectangle((half_elecwidth, edgelen - 1), (halflen, edgelen), **layer) single_cell.add(insulate1) insulate2 = gdspy.Rectangle((-half_elecwidth, edgelen - 1), (-halflen, edgelen), **layer) single_cell.add(insulate2) insulate3 = gdspy.Rectangle((-half_elecwidth, -edgelen + 1), (-halflen, -edgelen), **layer) single_cell.add(insulate3) insulate4 = gdspy.Rectangle((half_elecwidth, -edgelen + 1), (halflen, -edgelen), **layer) single_cell.add(insulate4) insulate5 = gdspy.Rectangle((edgelen - 1, halflen), (edgelen, -halflen), **layer) single_cell.add(insulate5) insulate6 = gdspy.Rectangle((-edgelen + 1, halflen), (-edgelen, -halflen), **layer) single_cell.add(insulate6) """ 绘制拼接场外围尺寸,固定等效曝光区域宽10μm 位置在边界处:pin_length-minedge """ """ length = oldl # oldl=原始length,保证被整场分割而不滑移。允许出现边界处拼接场存在。 layer_useless = {'layer': 3, 'datatype': 3} out = gdspy.Rectangle((-length / 2 - pin_length, -maxdiameter / 2), # 左边 (-length / 2 - pin_length + 1, maxdiameter / 2), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((length / 2 + pin_length, -maxdiameter / 2), # 右边 (length / 2 + pin_length - 1, maxdiameter / 2), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((-maxdiameter / 2, length / 2 + pin_length), # 上左 (-half_elecwidth, length / 2 + pin_length - 1), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((maxdiameter / 2, length / 2 + pin_length), # 上右 (half_elecwidth, length / 2 + pin_length - 1), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((-maxdiameter / 2, -length / 2 - pin_length), # 下左 (-half_elecwidth, -length / 2 - pin_length + 1), **layer_useless ) single_cell.add(out) out = gdspy.Rectangle((maxdiameter / 2, -length / 2 - pin_length), # 下右 (half_elecwidth, -length / 2 - pin_length + 1), **layer_useless ) single_cell.add(out) """ """ 对准标记 4umX100μm大小十字 位置,-500um,500um """ markers = [1, 9, 41, 73, 81] if mark in markers: cross = gdspy.Rectangle((-450, 498), (-550, 502), **layer) single_cell.add(cross) cross = gdspy.Rectangle((-498, 450), (-502, 550), **layer) single_cell.add(cross) """ 编号 """ text = gdspy.Text(str(number), 20, (1000, 300), **layer) single_cell.add(text) merged = gdspy.fast_boolean(gdspy.Rectangle( (-maxdiameter / 2, -maxdiameter / 2), (maxdiameter / 2, maxdiameter / 2)), gdspy.CellReference(single_cell), 'not', max_points=190) # Offset the path shape by 0.5 and add it to the cell. single_cell.add(merged) return single_cell
def number(self, text='123456', size=300): self.htext1 = gs.Text(text=text, size=size, layer=2) self.cell.add(self.htext1)
f = linspace(4.5E9,4.6E9,6) # Fundamental frequency l4 = c/sqrt(ereff)/4./f*1E6 # length for lambda/4 resonator for i in range(0,6): totalLength = l4[i] openDis = 10 capDist = 10*(1+i) cpwSrtExtend = 200 bendRad = 100 meanderLen = totalLength - openDis - capDist - cpwSrtExtend - pi*bendRad exec("cpw" + str(i) + " = gdslib.CPWPath(10,5,layer = 6)") exec("cpw" + str(i) + ".start([2100 - 750 + 625 + 1250*" + str(i) + ",2500 + 25],'-x')") exec("cpw" + str(i) + ".openGap(openDis)") exec("cpw" + str(i) + ".straight(capDist)") exec("cpw" + str(i) + ".bend(bendRad, 'r')") exec("cpw" + str(i) + ".straight(cpwSrtExtend)") exec("cpw" + str(i) + ".bend(bendRad, 'r')") exec("cpw" + str(i) + ".meander(meanderLen, bendRad, 500,'ll')") exec("poly = gdspy.PolygonSet(cpw" + str(i) + ".path.polygons)") exec("gdslib.addPolyToCell(poly,device)") # exec("print(cpw" + str(i) + ".len())") # DEVICE LABEL deviceText = gdspy.Text('2016Jan18_Resonator', 250, (3000,250), layer=4) device.add(deviceText) gdspy.gds_print(deviceName + '.gds', unit=1.0e-6, precision=1.0e-9) gdspy.LayoutViewer()
# add coupling tapers for ktaper in range(0, 3): posTaper = (taperWidth / 2, -(k + ktaper) * couplePitch) MZIUnitCell.add(gdspy.CellReference(couplingTaperCell, posTaper)) MZIUnitCell.add( gdspy.Rectangle([ -taperBufferLength, -(k + ktaper) * couplePitch + taperBufferWidth / 2 ], [0, -(k + ktaper) * couplePitch - taperBufferWidth / 2], layer=layerNumber)) # add text below coupling first taper text = gdspy.Text( str(int(deltaL)), textSize, (textBuffer, -k * couplePitch - textBuffer - textSize / 2), layer=layerNumber) MZIUnitCell.add(text) # connect top taper to coupler MZIUnitCell.add( gdspy.Rectangle( [taperWidth, -k * couplePitch + waveguideWidth / 2], [ k * couplePitch - MZIcellWidth / 2, -k * couplePitch - waveguideWidth / 2 ], layer=layerNumber)) # connect middle taper to coupler length = [
# TOP RESONATOR ARRAY f = linspace(4.5E9,4.6E9,6) # Fundamental frequency l4 = c/sqrt(ereff)/4./f*1E6 # length for lambda/4 resonator for i in range(0,6): totalLength = l4[i] openDis = 10 capDist = 10*(1+i) cpwSrtExtend = 200 bendRad = 100 meanderLen = totalLength - openDis - capDist - cpwSrtExtend - pi*bendRad cpw = gdslib.CPWPath(10,5,layer = 6, cellName = device) cpw.start([2100 - 750 + 625 + 1250*i,2500 + 25],'-x') cpw.openGap(openDis) cpw.straight(capDist) cpw.bend(bendRad, 'r') cpw.straight(cpwSrtExtend) cpw.bend(bendRad, 'r') cpw.meander(meanderLen, bendRad, 500,'ll') cpw.end() # DEVICE LABEL deviceText = gdspy.Text('2016Feb03_Resonator', 250, (3000,250), layer=4) device.add(deviceText) gdspy.gds_print(deviceName + '.gds', unit=1.0e-6, precision=1.0e-9) gdspy.LayoutViewer()
#add termination buffer BraggUnitCell.add(gdspy.Rectangle( [chipDim,-(iterCoupler+ktaper)*couplePitch+taperBufferWidth/2 - yOffset], [chipDim + taperBufferLength,-(iterCoupler+ktaper)*couplePitch-taperBufferWidth/2 - yOffset], layer=layerNumber)) # connect termination taper to bragg array BraggUnitCell.add(gdspy.Rectangle( [taperWidth + numCols * L, -(iterCoupler+ktaper)*couplePitch - yOffset + waveguideWidth/2], [chipDim - taperWidth, -(iterCoupler+ktaper)*couplePitch - yOffset - waveguideWidth/2], layer=layerNumber )) # add text below taper on left label = 'p='+str(int(gratingPeriod[iterPeriods]*1e3))+' w='+str(int(dwidth[iterWidths]*1e3)) text = gdspy.Text(label, textSize, (textBuffer, -(iterCoupler+ktaper)*couplePitch - textBuffer - textSize/2 - yOffset),layer=layerNumber) BraggUnitCell.add(text) # add text below taper on right text = gdspy.Text(label, textSize, (chipDim - 8*textBuffer, -(iterCoupler+ktaper)*couplePitch - textBuffer - textSize/2 - yOffset),layer=layerNumber) BraggUnitCell.add(text) # consolidate cells to master cell BGLattice.add(gdspy.CellReference(BraggUnitCell)) iterCoupler = iterCoupler + numRepeats # ------------------------------------------------------------------ # # Center Parent Cell for fab # ------------------------------------------------------------------ #
outerCross = gdspy.Cell("OUTER CROSS", outerCrossShape) crossCoordinates = outerCrossDiameter / 2 + crossSpacing * np.array([1, 1]) triangle = createArrow(20 * um, 10 * um, 3 * um) crossTopRight = createCross(outerCrossDiameter, outerCrossWidth, crossCoordinates * np.array([1, 1])) crossTopLeft = createCross(outerCrossDiameter, outerCrossWidth, crossCoordinates * np.array([-1, 1])) crossBottomRight = createCross(outerCrossDiameter, outerCrossWidth, crossCoordinates * np.array([1, -1])) crossBottomLeft = createCross(outerCrossDiameter, outerCrossWidth, crossCoordinates * np.array([-1, -1])) textCrossOffset = np.array([outerCrossWidth, outerCrossWidth]) topRightText = gdspy.Text( "TR", 3, np.array([1, 1]) * crossCoordinates + textCrossOffset) topLeftText = gdspy.Text( "TL", 3, np.array([-1, 1]) * crossCoordinates + textCrossOffset) bottomRightText = gdspy.Text( "BR", 3, np.array([1, -1]) * crossCoordinates + textCrossOffset) bottomLeftText = gdspy.Text( "BL", 3, np.array([-1, -1]) * crossCoordinates + textCrossOffset) cell.add(topRightText) cell.add(topLeftText) cell.add(bottomRightText) cell.add(bottomLeftText)
# pat.add(supp_ref) # pat.add(tether_list) # pat.add(taper_ref) # now rotate the cell by 90 degrees and offset to the cell position pat_ref = gdspy.CellReference( pat, (X_MIN + 500 + k * DEVICE_SPACING + i * SUBFIELD_SPACING + SUBFIELD_SPACING / 2, Y_MAX), rotation=90) # old line for adding a disc without a waveguide #disc_ref=gdspy.CellReference(disc_cell,(X_MIN+j*DEVICE_SPACING+i*SUBFIELD_SPACING,Y_MAX-DICING-160)) main.add(pat_ref) # add text microdisk_fiber_label = gdspy.Text('MICRODISK+LENSED FIBER', 128, (X_MIN + 1500, Y_MAX + 1000), **ld_opt) # microdisk_label=gdspy.Text('MICRODISK',128,(X_MIN+2500,Y_MAX-DICING-1000),**ld_opt) main.add(microdisk_fiber_label) #main.add(microdisk_label) # sweep the spacing of the ring from the waveguide for i in range(len(RING_SPACINGS)): params['dist'] = RING_SPACINGS[i] # add reference 3 copies of the same ring pattern for j in range(COPIES): # pass in parameter to give a unique name to each cell # the name should be a string disc_args = {} params['wg_width'] = 0.550 * WG_W_BIAS * sc
for j in range(0, 3): idx = 3 * i + j totalLength = l4[idx] openDis = gaps[idx] capDist = 50 constantOffset = 15 distOffset = widths[idx] / 2 + gaps[idx] + constantOffset + dWidth * idx print(distOffset) cpwSrtExtend = 200 bendRad = 150 meanderLen = totalLength - openDis - capDist - cpwSrtExtend - pi * bendRad cpw = gdslib.CPWPath(1e-9, (widths[idx] + 2 * gaps[idx]) / 2 + 4, layer=8, cellName=device) cpw.start([1125 + 150 + distOffset + 2500 * i, 1900 + 1100 * j], '+y') cpw.openGap(openDis) cpw.straight(capDist) cpw.bend(bendRad, 'r') cpw.straight(cpwSrtExtend) cpw.bend(bendRad, 'r') cpw.meander(meanderLen, bendRad, 500, 'll') cpw.end() # DEVICE LABEL deviceText = gdspy.Text(deviceName, 250, (3000, 500), layer=4) device.add(deviceText) gdspy.LayoutViewer() gdspy.gds_print(deviceName + '.gds', unit=1.0e-6, precision=1.0e-9)
circle2 = gdspy.Cell('DOTS2.0UM') # size of the circles #circle1.add(gdspy.Round((0, 0), 0.5, layer=2)) # 1um diameter circle2.add(gdspy.Round((0, 0), 1, layer=2)) # 2um diameter # add a cell for the outline, text and arrays rect_cell = gdspy.Cell('REFS') #ref_cell2 = gdspy.Cell('DNA1') # draw circle array (class gdspy.CellArray(ref_cell, columns, rows, spacing, origin=(0, 0) rect_cell.add(gdspy.CellArray('DOTS2.0UM', 6800, 6800, (10, 10), (4100, 4100))) # draw rectangle as border for the mask rectangle = gdspy.Rectangle((0, 0), (76200, 76200)) rect_cell.add(rectangle) # lable for the mask file rect_cell.add(gdspy.Text('2.0 um x 10 um', 1800, (27850, 73000), layer=6)) compile_date = time.strftime("%d-%m-%Y") rect_cell.add(gdspy.Text(compile_date, 2500, (28000, 1000), layer=6)) curr_time = time.strftime("%H.%M.%S") file_name = "Mask-{0}-{1}.gds".format(compile_date, curr_time) print(file_name) gdspy.write_gds(file_name, cells=[rect_cell, circle2], unit=1.0e-6, precision=1.0e-9)
offset=[-0.25, 0.25, -0.75, 0.75], ) lp.parametric( lambda u: numpy.array((45 * u, 4 * numpy.sin(6 * numpy.pi * 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(gdspy.Cell("robust_paths").add(lp)) # Boolean Operations # Create some text text = gdspy.Text("GDSPY", 4, (0, 0)) # Create a rectangle extending the text's bounding box by 1 bb = numpy.array(text.get_bounding_box()) rect = gdspy.Rectangle(bb[0] - 1, bb[1] + 1) # Subtract the text from the rectangle inv = gdspy.boolean(rect, text, "not") draw(gdspy.Cell("boolean_operations").add(inv)) # Slice Operation ring1 = gdspy.Round((-6, 0), 6, inner_radius=4) ring2 = gdspy.Round((0, 0), 6, inner_radius=4) ring3 = gdspy.Round((6, 0), 6, inner_radius=4) # Slice the first ring across x=-3, the second ring across x=-3 # and x=3, and the third ring across x=3
grating.add(poly) return grating lib = gdspy.GdsLibrary(precision=1e-10) # Geometry must be placed in cells. DEVICES = lib.new_cell("DEVICES") # load data for Air filename = './data_apodized/apod_2D_params_Air_8Deg.txt' data = readParameters(filename) text = 'Air 1' com = lib.new_cell(text) com.add(gdspy.Text(text, 40, (0, 50), **ld_fulletch)) ref = gdspy.CellReference(com) DEVICES.add(ref) space = 0 for complement in [0, 0.005, -0.005]: data_mod = list(np.array(data) + complement) cellname = 'GC_Air_Apodized_8Deg_' + str(int(complement * 1e3)) # create the rect grating for Air GC_rect_Apodized_Air = lib.new_cell(cellname) gc_rect(GC_rect_Apodized_Air, data) GC_line = gc_line(lib.new_cell(cellname + "_Line"), GC_rect_Apodized_Air) DEVICES.add(gdspy.CellReference(GC_line, (0, space))) space += -100 text = 'Air 2'
import scipy.io as scio import Photonics_PDK_v1 as GC lib = gdspy.GdsLibrary(precision=1e-10) # Geometry must be placed in cells. GC_scan = lib.new_cell("GC_scan") kwargs = {'w_gc': 12, 'w_wg': 0.510} layer_Mark = {"layer": 0, "datatype": 0} ld_fulletch = {"layer": 1, "datatype": 1} posi_end = (0, 0) text = 'D 165' com = lib.new_cell(text) com.add( gdspy.Text(text, 40, (posi_end[0] + 100, posi_end[1] + 50), **ld_fulletch)) ref = gdspy.CellReference(com) GC_scan.add(ref) posi_end = GC.Scan_d(lib, GC_scan, 0.165, 0.665, 'UGC_SiO2', step=0.003, origin=posi_end, n=(3, 3), space=200, type_GC='FA', **kwargs) text = 'D 175'
gdspy.CellReference(couplingTaperCell, posTaper, rotation=180)) RingUnitCell.add( gdspy.Rectangle([ chipDim + taperBufferLength, -(k + ktaper) * couplePitch + taperBufferWidth / 2 - couplerYOffset ], [ chipDim, -(k + ktaper) * couplePitch - taperBufferWidth / 2 - couplerYOffset ], layer=layerNumber)) # add text below coupling first taper on left text = gdspy.Text(str(int(ringRadius)), textSize, (textBuffer, -k * couplePitch - textBuffer - textSize / 2 - couplerYOffset), layer=layerNumber) RingUnitCell.add(text) # add text below coupling first taper on right text = gdspy.Text(str(int(ringRadius)), textSize, (chipDim - taperWidth, -k * couplePitch - textBuffer - textSize / 2 - couplerYOffset), layer=layerNumber) RingUnitCell.add(text) # connect top taper to coupler RingUnitCell.add( gdspy.Rectangle([