def save_or_visualize(device_name=None, out_file=None): ''' Handles a conditional write to file or send over lyipc connection. The context manager yields a new empty Device. The context block then modifies that device by adding references to it. It does not need to return anything. Back to the context manager, the Device is saved if out_file is not None, or it is sent over ipc Example:: with save_or_visualize(out_file='my_box.gds') as D: r = D << phidl.geometry.rectangle(size=(10, 10), layer=1) r.movex(20) will write the device with a rectangle to a file called 'my_box.gds' and do nothing with lyipc. By changing out_file to None, it will send an ipc load command instead of writing to a permanent file, (Although ipc does write a file to be loaded by klayout, it's name or persistence is not guaranteed.) ''' if device_name is None: CELL = Device() else: CELL = Device(device_name) yield CELL if out_file is None: klayout_quickplot(CELL, 'debugging.gds', fresh=True) else: CELL.write_gds(out_file)
def main(): #---- Example of using the templates---# D = Device() # Make a golden spiral with 1000 grids F = fibonacci(1000) D.add_ref(F) D.write_gds("spiral.gds") # Make a ring resonator D2 = Device() C = makeResonator() D2.add_ref(C) D2.write_gds("resonator.gds")
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)
# We can also label (annotate) our devices, in order to record information # directly into the final GDS file without putting any extra geometry onto any # layer # This label will display in a GDS viewer, but will not be rendered # or printed like the polygons created by the text() D2.add_label(text='First label', position=mwg1.center) D2.add_label('Second label', mwg2.center) # It's very useful for recording information about the devices or layout D2.add_label(text='The x size of this\nlayout is %s' % D2.xsize, position=(D2.xmax, D2.ymax), layer=255) # Again, note we have to write the GDS for it to be visible (view in KLayout) D2.write_gds('MultiMultiWaveguideWithLabels.gds') #============================================================================== # Saving the file as a .gds #============================================================================== D2.write_gds('MultiMultiWaveguideTutorial.gds') # If we want to use different units than micron units, we can do that too. # say instead of microns (1e-6) with nanometer precision (1e-6*1e-3), # we want to use millimeters (1e-3) subdivided onto a 10-micron grid, # our precision would then be (1e-2) so the grid would be (1e-3*1e-2) = 10e-6 D2.write_gds('MultiMultiWaveguideTutorialNewUnits.gds', unit=1e-3, precision=1e-2) #==============================================================================
import phidl.geometry as pg from phidl import quickplot as qp X = Device() X << pg.ellipse(layer = 0) X << pg.ellipse(layer = 1) D = pg.copy_layer(X, layer = 1, new_layer = 2) qp(D) # quickplot the geometry create_image(D, 'copy_layer') # example-import_gds import phidl.geometry as pg from phidl import quickplot as qp D = pg.ellipse() D.write_gds('myoutput.gds') D = pg.import_gds(filename = 'myoutput.gds', cellname = None, flatten = False) qp(D) # quickplot the geometry create_image(D, 'import_gds') # example-preview_layerset import phidl.geometry as pg from phidl import quickplot as qp from phidl import LayerSet lys = LayerSet() lys.add_layer('p', color = 'lightblue', gds_layer = 1, gds_datatype = 0) lys.add_layer('p+', color = 'blue', gds_layer = 2, gds_datatype = 0) lys.add_layer('p++', color = 'darkblue', gds_layer = 3, gds_datatype = 0) lys.add_layer('n', color = 'lightgreen', gds_layer = 4, gds_datatype = 0) lys.add_layer('n+', color = 'green', gds_layer = 4, gds_datatype = 98)
t = D2.add_ref(pg.text('Hello\nworld!', size=10, justify='center')) t.move([0, 40]).rotate(45) quickplot(D2) #============================================================================== # Labeling #============================================================================== # This label will display in a GDS viewer, but will not be rendered # or printed like the polygons created by the text() D2.label('First label', mwg1.center) D2.label('Second label', mwg2.center) #============================================================================== # Saving the file as a .gds #============================================================================== D2.write_gds('MultiMultiWaveguideTutorial.gds') #============================================================================== # Using Layers #============================================================================== # Let's make a new blank device DL and add some text to it, but this time on # different layers DL = Device() # You can specify any layer in one of three ways: # 1) as a single number 0-255 representing the gds layer number, e.g. layer = 1 # where the gds layer datatype will be automatically set to zero DL.add_ref(pg.text('Layer1', size=10, layer=1)) # 2) as a 2-element list [0,1] or tuple (0,1) representing the gds layer # number (0-255) and gds layer datatype (0-255)
#side_e_width pad_m = 1.5 * mm #RF pads n_rf = 4 #number of RF pobres spacing = 300 xoff = chip_width - (n_rf * 2 * spacing - pad) - pad_m yoff = height - pad #-pad/2 #Initial device setup D = Device('mac') D << pg.rectangle(size=(chip_width, height), layer=0) L = pg.text(text='MAC CHIP REV # 0', size=40, layer=30, justify='center') D.add_ref(L).move((1.8 * mm, yoff)) D.write_gds('mac_0.gds') # Length matching math and constants # In[3]: #Lower arm (a and phi) path lengths a_to_phi = 450.934996607 * um phi_len = 14 * mm - 0.169 * um phi_to_co = 15603.1440005 * um c_leg = 5.00436311264 #upper arm (b*c) path lengths b_to_c = 314.158991993 * um c_len = c_leg + 40 + c_leg + 14174.808 + c_leg + 40 + c_leg c_to_co = 15208.0394995 + 200
## Lower left 1 x0 = 10 y0 = 0 y0, LS3 = makeLineSpace(x0,y0,240,10,30,xm - yoff, layer) D.add_ref(LS3) ## Lower left 2 x0 = 10 y0 = y0 y0, LS3 = makeLineSpace(x0,y0,240 - xoff ,10,30,240, layer) D.add_ref(LS3) ## Lower right 1 x0 = xm + 10 y0 = 0 y0, LS4 = makeLineSpace(x0,y0,240,10,20,xm - yoff, layer) D.add_ref(LS4) ## Lower right 2 x0 = xm + xoff y0 = y0 y0, LS4 = makeLineSpace(x0,y0,240 - xoff + 10 ,10,20,240, layer) D.add_ref(LS4) # Add NOOPC cover on the pattern rec xt = xoff - 10 yt = yoff - 10 D.add_polygon([(xm-xt,ym-yt), (xm-xt,ym+yt), (xm+xt,ym+yt), (xm+xt,ym-yt) ], layer = NOOPC) D.write_gds("ppe.gds")