import pya import math class ParrTnPatch(pya.PCellDeclarationHelper): """ The PCell declaration for the IDT n Patch """ def __init__(self): # Important: initialize the super class super(ParrTnPatch, self).__init__() digitW=1500 # line/spacing = 1.5/1.5 numD=201 # 100 pairs of digits for txducer plus one digit (to make it symm'c) pitch=2*digitW tipClrnc= 5000 #2*pitch # tip of digit clearance to bridge that connect to the busbar overlapExtention = 10000 #5*2*pitch # this value minus tipClrns gives the length of digit that overlaps the bridge and makes contact with it digitL=100*2*pitch # digit length shiftY=tipClrnc + overlapExtention busBarOvrlp=25000 busBarClearance=25000 patchW=busBarClearance+busBarOvrlp patchL=((2*numD-1)*digitW) + 2*digitW # The last 2*digitW is for extention of the patch by digitW on each side (to ensure coverage of the digit) print(str(2*numD-1)) print(str(patchL)) # declare the parameters self.param("lyr", self.TypeLayer, "Layer") self.param("digitW", self.TypeDouble, "Digit Width", default = digitW) self.param("digitL", self.TypeDouble, "Digit Length", default = digitL) self.param("shp", self.TypeShape,"",default=pya.Polygon( [pya.DPoint(0,0), pya.DPoint(0,digitL + tipClrnc + overlapExtention), pya.DPoint(digitW,digitL + tipClrnc + overlapExtention) , pya.DPoint(digitW,0) ] ) ) # , pya.DPoint(digitW,0) self.param("numD", self.TypeInt, "Number of Reflectors", default = numD) self.param("vectX", self.TypeDouble, "vectX", default = pitch) self.param("vectY", self.TypeDouble, "vectY", default = shiftY) self.param("tipClrnc", self.TypeDouble, "Patch to Opposite Digit-tip Clearance", default = tipClrnc) self.param("overlapExtention", self.TypeDouble, "Patch and Digit Overlap Length", default = overlapExtention) self.param("busBarOvrlp", self.TypeDouble, "Patch-Busbar Overlap", default = busBarOvrlp) self.param("busBarClearance", self.TypeDouble, "ActiveDigit-Busbar Overlap", default = busBarClearance) # hidden parameters self.param("patchL", self.TypeDouble, "Patch Length", default = patchL, hidden = True) self.param("patchW", self.TypeDouble, "Patch Width", default = patchW, hidden = True) def display_text_impl(self): # Provide a descriptive text for the cell return "ParrTnPatch - IDT&Patch(Lyr=" + str(self.lyr) + ",Line/Spacing=" + ('%.3f' % (self.vectX/2)) + ")" def coerce_parameters_impl(self): pass def can_create_from_shape_impl(self): return self.shape.is_polygon() # self.shape.is_box() or self.shape.is_polygon() or self.shape.is_path() def parameters_from_shape_impl(self): self.shp =self.shape.dpolygon # self.shape.bbox().center() or self.shape.bbox().width() * self.layout.dbu / 2 self.lyr = self.layout.get_info(self.layer) # [place the PCell in the sm layer as the ref'ced shape] def transformation_from_shape_impl(self): return pya.Trans(pya.Point(0,0)) # No need for a txfrm'n for our case, but need to enter a txfrm'n obj, so we enter zero txfrm'n def produce_impl(self): # This is the main part of the implementation: create the layout self.cell.clear(self.lyr_layer) # Clear shapes already on the layer shps = [ s for s in self.cell.each_shape(self.lyr_layer) ] print("# of shapes in layer (at the start of produce_impl()): " + str(len(shps))) self.cell.shapes(self.lyr_layer).insert(self.shp) # Place the handle for the shape into the layout layer we're using print(str(self.shp.bbox())) for j in self.cell.shapes(self.lyr_layer).each(): # Get all the shapes on this layer and poll and use dpolygon to make them all the same units self.shp = j.dpolygon print("bbox: " + str(self.shp.bbox())) self.digitW = self.digitW * self.layout.dbu self.digitL = self.digitL * self.layout.dbu self.vectX = self.vectX * self.layout.dbu self.vectY = self.vectY * self.layout.dbu self.tipClrnc = self.tipClrnc * self.layout.dbu self.overlapExtention = self.overlapExtention * self.layout.dbu self.busBarOvrlp = self.busBarOvrlp * self.layout.dbu self.busBarClearance = self.busBarClearance * self.layout.dbu self.patchL = self.patchL * self.layout.dbu self.patchW = self.patchW * self.layout.dbu print("self.layout.dbu: " + str(self.layout.dbu)) print("digitW: " + str(self.digitW)) print("digitL: " + str(self.digitL)) print("vectX: " + str(self.vectX)) print("vectY: " + str(self.vectY)) print("numD: " + str(self.numD)) print("numD: " + str(self.numD)) print("patchW: " + str(self.patchW)) print("patchL : " + str(self.patchL)) shps = [ s for s in self.cell.each_shape(self.lyr_layer) ] print("# of shapes in layer (after creation of a polygon within produce_impl()): " + str(len(shps))) # Creating the array in rows and col's by getting the shape and placing in the array pos'ns (and in the second run) rotate and scale/magnify them for k in range(self.numD): if k==0: continue print(str(k)) tt = pya.DCplxTrans(self.vectX*k, -self.vectY*(k%2)) # Defining a txfrm'n, based on spacings and current (j,k) print(str(self.vectX*k) + ", " + str(-self.vectY*(k%2))) self.cell.shapes(self.lyr_layer).insert(tt.trans(self.shp)) # Apply the txfrm'n to a shape and insert it in the cell and in its layer, print("self.cell.shapes(self.lyr_layer).size(): " + str(self.cell.shapes(self.lyr_layer).size()) ) self.patch_shp = pya.Polygon( [pya.DPoint(0,0), pya.DPoint(0,self.patchW), pya.DPoint(self.patchL,self.patchW) , pya.DPoint(self.patchL,0) ] ) self.cell.shapes(self.lyr_layer).insert(self.patch_shp) # Place the handle for the shape into the layout layer we're using for j in self.cell.shapes(self.lyr_layer).each(): # Get all the shapes on this layer and poll and use dpolygon to make them all the same units self.shp = j.dpolygon tt = pya.DCplxTrans(-self.digitW, (self.digitL + self.tipClrnc)) # Defining a txfrm'n to move the patch_shp from origin to the two current drived ends of the digits self.cell.shapes(self.lyr_layer).insert(tt.trans(self.patch_shp)) # Apply the txfrm'n to a shape and insert it in the cell and in its layer, tt = pya.DCplxTrans(-self.digitW, -self.tipClrnc-self.patchW) # Defining a txfrm'n to move the patch_shp from origin to the two current drived ends of the digits self.cell.shapes(self.lyr_layer).insert(tt.trans(self.patch_shp)) # Apply the txfrm'n to a shape and insert it in the cell and in its layer, shps = [ s for s in self.cell.each_shape(self.lyr_layer) ] n=len(shps) print("len(shps): " + str(len(shps))) if len(shps)>self.numD: print(str(len(shps))+", " + str(self.numD) ) for j in self.cell.shapes(self.lyr_layer).each(): # Get all the shapes on this layer and poll and use dpolygon to make them all the same units if j.perimeter()*self.layout.dbu < 4*self.digitW: print("The tiny rectangle found and removed - Perimeter [um] = " + str(j.perimeter()*self.layout.dbu) ) self.cell.shapes(self.lyr_layer).erase(j) break shps1 = [ s for s in self.cell.each_shape(self.lyr_layer) ] shps2 = self.cell.shapes(self.lyr_layer) #shps2.erase(shps1[0]) shps = [ s for s in self.cell.each_shape(self.lyr_layer) ] print(len(shps)) class MyLibT2(pya.Library): """ The library where we will put the PCell into """ def __init__(self): # Set the description self.description = "My2 Third Library" # Create the PCell declarations self.layout().register_pcell("ParrTnPatch", ParrTnPatch()) # That would be the place to put in more PCells ... # Register us with the name "MyLib". # If a library with that name already existed, it will be replaced then. #self.add_technology("si4all") self.register("MyLibT2") # Instantiate and register the library MyLibT2()