def add_electrical_pads(component: Component, rotation=180, **kwargs): """add compnent with top electrical pads and routes Args: component: Component, pad_spacing: float = 150., pad: Callable = pad, fanout_length: Optional[int] = None, max_y0_optical: None = None, waveguide_separation: float = 4.0, bend_radius: float = 0.1, connected_port_list_ids: None = None, n_ports: int = 1, excluded_ports: List[Any] = [], pad_indices: None = None, route_filter: Callable = connect_elec_waypoints, port_name: str = "W", pad_rotation: int = -90, x_pad_offset: int = 0, port_labels: None = None, select_ports: Callable = select_electrical_ports, """ c = Component(f"{component.name}_pad") cr = rotate(component, rotation) elements, pads, _ = route_pad_array( component=cr, **kwargs, ) c << cr for e in elements: c.add(e) for e in pads: c.add(e) for pname, p in cr.ports.items(): if p.port_type == "optical": c.add_port(pname, port=p) return c.rotate(angle=-rotation)
def grating_coupler_uniform( num_teeth: int = 20, period: float = 0.75, fill_factor: float = 0.5, width_grating: float = 11.0, length_taper: float = 150.0, width: float = 0.5, partial_etch: bool = False, layer: Tuple[int, int] = pp.LAYER.WG, layer_partial_etch: Tuple[int, int] = pp.LAYER.SLAB150, polarization="te", wavelength=1500, ) -> Component: """Grating coupler uniform Args: num_teeth: 20 period: 0.75 fill_factor: 0.5 width_grating: 11 length_taper: 150 width: 0.5 partial_etch: False .. plot:: :include-source: import pp c = pp.c.grating_coupler_uniform() pp.plotgds(c) """ # returns a fiber grating G = Component() if partial_etch: partetch_overhang = 5 _compass = compass( size=[period * (1 - fill_factor), width_grating + partetch_overhang * 2], layer=layer_partial_etch, ) # make the etched areas (opposite to teeth) for i in range(num_teeth): cgrating = G.add_ref(_compass) cgrating.x += i * period # draw the deep etched square around the grating deepbox = G.add_ref( compass(size=[num_teeth * period, width_grating], layer=layer) ) deepbox.movex(num_teeth * period / 2) else: for i in range(num_teeth): cgrating = G.add_ref( compass(size=[period * fill_factor, width_grating], layer=layer) ) cgrating.x += i * period # make the taper tgrating = G.add_ref( taper( length=length_taper, width1=width_grating, width2=width, port=None, layer=layer, ) ) tgrating.xmin = cgrating.xmax G.add_port(port=tgrating.ports["2"], name="W0") G.polarization = polarization G.wavelength = wavelength G.rotate(180) return G
def route_fiber_single( component: Component, optical_io_spacing: int = 50, grating_coupler: Component = grating_coupler_te, min_input2output_spacing: int = 230, optical_routing_type: int = 1, optical_port_labels: Optional[List[str]] = None, excluded_ports: Optional[List[str]] = None, **kwargs ) -> Tuple[List[Union[ComponentReference, Label]], List[ComponentReference]]: """Returns routes with grating couplers for single fiber input/output. Args: component: to add grating couplers optical_io_spacing: between grating couplers grating_coupler: min_input2output_spacing: so opposite fibers do not touch optical_routing_type: 0, 1, 2 optical_port_labels: port labels that need connection excluded_ports: ports excluded from routing Returns: elements: list of routes ComponentReference grating_couplers: list of grating_couplers ComponentReferences """ component = component.copy() component_copy = component.copy() if optical_port_labels is None: optical_ports = component.get_ports_list(port_type="optical") else: optical_ports = [component.ports[lbl] for lbl in optical_port_labels] excluded_ports = excluded_ports or [] optical_ports = [p for p in optical_ports if p.name not in excluded_ports] N = len(optical_ports) if isinstance(grating_coupler, list): grating_couplers = [pp.call_if_func(g) for g in grating_coupler] grating_coupler = grating_couplers[0] else: grating_coupler = pp.call_if_func(grating_coupler) grating_couplers = [grating_coupler] * N gc_port2center = getattr(grating_coupler, "port2center", grating_coupler.xsize / 2) if component.xsize + 2 * gc_port2center < min_input2output_spacing: fanout_length = (pp.drc.snap_to_grid( min_input2output_spacing - component.xsize - 2 * gc_port2center, 10) / 2) else: fanout_length = None """ _________ | |_E1 W0_| | | |_E0 |_________| rotate +90 deg and route West ports to South E1 E0 _|___|_ | | | | | | | | | | | | |_______| | W0 """ # route west ports to south component = component.rotate(90) west_ports = component.get_ports_dict(prefix="W") north_ports = { p.name: p for p in component.ports.values() if not p.name.startswith("W") } component.ports = west_ports elements_south, gratings_south, _ = route_fiber_array( component=component, with_align_ports=False, optical_io_spacing=optical_io_spacing, fanout_length=fanout_length, grating_coupler=grating_couplers[0], optical_routing_type=optical_routing_type, **kwargs) # route north ports component = component_copy.rotate(-90) north_ports = { p.name: p for p in component.ports.values() if not p.name.startswith("W") } component.ports = north_ports elements_north, gratings_north, _ = route_fiber_array( component=component, with_align_ports=False, optical_io_spacing=optical_io_spacing, fanout_length=fanout_length, grating_coupler=grating_couplers[1:], **kwargs) for e in elements_north: elements_south.append(e.rotate(180)) if len(gratings_north) > 0: for io in gratings_north[0]: gratings_south.append(io.rotate(180)) return elements_south, gratings_south