def difftest(component: Component): """Runs an XOR over a component and makes boolean comparison with a GDS reference. If it runs for the fist time it just stores the GDS reference. raises GeometryDifference if there are differences and show differences in klayout. """ # containers function_name is different from component.name filename = (f"{component.function_name}_{component.name}.gds" if hasattr(component, "function_name") and component.name != component.function_name else f"{component.name}.gds") ref_file = cwd / "gds_ref" / filename run_file = cwd / "gds_run" / filename pp.write_gds(component, gdspath=run_file) if not ref_file.exists(): print(f"Creating GDS reference for {component.name} in {ref_file}") pp.write_gds(component, gdspath=ref_file) try: run_xor(str(ref_file), str(run_file), tolerance=1, verbose=False) except GeometryDifference: diff = gdsdiff(ref_file, run_file) pp.show(diff) raise
def debug(): c = mzi2x2() h0 = c.hash_geometry() gdspath1 = "{}.gds".format(c.name) gdspath2 = "{}_2.gds".format(c.name) gdspath3 = "{}_3.gds".format(c.name) pp.write_gds(c, gdspath1) c1 = pp.import_gds(gdspath1, overwrite_cache=True) c2 = pp.import_gds(gdspath2, overwrite_cache=True) c3 = pp.import_gds(gdspath3, overwrite_cache=True) dbg = False dh1 = hash_cells(c1, {}, dbg=dbg) dh2 = hash_cells(c2, {}, dbg=dbg) dh3 = hash_cells(c3, {}, dbg=dbg) h1 = dh1[c1.name] h2 = dh2[c2.name] h3 = dh3[c3.name] print(h1) print(h2) print(h3) print(h0) print(gdspy.gdsii_hash(gdspath1)) print(gdspy.gdsii_hash(gdspath2)) print(gdspy.gdsii_hash(gdspath3))
def test_mask(precision=1e-9): workspace_folder = CONFIG["samples_path"] / "mask_pack" build_path = workspace_folder / "build" mask_path = build_path / "mask" mask_path.mkdir(parents=True, exist_ok=True) gdspath = mask_path / "sample_mask.gds" markdown_path = gdspath.with_suffix(".md") json_path = gdspath.with_suffix(".json") test_metadata_path = gdspath.with_suffix(".tp.json") components = [spiral_te(length=length) for length in [2, 4, 6]] components += [ coupler_te(length=length, gap=0.2) for length in [10, 20, 30, 40] ] c = pp.pack(components) m = c[0] m.name = "sample_mask" pp.write_gds(m, gdspath) merge_metadata(gdspath=gdspath) assert gdspath.exists() assert markdown_path.exists() assert json_path.exists() assert test_metadata_path.exists() return gdspath
def test_placer(): cwd = pathlib.Path(__file__).parent filepath = cwd / "config.yml" gdspath = cwd / "build" / "mask" / "test_placer.gds" top_level = component_grid_from_yaml(filepath) pp.write_gds(top_level, gdspath) assert gdspath.exists() return gdspath
def test_density(): """ Return ratio of total area on a layer over the bounding box of the component """ import pp layer = (1, 0) c = pp.c.rectangle(size=(4, 2), layer=layer) pp.write_gds(c) area = compute_area(c, layer) assert np.isclose(8, area)
def test_mask(): workspace_folder = pathlib.Path(__file__).parent filepath_yml = workspace_folder / "config.yml" config = load_config(filepath_yml) gdspath = str(config["mask"]["gds"]) top_level = component_grid_from_yaml(config) pp.write_gds(top_level, gdspath) assert config["mask"]["gds"].exists() return gdspath
def mask2(): N = 15 bend_radius = 15 e = [] e.append( ubc.spiral_te( N=N, bend_radius=bend_radius, y_straight_inner_top=0, x_inner_length_cutback=0, )) e.append( ubc.spiral_te( N=N, bend_radius=bend_radius, y_straight_inner_top=30, x_inner_length_cutback=85, )) c = pack(e) m = c[0] m.name = "EBeam_JoaquinMatres_2" add_floorplan(m) gdspath = pp.write_gds(m, precision=1e-9) change_grid_klayout(gdspath) pp.show(m)
def test_wmin_failing(layer=(1, 0)): w = 50 min_width = 50 + 10 # device edges are smaller than min_width c = pp.c.rectangle(size=(w, w), layer=layer) gdspath = pp.write_gds(c, "wmin.gds") # r = check_width(gdspath, min_width=min_width, layer=layer) # print(check_width(gdspath, min_width=min_width, layer=layer)) assert check_width(gdspath, min_width=min_width, layer=layer) == 2 assert check_width(c, min_width=min_width, layer=layer) == 2
def test_wmin_passing(layer=(1, 0)): w = 50 min_width = 50 - 10 # device edges are bigger than the min_width c = pp.c.rectangle(size=(w, w), layer=layer) gdspath = pp.write_gds(c, "wmin.gds") # print(check_width(c, min_width=min_width, layer=layer)) # assert check_width(gdspath, min_width=min_width, layer=layer) is None # assert check_width(c, min_width=min_width, layer=layer) is None assert check_width(gdspath, min_width=min_width, layer=layer) == 0 assert check_width(c, min_width=min_width, layer=layer) == 0
def mask1(): e = [ubc.mzi_te(delta_length=dl) for dl in [9.32, 93.19]] e += [ ubc.ring_single_te(bend_radius=12, gap=gap, length_x=coupling_length) for gap in [0.2] for coupling_length in [2.5, 4.5, 6.5] ] c = pack(e) m = c[0] m.name = "EBeam_JoaquinMatres_1" add_floorplan(m) gdspath = pp.write_gds(m, precision=1e-9) change_grid_klayout(gdspath) pp.show(m)
def show(gds_filename: Union[PosixPath, str], keep_position: bool = True) -> None: """ Show GDS in klayout """ if not os.path.isfile(gds_filename): raise ValueError(f"{gds_filename} does not exist") data = { "gds": os.path.abspath(gds_filename), "keep_position": keep_position, } data_string = json.dumps(data) try: conn = socket.create_connection(("127.0.0.1", 8082), timeout=1.0) data_string = data_string + "\n" data_string = (data_string.encode() if hasattr(data_string, "encode") else data_string) conn.sendall(data_string) conn.close() except socket.error: print( "error sending GDS to klayout. Make sure have Klayout opened and that you have installed klive with `pf install`" ) if __name__ == "__main__": import pp c = pp.c.waveguide() gdspath = pp.write_gds(c) show(gdspath)
ps = gds.fast_boolean(ps, None, "or") """ component """ c = pp.Component() c.length = length c.add_polygon(ps, layer=wg_layer) c.add_port( name="W0", midpoint=(s[0], s[1]), orientation=180, layer=wg_layer, width=wg_width, ) c.add_port( name="E0", midpoint=(e[0], e[1]), orientation=180, layer=wg_layer, width=wg_width, ) return c if __name__ == "__main__": c = spiral_circular(length=1e3, pins=True) print(c.ports) print(c.ports.keys()) print(c.get_ports_array()) pp.show(c) pp.write_gds(c)
def mmi1x2_biased( wg_width=0.5, width_taper=1.0, length_taper=10, length_mmi=5.496, width_mmi=2.5, gap_mmi=0.25, layer=pp.LAYER.WG, ): return mmi1x2( wg_width=pp.bias.width(wg_width), width_taper=pp.bias.width(width_taper), length_taper=length_taper, length_mmi=length_mmi, width_mmi=pp.bias.width(width_mmi), gap_mmi=pp.bias.gap(gap_mmi), layer=layer, ) if __name__ == "__main__": c = mmi1x2(pins=True) print(c.ports) # print(c.get_ports_array()) # c = mmi1x2_biased() # pp.write_to_libary("mmi1x2", width_mmi=10, overwrite=True) # print(c.get_optical_ports()) pp.write_gds(c, pp.CONFIG["gdsdir"] / "mmi1x2.gds") pp.show(c) # print(c.get_settings())
def _demo_waveguide(): c = waveguide() pp.write_gds(c) return c
def _demo_bend(): c = bend_circular() pp.write_gds(c)
gc_port_name="W0", get_input_labels_function=get_input_labels, with_align_ports=False, ): c = pp.routing.add_io_optical( component=component, component_name=component_name, bend_factory=bend_factory, straight_factory=straight_factory, route_filter=route_filter, grating_coupler=grating_coupler, layer_label=layer_label, taper_factory=taper_factory, gc_port_name=gc_port_name, get_input_labels_function=get_input_labels_function, with_align_ports=with_align_ports, ) c = rotate(c, -90) return c if __name__ == "__main__": import ubc # c = gc_te1550() # print(c.ports) c = add_gc(component=ubc.mzi(delta_length=100)) # c = add_gc(component=waveguide()) pp.show(c) pp.write_gds(c, "mzi.gds")
def write( component, session=None, run=True, overwrite=False, dirpath=pp.CONFIG["sp"], height_nm=220, **settings, ): """ writes Sparameters from a gdsfactory component using Lumerical FDTD Args: component: gdsfactory Component session: you can pass a session=lumapi.FDTD() for debugging run: True-> runs Lumerical , False -> only draws simulation overwrite: run even if simulation results already exists dirpath: where to store the simulations height_nm: height layer2nm: dict of {(1, 0): 220} layer2material: dict of {(1, 0): "si"} remove_layers: list of tuples (layers to remove) background_material: for the background port_width: port width (m) port_height: port height (m) port_extension_um: port extension (um) mesh_accuracy: 2 (1: coarse, 2: fine, 3: superfine) zmargin: for the FDTD region 1e-6 (m) ymargin: for the FDTD region 2e-6 (m) wavelength_start: 1.2e-6 (m) wavelength_stop: 1.6e-6 (m) wavelength_points: 500 Return: results: dict(wavelength_nm, S11, S12 ...) after simulation, or if simulation exists and returns the Sparameters directly """ if hasattr(component, "simulation_settings"): settings.update(component.simulation_settings) sim_settings = s = dict( layer2nm=layer2nm, layer2material=layer2material, remove_layers=[pp.LAYER.WGCLAD], background_material="sio2", port_width=3e-6, port_height=1.5e-6, port_extension_um=1, mesh_accuracy=2, zmargin=1e-6, ymargin=2e-6, wavelength_start=1.2e-6, wavelength_stop=1.6e-6, wavelength_points=500, ) for setting in settings.keys(): assert ( setting in s ), f"`{setting}` is not a valid setting ({list(settings.keys())})" s.update(**settings) ss = namedtuple("sim_settings", s.keys())(*s.values()) assert ss.port_width < 5e-6 assert ss.port_height < 5e-6 assert ss.zmargin < 5e-6 assert ss.ymargin < 5e-6 ports = component.ports component.remove_layers(ss.remove_layers) component._bb_valid = False c = pp.extend_ports(component=component, length=ss.port_extension_um) gdspath = pp.write_gds(c) filepath = component.get_sparameters_path(dirpath=dirpath, height_nm=height_nm) filepath_json = filepath.with_suffix(".json") filepath_sim_settings = filepath.with_suffix(".settings.json") filepath_fsp = filepath.with_suffix(".fsp") if run and filepath_json.exists() and not overwrite: return json.loads(open(filepath_json).read()) if not run and session is None: print(""" you need to pass `run=True` flag to run the simulation To debug, you can create a lumerical FDTD session and pass it to the simulator ``` import lumapi s = lumapi.FDTD() import pp c = pp.c.waveguide() # or whatever you want to simulate pp.sp.write(component=c, run=False, session=s) ``` """) pe = ss.port_extension_um * 1e-6 / 2 x_min = c.xmin * 1e-6 + pe x_max = c.xmax * 1e-6 - pe y_min = c.ymin * 1e-6 - ss.ymargin y_max = c.ymax * 1e-6 + ss.ymargin port_orientations = [p.orientation for p in ports.values()] if 90 in port_orientations and len(ports) > 2: y_max = c.ymax * 1e-6 - pe x_max = c.xmax * 1e-6 elif 90 in port_orientations: y_max = c.ymax * 1e-6 - pe x_max = c.xmax * 1e-6 + ss.ymargin z = 0 z_span = 2 * ss.zmargin + max(ss.layer2nm.values()) * 1e-9 import lumapi s = session or lumapi.FDTD(hide=False) s.newproject() s.selectall() s.deleteall() s.addrect( x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max, z=z, z_span=z_span, index=1.5, name="clad", ) material = ss.background_material if material not in materials: raise ValueError(f"{material} not in {list(materials.keys())}") material = materials[material] s.setnamed("clad", "material", material) s.addfdtd( dimension="3D", x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max, z=z, z_span=z_span, mesh_accuracy=ss.mesh_accuracy, use_early_shutoff=True, ) layers = component.get_layers() for layer, nm in ss.layer2nm.items(): if layer not in layers: continue assert layer in ss.layer2material, f"{layer} not in {ss.layer2material.keys()}" material = ss.layer2material[layer] if material not in materials: raise ValueError(f"{material} not in {list(materials.keys())}") material = materials[material] s.gdsimport(str(gdspath), c.name, f"{layer[0]}:{layer[1]}") silicon = f"GDS_LAYER_{layer[0]}:{layer[1]}" s.setnamed(silicon, "z span", nm * 1e-9) s.setnamed(silicon, "material", material) for i, port in enumerate(ports.values()): s.addport() p = f"FDTD::ports::port {i+1}" s.setnamed(p, "x", port.x * 1e-6) s.setnamed(p, "y", port.y * 1e-6) s.setnamed(p, "z span", ss.port_height) deg = int(port.orientation) # assert port.orientation in [0, 90, 180, 270], f"{port.orientation} needs to be [0, 90, 180, 270]" if -45 <= deg <= 45: direction = "Backward" injection_axis = "x-axis" dxp = 0 dyp = ss.port_width elif 45 < deg < 90 + 45: direction = "Backward" injection_axis = "y-axis" dxp = ss.port_width dyp = 0 elif 90 + 45 < deg < 180 + 45: direction = "Forward" injection_axis = "x-axis" dxp = 0 dyp = ss.port_width elif 180 + 45 < deg < -45: direction = "Forward" injection_axis = "y-axis" dxp = ss.port_width dyp = 0 else: raise ValueError( f"port {port.name} with orientation {port.orientation} is not a valid" " number ") s.setnamed(p, "direction", direction) s.setnamed(p, "injection axis", injection_axis) s.setnamed(p, "y span", dyp) s.setnamed(p, "x span", dxp) # s.setnamed(p, "theta", deg) s.setnamed(p, "name", port.name) s.setglobalsource("wavelength start", ss.wavelength_start) s.setglobalsource("wavelength stop", ss.wavelength_stop) s.setnamed("FDTD::ports", "monitor frequency points", ss.wavelength_points) if run: s.save(str(filepath_fsp)) s.deletesweep("s-parameter sweep") s.addsweep(3) s.setsweep("s-parameter sweep", "Excite all ports", 0) s.setsweep("S sweep", "auto symmetry", True) s.runsweep("s-parameter sweep") # collect results # S_matrix = s.getsweepresult("s-parameter sweep", "S matrix") sp = s.getsweepresult("s-parameter sweep", "S parameters") # export S-parameter data to file named s_params.dat to be loaded in INTERCONNECT s.exportsweep("s-parameter sweep", str(filepath)) print(f"wrote sparameters to {filepath}") keys = [key for key in sp.keys() if key.startswith("S")] ra = { f"{key}a": list(np.unwrap(np.angle(sp[key].flatten()))) for key in keys } rm = {f"{key}m": list(np.abs(sp[key].flatten())) for key in keys} results = {"wavelength_nm": list(sp["lambda"].flatten() * 1e9)} results.update(ra) results.update(rm) with open(filepath_json, "w") as f: json.dump(results, f) with open(filepath_sim_settings, "w") as f: s = sim_settings s["layer2nm"] = [ f"{k[0]}_{k[1]}_{v}" for k, v in s["layer2nm"].items() ] s["layer2material"] = [ f"{k[0]}_{k[1]}_{v}" for k, v in s["layer2material"].items() ] json.dump(s, f) return results
p.name = k elif straight_heater_factory == waveguide: ports_map = { "W0": ("CP1", "W0"), "W1": ("CP1", "W1"), "E0": ("CP2", "E0"), "E1": ("CP2", "E1"), } component = netlist_to_component(components, connections, ports_map) return component def get_mzi_delta_length(m, neff=2.4, wavelength=1.55): """ m*wavelength = neff * delta_length """ return m * wavelength / neff if __name__ == "__main__": import pp # print(get_mzi_delta_length(m=15)) # print(get_mzi_delta_length(m=150)) # c = mzi2x2() c = mzi2x2(straight_heater_factory=waveguide_heater) pp.write_gds(c, 'mzi.gds') pp.show(c)
def test_wire(): c = wire() pp.write_gds(c) return c
def write( component: Component, session: Optional[object] = None, run: bool = True, overwrite: bool = False, dirpath: PosixPath = pp.CONFIG["sp"], **settings, ) -> pd.DataFrame: """Return and write component Sparameters from Lumerical FDTD. if simulation exists and returns the Sparameters directly unless overwrite=False Args: component: gdsfactory Component session: you can pass a session=lumapi.FDTD() for debugging run: True-> runs Lumerical , False -> only draws simulation overwrite: run even if simulation results already exists dirpath: where to store the simulations layer2nm: dict of GDSlayer to thickness (nm) {(1, 0): 220} layer2material: dict of {(1, 0): "si"} remove_layers: list of tuples (layers to remove) background_material: for the background port_width: port width (m) port_height: port height (m) port_extension_um: port extension (um) mesh_accuracy: 2 (1: coarse, 2: fine, 3: superfine) zmargin: for the FDTD region 1e-6 (m) ymargin: for the FDTD region 2e-6 (m) wavelength_start: 1.2e-6 (m) wavelength_stop: 1.6e-6 (m) wavelength_points: 500 Return: Sparameters pandas DataFrame (wavelength_nm, S11m, S11a, S12a ...) suffix `a` for angle and `m` for module """ sim_settings = default_simulation_settings if hasattr(component, "simulation_settings"): sim_settings.update(component.simulation_settings) for setting in sim_settings.keys(): assert ( setting in sim_settings ), f"`{setting}` is not a valid setting ({list(sim_settings.keys())})" for setting in settings.keys(): assert ( setting in sim_settings ), f"`{setting}` is not a valid setting ({list(sim_settings.keys())})" sim_settings.update(**settings) # easier to access dict in a namedtuple `ss.port_width` ss = namedtuple("sim_settings", sim_settings.keys())(*sim_settings.values()) assert ss.port_width < 5e-6 assert ss.port_height < 5e-6 assert ss.zmargin < 5e-6 assert ss.ymargin < 5e-6 ports = component.ports component.remove_layers(ss.remove_layers) component._bb_valid = False c = pp.extend_ports(component=component, length=ss.port_extension_um) gdspath = pp.write_gds(c) layer2material = settings.pop("layer2material", ss.layer2material) layer2nm = settings.pop("layer2nm", ss.layer2nm) filepath = get_sparameters_path( component=component, dirpath=dirpath, layer2material=layer2material, layer2nm=layer2nm, **settings, ) filepath_csv = filepath.with_suffix(".csv") filepath_sim_settings = filepath.with_suffix(".yml") filepath_fsp = filepath.with_suffix(".fsp") if run and filepath_csv.exists() and not overwrite: return pd.read_csv(filepath_csv) if not run and session is None: print(run_false_warning) pe = ss.port_extension_um * 1e-6 / 2 x_min = c.xmin * 1e-6 + pe x_max = c.xmax * 1e-6 - pe y_min = c.ymin * 1e-6 - ss.ymargin y_max = c.ymax * 1e-6 + ss.ymargin port_orientations = [p.orientation for p in ports.values()] if 90 in port_orientations and len(ports) > 2: y_max = c.ymax * 1e-6 - pe x_max = c.xmax * 1e-6 elif 90 in port_orientations: y_max = c.ymax * 1e-6 - pe x_max = c.xmax * 1e-6 + ss.ymargin z = 0 z_span = 2 * ss.zmargin + max(ss.layer2nm.values()) * 1e-9 layers = component.get_layers() sim_settings = dict( simulation_settings=clean_dict(sim_settings, layers), component=component.get_settings(), version=__version__, ) # filepath_sim_settings.write_text(yaml.dump(sim_settings)) # print(filepath_sim_settings) # return try: import lumapi except ModuleNotFoundError as e: print( "Cannot import lumapi (Python Lumerical API). " "You can add set the PYTHONPATH variable or add it with `sys.path.append()`" ) raise e except OSError as e: raise e start = time.time() s = session or lumapi.FDTD(hide=False) s.newproject() s.selectall() s.deleteall() s.addrect( x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max, z=z, z_span=z_span, index=1.5, name="clad", ) material = ss.background_material if material not in materials: raise ValueError(f"{material} not in {list(materials.keys())}") material = materials[material] s.setnamed("clad", "material", material) s.addfdtd( dimension="3D", x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max, z=z, z_span=z_span, mesh_accuracy=ss.mesh_accuracy, use_early_shutoff=True, ) for layer, nm in ss.layer2nm.items(): if layer not in layers: continue assert layer in ss.layer2material, f"{layer} not in {ss.layer2material.keys()}" material = ss.layer2material[layer] if material not in materials: raise ValueError(f"{material} not in {list(materials.keys())}") material = materials[material] s.gdsimport(str(gdspath), c.name, f"{layer[0]}:{layer[1]}") silicon = f"GDS_LAYER_{layer[0]}:{layer[1]}" s.setnamed(silicon, "z span", nm * 1e-9) s.setnamed(silicon, "material", material) for i, port in enumerate(ports.values()): s.addport() p = f"FDTD::ports::port {i+1}" s.setnamed(p, "x", port.x * 1e-6) s.setnamed(p, "y", port.y * 1e-6) s.setnamed(p, "z span", ss.port_height) deg = int(port.orientation) # assert port.orientation in [0, 90, 180, 270], f"{port.orientation} needs to be [0, 90, 180, 270]" if -45 <= deg <= 45: direction = "Backward" injection_axis = "x-axis" dxp = 0 dyp = ss.port_width elif 45 < deg < 90 + 45: direction = "Backward" injection_axis = "y-axis" dxp = ss.port_width dyp = 0 elif 90 + 45 < deg < 180 + 45: direction = "Forward" injection_axis = "x-axis" dxp = 0 dyp = ss.port_width elif 180 + 45 < deg < -45: direction = "Forward" injection_axis = "y-axis" dxp = ss.port_width dyp = 0 else: raise ValueError( f"port {port.name} with orientation {port.orientation} is not a valid" " number ") s.setnamed(p, "direction", direction) s.setnamed(p, "injection axis", injection_axis) s.setnamed(p, "y span", dyp) s.setnamed(p, "x span", dxp) # s.setnamed(p, "theta", deg) s.setnamed(p, "name", port.name) s.setglobalsource("wavelength start", ss.wavelength_start) s.setglobalsource("wavelength stop", ss.wavelength_stop) s.setnamed("FDTD::ports", "monitor frequency points", ss.wavelength_points) if run: s.save(str(filepath_fsp)) s.deletesweep("s-parameter sweep") s.addsweep(3) s.setsweep("s-parameter sweep", "Excite all ports", 0) s.setsweep("S sweep", "auto symmetry", True) s.runsweep("s-parameter sweep") # collect results # S_matrix = s.getsweepresult("s-parameter sweep", "S matrix") sp = s.getsweepresult("s-parameter sweep", "S parameters") # export S-parameter data to file named s_params.dat to be loaded in # INTERCONNECT s.exportsweep("s-parameter sweep", str(filepath)) print(f"wrote sparameters to {filepath}") keys = [key for key in sp.keys() if key.startswith("S")] ra = { f"{key}a": list(np.unwrap(np.angle(sp[key].flatten()))) for key in keys } rm = {f"{key}m": list(np.abs(sp[key].flatten())) for key in keys} wavelength_nm = sp["lambda"].flatten() * 1e9 results = {"wavelength_nm": wavelength_nm} results.update(ra) results.update(rm) df = pd.DataFrame(results, index=wavelength_nm) end = time.time() sim_settings.update(compute_time_seconds=end - start) df.to_csv(filepath_csv, index=False) filepath_sim_settings.write_text(yaml.dump(sim_settings)) return df
def test_type2(): c = pp.c.coupler(gap=0.244, length=5.67) c.polarization = "tm" cc = add_io_optical(c, optical_routing_type=2) pp.write_gds(cc) return cc
from pp.component import Component @pp.autoname def verniers(width_min: float = 0.1, width_max: float = 0.5, gap: float = 0.1, size_max: int = 11) -> Component: c = pp.Component() y = 0 widths = np.linspace(width_min, width_max, int(size_max / (width_max + gap))) for width in widths: w = c << pp.c.waveguide( width=width, length=size_max, layers_cladding=[]) y += width / 2 w.y = y c.add(pp.c.label(str(int(width * 1e3)), position=(0, y))) y += width / 2 + gap return c if __name__ == "__main__": c = verniers() c.flatten() pp.write_gds(c, "verniers.gds") pp.show(c)
def _demo_waveguide_heater(): c = waveguide_heater(width=0.5) pp.write_gds(c)
def test_compute_area(x, y, layer): c = pp.c.rectangle(size=(x, y), layer=layer) pp.write_gds(c) area = pp.drc.compute_area(c, layer) assert np.isclose(area, x * y)
def test_import_gds_hierarchy(): c0 = pp.c.mzi2x2() gdspath = pp.write_gds(c0) c = import_gds(gdspath) assert len(c.get_dependencies()) == 3
def test_type0(): component = pp.c.coupler(gap=0.244, length=5.67) cc = add_fiber_array(component, optical_routing_type=0) pp.write_gds(cc) return cc
def _demo(): c = coupler_straight(gap=0.2) pp.write_gds(c) return c
import pp characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!#()+,-./:;<=>?@[{|}~_" @pp.autoname def alphabet(dx=10): c = pp.Component() x = 0 for s in characters: ci = pp.c.text(text=s) ci.name = s char = c << ci.flatten() char.x = x x += dx return c if __name__ == "__main__": c = alphabet() pp.write_gds(c, "alphabet.gds") pp.show(c)
@pp.autoname def snapping_error(gap=1e-3): c = pp.Component() r1 = c << pp.c.rectangle(size=(1, 1), layer=layer) r2 = c << pp.c.rectangle(size=(1, 1), layer=layer) r1.xmax = 0 r2.xmin = gap return c @pp.autoname def errors(): D_list = [width_min(), gap_min()] c = pp.pack(D_list, spacing=1.5) return c[0] if __name__ == "__main__": # c = width_min() # pp.write_gds(c, "wmin.gds") # c = gap_min() # pp.write_gds(c, "gmin.gds") # c = snapping_error() # pp.write_gds(c, "snap.gds") c = errors() pp.write_gds(c, "errors.gds") pp.show(c)
def test_type1(): component = pp.c.coupler(gap=0.2, length=5.0) cc = add_io_optical(component, optical_routing_type=1) pp.write_gds(cc) return cc