def global_markers(layer_marker=10, layer_mask=20): D = Device('Global Markers') R = pg.rectangle(size=(20, 20), layer=1) a = D.add_array(R, columns=6, rows=6, spacing=(100, 100)) a.move([-260, -260]) #Center of the array R = pg.rectangle(size=(20, 20), layer=1) a = D.add_array(R, columns=6, rows=6, spacing=(100, 100)) a.move([-260, -260]) #Center of the array #Add marker cover cover = pg.bbox(bbox=a.bbox, layer=layer_mask) D << pg.offset(cover, distance=100, layer=layer_mask) return D
def poling_region(length=4000, period=5, dutycycle=0.4, gap=25, Lfinger=50, layer=10, pad_width=50): #Calculations Wfinger = period * dutycycle Nfinger = int(length / period) + 1 length = Nfinger * period - (1 - dutycycle) * period P = Device('Poling Electrodes') #Positive side R = pg.rectangle([length, pad_width], layer=layer) F = pg.rectangle([Wfinger, Lfinger], layer=layer) P << R a = P.add_array(F, columns=Nfinger, rows=1, spacing=(period, 0)) a.move([0, pad_width]) #Negative side R2 = pg.rectangle([length, pad_width], layer=layer) r2 = P.add_ref(R2) r2.move([0, pad_width + Lfinger + gap]) return P
def test_write_and_import_gds(): D = Device() D.add_ref(pg.rectangle(size=[1.5, 2.7], layer=[3, 2])) D.add_ref(pg.rectangle(size=[0.8, 2.5], layer=[9, 7])) D.add_array(pg.rectangle(size=[1, 2], layer=[4, 66]), rows=3, columns=2, spacing=[14, 7.5]) D.add_array(pg.rectangle(size=[1.5, 2.5], layer=[4, 67]), rows=1, columns=2, spacing=[14, 7.5]) D.add_polygon([[3, 4, 5], [6.7, 8.9, 10.15]], layer=[7, 8]) D.add_polygon([[3, 4, 5], [1.7, 8.9, 10.15]], layer=[7, 9]) precision = 1e-4 unit = 1e-6 h1 = D.hash_geometry(precision=precision) D.write_gds('temp.gds', precision=unit * precision, unit=1e-6) Dimport = pg.import_gds('temp.gds', flatten=False) h2 = Dimport.hash_geometry(precision=precision) assert (h1 == h2)
def test_group(): # Test all types D = Device() E1 = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=0) E2 = pg.rectangle(size=(4, 2), layer=0).movex(15) e1 = D << E1 e2 = D << E2 e3 = D << E2 e4 = D.add_label('hello', position=(1.5, -1.5)) e5 = pg.snspd() e6 = D.add_polygon([(8, 6, 7, 9, 7, 0), (6, 8, 9, 5, 7, 0)]) e7 = D.add_array(pg.cross()) e2verify = D << E2 # Test creation and addition G = Group() G.add(e1) G.add(e2) G.add([e3, e4, e5]) G += (e6, e7) assert np.allclose(G.bbox.flatten(), np.array([-10., -8.5, 105., 105.])) # Test movement G.move((2, 7)) e2verify.move((2, 7)) assert np.allclose(G.bbox.flatten(), np.array([-8., -1.5, 107., 112.])) assert all(e2.center == e2verify.center) assert e2.rotation == e2verify.rotation # Test rotation G.rotate(90, center=(5, 5)) e2verify.rotate(90, center=(5, 5)) assert np.allclose(G.bbox.flatten(), np.array([-102., -8., 11.5, 107.])) assert all(e2.center == e2verify.center) assert e2.rotation == e2verify.rotation # Test mirroring G.mirror(p1=(1, 1), p2=(-1, 1)) e2verify.mirror(p1=(1, 1), p2=(-1, 1)) assert np.allclose(G.bbox.flatten(), np.array([-102., -105., 11.5, 10.])) assert all(e2.center == e2verify.center) assert e2.rotation == e2verify.rotation h = D.hash_geometry(precision=1e-4) assert (h == '3964acb3971771c6e70ceb587c2ae8b37f2ed112')
def test_add_array(): D = Device() E = Device() E.add_polygon([[30, 20], [30, 0], [0, 0], [0, 20]], layer=7) A = D.add_array(E, columns=7, rows=5, spacing=(31, 21)) assert (A.bbox.tolist() == [[0.0, 0.0], [216.0, 104.0]]) A.rotate(10) A.move((15, 1.5)) A.mirror((0, 1)) A.get_polygons() h = D.hash_geometry(precision=1e-4) assert (h == '418b7503baff80fbe93031d45d87557c277f07b4') F = Device() f1 = F << D f2 = F << D f1.movex(300) f2.rotate(45) h = F.hash_geometry(precision=1e-4) assert (h == 'fd7c2b4adb811342b836d9fca13992eff951630d')
for p in all_ports: if 'is_useful' in p.info and p.info['is_useful'] is True: print(str(p) + ' is useful') #============================================================================== # Advanced: Using CellArray #============================================================================== # In GDS, there's a type of structure called a "CellArray" which takes a cell # and repeats it NxM times on a fixed grid spacing. For convenience, PHIDL # includes this functionality with the add_array() function. Note that # CellArrays are not compatible with ports (since there is no way to # access/modify individual elements in a GDS cellarray) D = Device() R = pg.rectangle([30, 20]) a = D.add_array(R, columns=7, rows=5, spacing=(31, 21)) # bbox gets the bounding box of the whole array a.bbox.tolist() == [[0.0, 0.0], [216.0, 104.0]] qp(D) #============================================================================== # Adding premade geometry with phidl.geometry #============================================================================== # Usually at the beginning of a phidl file we import the phidl.geometry module # as ``pg``, like this: import phidl.geometry as pg # The ``pg`` module contains dozens of premade shapes and structures, ranging # from simple ones like ellipses to complex photonic structures. Let's create # a few simple structures and plot them D = Device()