def test_copy_deepcopy(): D = Device() A = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) B = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) a = D << A b1 = D << B b2 = D << B Dcopy = pg.copy(D) Ddeepcopy = pg.deepcopy(D) h = D.hash_geometry(precision=1e-4) assert (h == '0313cd7e58aa265b44dd1ea10265d1088a2f1c6d') h = Dcopy.hash_geometry(precision=1e-4) assert (h == '0313cd7e58aa265b44dd1ea10265d1088a2f1c6d') h = Ddeepcopy.hash_geometry(precision=1e-4) assert (h == '0313cd7e58aa265b44dd1ea10265d1088a2f1c6d') D << pg.ellipse(radii=(12, 5), angle_resolution=2.5, layer=2) h = D.hash_geometry(precision=1e-4) assert (h == '856cedcbbb53312ff839b9fe016996357e658d33') h = Dcopy.hash_geometry(precision=1e-4) assert (h == '0313cd7e58aa265b44dd1ea10265d1088a2f1c6d') h = Ddeepcopy.hash_geometry(precision=1e-4) assert (h == '0313cd7e58aa265b44dd1ea10265d1088a2f1c6d') A.add_ref(pg.ellipse(radii=(12, 5), angle_resolution=2.5, layer=2)) B.add_polygon([[3, 4, 5], [6.7, 8.9, 10.15]], layer=0) h = D.hash_geometry(precision=1e-4) assert (h == 'c007b674e8053c11c877860f0552fff18676b68e') h = Dcopy.hash_geometry(precision=1e-4) assert (h == '2590bd786348ab684616eecdfdbcc9735b156e18') h = Ddeepcopy.hash_geometry(precision=1e-4) assert (h == '0313cd7e58aa265b44dd1ea10265d1088a2f1c6d')
def test_packer(): np.random.seed(5) D_list = [ pg.ellipse(radii=np.random.rand(2) * n + 2).move(np.random.rand(2) * 100 + 2) for n in range(50) ] D_list += [ pg.rectangle(size=np.random.rand(2) * n + 2).move(np.random.rand(2) * 1000 + 2) for n in range(50) ] D_packed_list = pg.packer( D_list, # Must be a list or tuple of Devices spacing=1.25, # Minimum distance between adjacent shapes aspect_ratio=(1, 2), # Shape of the box max_size=( None, None), # Limits the size into which the shapes will be packed density=1.5, sort_by_area=True, # Pre-sorts the shapes by area verbose=False, ) # The function will return a list of packed Devices. If not all the Devices # in D_list can fit in the area `max_size`, it will fill up the first box to # capacity then create another, repeating until all the shapes are packed # into boxes of max_size. (`max_size` can be (None, None)) # of `max_size` as is necessary D = D_packed_list[0] h = D.hash_geometry(precision=1e-4) assert (h == 'd90e43693a5840bdc21eae85f56fdaa57fdb88b2')
def test_offset(): A = pg.cross(length=10, width=3, layer=0) B = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) D = pg.offset([A, B], distance=0.1, join_first=True, precision=0.001, layer=2) h = D.hash_geometry(precision=1e-4) assert (h == 'dea81b4adf9f163577cb4c750342f5f50d4fbb6d')
def test_offset(): A = pg.cross(length=10, width=3, layer=0) B = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) D = pg.offset([A, B], distance=0.1, join_first=True, precision=0.001, max_points=4000, layer=2) h = D.hash_geometry(precision=1e-4) assert (h == 'bd4b9182042522fa00b5ddb49d182523b4bf9eb5')
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_pack(): import phidl.geometry as pg D_list = [pg.ellipse(radii=np.random.rand(2) * n + 2) for n in range(2)] D_list += [pg.rectangle(size=np.random.rand(2) * n + 2) for n in range(2)] D_packed_list = pack( D_list, # Must be a list or tuple of Components spacing=1.25, # Minimum distance between adjacent shapes aspect_ratio=(2, 1), # (width, height) ratio of the rectangular bin max_size=( None, None), # Limits the size into which the shapes will be packed density= 1.05, # Values closer to 1 pack tighter but require more computation sort_by_area=True, # Pre-sorts the shapes by area ) c = D_packed_list[0] # Only one bin was created, so we plot that # print(len(c.get_dependencies())) assert len(c.get_dependencies()) == 4
def _demo(): import pp import phidl.geometry as pg D_list = [pg.ellipse(radii=np.random.rand(2) * n + 2) for n in range(50)] D_list += [pg.rectangle(size=np.random.rand(2) * n + 2) for n in range(50)] D_packed_list = pack( D_list, # Must be a list or tuple of Components spacing=1.25, # Minimum distance between adjacent shapes aspect_ratio=(2, 1), # (width, height) ratio of the rectangular bin max_size=( None, None), # Limits the size into which the shapes will be packed density= 1.05, # Values closer to 1 pack tighter but require more computation sort_by_area=True, # Pre-sorts the shapes by area verbose=False, ) D = D_packed_list[0] # Only one bin was created, so we plot that pp.show(D) # show it in klayout
# 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() G1 = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) G2 = pg.snspd(wire_width=0.2, wire_pitch=0.6, size=(10, 8), layer=2) G3 = pg.rectangle(size=(10, 5), layer=3) g1 = D.add_ref(G1) g2 = D.add_ref(G2) g3 = D.add_ref(G3) g1.xmin = g2.xmax + 5 g3.xmin = g1.xmax + 5 qp(D) # There are dozens of these types of structures. See the /phidl/geometry.py # file for a full geometry list. Note some of the more complex shapes are # experimental and may change with time. # Let's save this file so we can practice importing it in the next step D.write_gds('MyNewGDS.gds')
#============================================================================== # 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)], layer=0) # 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([(-5, 3), (-4, 4), (-4, 6), (-8, 6)], layer=1) # As a third option, use functions from the built-in geometry library # (more examples below in section "Using the built-in geometry library") # and a listing is available at http://phidl.readthedocs.io/ ) D << pg.ellipse(radii=(3, 1.5), layer=1).move([10, -4]) D << pg.cross(length=3, width=0.2, layer=0).move([10, -8]) D << pg.rectangle(size=(4, 2), layer=3).move([-10, -5]) D << pg.litho_steps( line_widths=[.1, .2, .4, .8], line_spacing=1, height=6, layer=0).move( [0, -5]) 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.
qp(D) # quickplot the geometry create_image(D, 'bbox') # example-cross import phidl.geometry as pg from phidl import quickplot as qp D = pg.cross(length = 10, width = 0.5, layer = 0) qp(D) # quickplot the geometry create_image(D, 'cross') # example-ellipse import phidl.geometry as pg from phidl import quickplot as qp D = pg.ellipse(radii = (10,5), angle_resolution = 2.5, layer = 0) create_image(D, 'ellipse') # example-circle import phidl.geometry as pg from phidl import quickplot as qp D = pg.circle(radius = 10, angle_resolution = 2.5, layer = 0) qp(D) # quickplot the geometry create_image(D, 'circle') # example-ring import phidl.geometry as pg from phidl import quickplot as qp D = pg.ring(radius = 5, width = 0.5, angle_resolution = 2.5, layer = 0)
quickplot(DL) DL.write_gds('MultipleLayerText.gds') #============================================================================== # 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() G1 = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) G2 = pg.snspd(wire_width=0.2, wire_pitch=0.6, size=(10, 8), layer=2) G3 = pg.rectangle(size=(10, 5), layer=3) g1 = D.add_ref(G1) g2 = D.add_ref(G2) g3 = D.add_ref(G3) g1.xmin = g2.xmax + 5 g3.xmin = g1.xmax + 5 quickplot(D) # There are dozens of these types of structures. See the /phidl/geometry.py # file for a full geometry list. Note some of the more complex shapes are # experimental and may change with time. # Let's save this file so we can practice importing it in the next step D.write_gds('MyNewGDS.gds')
qp(D) # quickplot the geometry create_image(D, 'bbox') # example-cross import phidl.geometry as pg from phidl import quickplot as qp D = pg.cross(length=10, width=0.5, layer=0) qp(D) # quickplot the geometry create_image(D, 'cross') # example-ellipse import phidl.geometry as pg from phidl import quickplot as qp D = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=0) create_image(D, 'ellipse') # example-circle import phidl.geometry as pg from phidl import quickplot as qp D = pg.circle(radius=10, angle_resolution=2.5, layer=0) qp(D) # quickplot the geometry create_image(D, 'circle') # example-ring import phidl.geometry as pg from phidl import quickplot as qp D = pg.ring(radius=5, width=0.5, angle_resolution=2.5, layer=0)
def test_invert(): A = pg.cross(length=10, width=3, layer=0) B = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) D = pg.invert([A, B], border=4, precision=1e-6, layer=2) h = D.hash_geometry(precision=1e-4) assert (h == 'eed5a4cb31da61a495c9ff4c5dc4d06fe28707aa')
def test_ellipse(): D = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=0) h = D.hash_geometry(precision=1e-4) assert (h == 'f46840e01a8b8d292a23d4c651a064d65c563575')
def test_outline(): A = pg.cross(length=10, width=3, layer=0) B = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) D = pg.outline([A, B], distance=1, precision=1e-6, layer=2) h = D.hash_geometry(precision=1e-4) assert (h == '503522b071080be6c98017cdc616752c1a3d75ce')
def test_boolean(): A = pg.cross(length=10, width=3, layer=0) B = pg.ellipse(radii=(10, 5), angle_resolution=2.5, layer=1) D = pg.boolean(A=A, B=B, operation='and', precision=1e-6, layer=2) h = D.hash_geometry(precision=1e-4) assert (h == 'fcf1d0809488be01480027a5914dfb399faf088c')