def waveguide(width=10, height=1): WG = Device('waveguide') WG.add_polygon([(0, 0), (width, 0), (width, height), (0, height)]) WG.add_port(name='wgport1', midpoint=[0, height / 2], width=height, orientation=180) WG.add_port(name='wgport2', midpoint=[width, height / 2], width=height, orientation=0) return WG
def test_rotate(): # Test polygon rotation D = Device() p = D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) p.rotate(37.5) h = D.hash_geometry(precision=1e-4) assert (h == '2e4815072eabe053c3029d9e29a5b3ed59fe9bb7') # Test Device rotation D = Device() p = D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) D.rotate(37.5) h = D.hash_geometry(precision=1e-4) assert (h == '2e4815072eabe053c3029d9e29a5b3ed59fe9bb7')
def test_reflect(): # Test polygon reflection D = Device() p = D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) p.mirror(p1=(1.7, 2.5), p2=(4.5, 9.1)) h = D.hash_geometry(precision=1e-4) assert (h == 'bc6ae5308c2240e425cd503e0cdda30007bbfc4d') # Test Device reflection D = Device() p = D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) D.mirror(p1=(1.7, 2.5), p2=(4.5, 9.1)) h = D.hash_geometry(precision=1e-4) assert (h == 'bc6ae5308c2240e425cd503e0cdda30007bbfc4d')
def test_flatten(): D = Device() E1 = Device() E2 = Device() E1.add_polygon( [(8,6,7,9,7,0), (6,8,9,5,7,0)], layer = 8) E2.add_polygon( [(18,16,17,19,17,10), (16,18,19,15,17,10)], layer = 9) D << E1 D << E2 h = D.hash_geometry(precision = 1e-4) assert(h == '8a057feca51d8097f2a915eda558fe2a9b88fb13') D.flatten() h = D.hash_geometry(precision = 1e-4) assert(h == '8a057feca51d8097f2a915eda558fe2a9b88fb13') D.flatten(single_layer = (5,5)) h = D.hash_geometry(precision = 1e-4) assert(h == 'cfc1ba30384f5f1f7d888f47f16d1f310f95b464')
def test_move(): # Test polygon move D = Device() p = D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) p.move([1.7, 0.8]) h = D.hash_geometry(precision=1e-4) assert (h == '57a86bce5f60f7bc78c7c30473a544b736d2afb3') p.movex(13.9) h = D.hash_geometry(precision=1e-4) assert (h == '8fe6706e05ebe1512ee2efe2582546b949fbc48f') p.movey(19.2) h = D.hash_geometry(precision=1e-4) assert (h == '7df43241eca2dd11f267c25876e650eadaca7d9f') # Test Device move D = Device() D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) D.add_polygon([(8, 6, 7, 9, 7, 0), (6, 8, 9, 5, 7, 0)]) D.move([1.7, 0.8]) h = D.hash_geometry(precision=1e-4) assert (h == 'c863156dd00a590dc02823e1791554d4142b1ea9') # Test label move D = Device() D.add_polygon([(8, 8, 8, 8), (6, 6, 6, 6)]) l = D.add_label('testing', position=D.center) print(all(l.center == D.center)) D.rotate(45) print(np.allclose(l.center, D.center)) D.move([70000.5, 30000.5]) print(np.allclose(l.center, D.center)) D.rotate(75) print(np.allclose(l.center, D.center)) D.mirror([7, 5]) print(np.allclose(l.center, D.center))
def test_remove_layers(): D = Device() D.add_polygon([(8, 6, 7, 9, 7), (6, 8, 9, 5, 7)], layer=13) D.add_polygon([(18, 16, 17, 19, 17), (16, 18, 19, 15, 17)], layer=14) xpts = list(range(1000)) ypts = [x % 73 for x in xpts] p = D.add_polygon([xpts, ypts], layer=15) p.fracture(max_points=13, precision=1e-4) # Switch part of the polygons to layer (14,0) p.layers[13:17] = [14] * 4 # Switch part of the polygons to layer (14,1) p.layers[23:27] = [14] * 4 p.datatypes[23:27] = [1] * 4 h = D.hash_geometry(precision=1e-4) assert (h == '7a7aa6a22b3d0b852a0e465398018dd19a1be305') D.remove_layers(layers=[13, (14, 0)]) h = D.hash_geometry(precision=1e-4) assert (h == 'bb81ec3b3a6be2372a7ffc32f57121a9f1a97b34')
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')
def test_polygon_simplify(): D = Device() t = np.linspace(0, np.pi, 1000) x = np.cos(t) y = np.sin(t) poly = D.add_polygon([x, y]) h = D.hash_geometry(precision=1e-4) assert (h == '0c3b1465c8b6ffd911c41b02114b9a06f606ad91') # qp(D) poly.simplify(tolerance=1e-1) h = D.hash_geometry(precision=1e-4) assert (h == '7d9ebcb231fb0107cbbf618353adeb583782ca11')
def test_bbox(): D = Device() D.add_polygon([(0, 0), (10, 0), (10, 10), (0, 10)], layer=2) assert (D._bb_valid == False) # Calculating the bbox should change _bb_valid to True once it's cached assert (D.bbox.tolist() == [[0, 0], [10, 10]]) assert (D._bb_valid == True) E = Device() e1 = E.add_ref(D) e2 = E.add_ref(D) e2.movex(30) assert (E._bb_valid == False) assert (E.bbox.tolist() == [[0, 0], [40, 10]]) assert (E._bb_valid == True) D.add_polygon([(0, 0), (100, 0), (100, 100), (0, 100)], layer=2) D.add_polygon([(0, 0), (100, 0), (100, 100), (0, 100)], layer=2) assert (E.bbox.tolist() == [[0, 0], [130, 100]]) assert (e1.bbox.tolist() == [[0, 0], [100, 100]]) assert (e2.bbox.tolist() == [[30, 0], [130, 100]])
def test_move(): D = Device() p = D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) p.move([1.7, 0.8]) h = D.hash_geometry(precision=1e-4) assert (h == '57a86bce5f60f7bc78c7c30473a544b736d2afb3') p.movex(13.9) h = D.hash_geometry(precision=1e-4) assert (h == '8fe6706e05ebe1512ee2efe2582546b949fbc48f') p.movey(19.2) h = D.hash_geometry(precision=1e-4) assert (h == '7df43241eca2dd11f267c25876e650eadaca7d9f')
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 triplet_pad(x, y, pad, pad_g, elec_m, elec, elec_s, e_e_gap, pos): R = pg.rectangle(size=(pad, pad), layer=70) D = Device() rect1 = D << R rect2 = D << R rect3 = D << R rect1.move([x, y]) rect2.move([x - pad_g, y]) rect3.move([x + pad_g, y]) #middle connector pad xm1 = x - elec_m / 2 xm2 = x - pad / 2 xm3 = x + pad / 2 xm4 = x + elec_m / 2 xpts = (xm1 + pad / 2, xm2 + pad / 2, xm3 + pad / 2, xm4 + pad / 2) ypts = (y + pad + elec, y + elec, y + elec, y + pad + elec) if pos == 'u': ypts = (y - elec, y, y, y - elec) D.add_polygon([xpts, ypts], layer=70) text_size = 20 L = pg.text(text='S', size=text_size, layer=97, justify='center') D.add_ref(L).move((x + pad / 3, y)) #left connector pad xm1 = x - elec_m / 2 - e_e_gap - elec_s xm2 = x - pad / 2 - pad_g xm3 = x + pad / 2 - pad_g xm4 = x - elec_m / 2 - e_e_gap xpts = (xm1 + pad / 2, xm2 + pad / 2, xm3 + pad / 2, xm4 + pad / 2) ypts = (y + pad + elec, y + elec, y + elec, y + pad + elec) if pos == 'u': ypts = (y - elec, y, y, y - elec) D.add_polygon([xpts, ypts], layer=70) L = pg.text(text='G', size=text_size, layer=97, justify='center') D.add_ref(L).move((x - pad_g + +pad / 3, y)) #left connector pad xm1 = x + elec_m / 2 + e_e_gap xm2 = x + pad / 2 + pad_g - pad xm3 = x + pad / 2 + pad_g xm4 = x + elec_m / 2 + e_e_gap + elec_s xpts = (xm1 + pad / 2, xm2 + pad / 2, xm3 + pad / 2, xm4 + pad / 2) ypts = (y + pad + elec, y + elec, y + elec, y + pad + elec) if pos == 'u': ypts = (y - elec, y, y, y - elec) D.add_polygon([xpts, ypts], layer=70) L = pg.text(text='G', size=text_size, layer=97, justify='center') D.add_ref(L).move((x + pad_g + +pad / 3, y)) return D
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')
# reference, which we will label with lowercase letters wg1 and wg2. This # handle will be useful later when we want to move wg1 and wg2 around in D. wg1 = D.add_ref(WG1) # Using the function add_ref() wg2 = D << WG2 # Using the << operator which is identical to add_ref() # Alternatively, we can do this all on one line wg3 = D.add_ref(waveguide(width=14, height=3)) qp(D) # quickplot it! #============================================================================== # Creating polygons #============================================================================== # Create and add a polygon from separate lists of x points and y points # e.g. [(x1, x2, x3, ...), (y1, y2, y3, ...)] poly1 = D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) # Alternatively, create and add a polygon from a list of points # e.g. [(x1,y1), (x2,y2), (x3,y3), ...] using the same function poly2 = D.add_polygon([(0, 0), (1, 1), (1, 3), (-3, 3)]) qp(D) # quickplot it! #============================================================================== # Manipulating geometry 1 - Basic movement and rotation #============================================================================== # There are several actions we can take to move and rotate the geometry. These # actions include movement, rotation, and reflection. wg1.move([10, 4]) # Shift the second waveguide we created over by dx = 10, dy = 4
def computationally_intensive_device(width=10, unused_var=1): D = Device() time.sleep(0.1) # Pretend we're doing computations for 0.1 seconds here D.add_polygon([(width, 6, 7, 9), (6, 8, 9, 5)]) return D
#============================================================================== D = Device('PPE') layer = 1 NOOPC = 2 OPC = 3 # Define global variables xmax = 500 ymax = 500 xmin = 0 ymin = 0 xm = (xmax-xmin)/2.0 ym = (ymax-ymin)/2.0 # Cover the entire macro D.add_polygon([(0,0),(xmax,0),(xmax,ymax),(0,ymax) ], layer = 0) ## Place the pattern rec Cross = makeCross(xm,ym,100,10, layer) Cross.rotate(45,center = [xm,ym]) D.add_ref(Cross) # calculate offset due to the cross xoff = math.sqrt(100*50) yoff = math.sqrt(100*50) ## Top left 1 x0 = 10 y0 = ym y0, LS1 = makeLineSpace(x0,y0, 240 - xoff ,10,20,ym + yoff, layer) D.add_ref(LS1)
def computationally_intensive_device(width=10, height=1): D = Device() D.add_polygon([(width, 6, 7, 9), (6, 8, 9, 5)]) time.sleep(1.5) # Pretend we're doing computations for 1.5 seconds here return D
def test_add_polygon1(): D = Device() D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) h = D.hash_geometry(precision=1e-4) assert (h == 'c0629d2a7c557f72fad131ae8260df22c1df2d56')
# reference, which we will label with lowercase letters wg1 and wg2. This # handle will be useful later when we want to move wg1 and wg2 around in D. wg1 = D.add_ref(WG1) wg2 = D.add_ref(WG2) # Alternatively, we can do this all on one line wg3 = D.add_ref(waveguide(width=14, height=3)) quickplot(D) #============================================================================== # Creating polygons #============================================================================== # Create and add a polygon from separate lists of x points and y points # e.g. [(x1, x2, x3, ...), (y1, y2, y3, ...)] poly1 = D.add_polygon([(8, 6, 7, 9), (6, 8, 9, 5)]) # Alternatively, create and add a polygon from a list of points # e.g. [(x1,y1), (x2,y2), (x3,y3), ...] using the same function poly2 = D.add_polygon([(0, 0), (1, 1), (1, 3), (-3, 3)]) quickplot(D) #============================================================================== # Manipulating geometry 1 - Basic movement and rotation #============================================================================== # There are several actions we can take to move and rotate the geometry. These # actions include movement, rotation, and reflection. wg1.move([10, 4]) # Shift the second waveguide we created over by dx = 10, dy = 4
def makeLine(x0,y0,width, height, layer=0): L = Device('line') L.add_polygon([(x0, y0), (x0 + width, y0), (x0 + width, y0+ height), (x0, y0+ height)], layer = layer) return L