def from_phidl(component: Device, **kwargs) -> Component: """Returns gf.Component from a phidl Device or function""" device = call_if_func(component, **kwargs) component = Component(name=device.name) for ref in device.references: new_ref = ComponentReference( component=ref.parent, origin=ref.origin, rotation=ref.rotation, magnification=ref.magnification, x_reflection=ref.x_reflection, ) new_ref.owner = component component.add(new_ref) for alias_name, alias_ref in device.aliases.items(): if alias_ref == ref: component.aliases[alias_name] = new_ref for p in device.ports.values(): component.add_port( port=Port( name=p.name, midpoint=p.midpoint, width=p.width, orientation=p.orientation, parent=p.parent, ) ) for poly in device.polygons: component.add_polygon(poly) for label in device.labels: component.add_label( text=label.text, position=label.position, layer=(label.layer, label.texttype), ) return component
def ring_single_dut(component=taper2, wg_width=0.5, gap=0.2, length_x=4, radius=5, length_y=0, coupler=coupler_ring, straight=straight_function, bend=bend_euler, with_component=True, **kwargs): """Single bus ring made of two couplers (ct: top, cb: bottom) connected with two vertical straights (wyl: left, wyr: right) (Device Under Test) in the middle to extract loss from quality factor Args: with_component: if False changes component for just a straight .. code:: bl-wt-br | | length_y wl component | | --==cb==-- gap length_x """ component = call_if_func(component) assert_on_2nm_grid(gap) coupler = call_if_func(coupler, gap=gap, radius=radius, length_x=length_x, **kwargs) straight_side = call_if_func(straight, width=wg_width, length=length_y + component.xsize, **kwargs) straight_top = call_if_func(straight, width=wg_width, length=length_x, **kwargs) bend = call_if_func(bend, width=wg_width, radius=radius, **kwargs) c = Component() c.component = component cb = c << coupler wl = c << straight_side if with_component: d = c << component else: d = c << straight_side bl = c << bend br = c << bend wt = c << straight_top wl.connect(port="o2", destination=cb.ports["o2"]) bl.connect(port="o2", destination=wl.ports["o1"]) wt.connect(port="o1", destination=bl.ports["o1"]) br.connect(port="o2", destination=wt.ports["o2"]) d.connect(port="o1", destination=br.ports["o1"]) c.add_port("o2", port=cb.ports["o4"]) c.add_port("o1", port=cb.ports["o1"]) c.copy_child_info(component) return c
def ring_single_sample(gap: float = 0.2, radius: float = 10.0, length_x: float = 4.0, length_y: float = 0.010, coupler_ring: ComponentFactory = coupler_ring_function, straight: ComponentFactory = straight_function, bend: Optional[ComponentFactory] = None, cross_section: CrossSectionFactory = strip, **kwargs) -> Component: """Single bus ring made of a ring coupler (cb: bottom) connected with two vertical straights (wl: left, wr: right) two bends (bl, br) and horizontal straight (wg: top) Args: gap: gap between for coupler radius: for the bend and coupler length_x: ring coupler length length_y: vertical straight length coupler_ring: ring coupler function straight: straight function bend: 90 degrees bend function cross_section: kwargs: cross_section settings .. code:: bl-wt-br | | wl wr length_y | | --==cb==-- gap length_x """ assert_on_2nm_grid(gap) coupler_ring_component = (coupler_ring(bend=bend, gap=gap, radius=radius, length_x=length_x, cross_section=cross_section, **kwargs) if callable(coupler_ring) else coupler_ring) straight_side = call_if_func(straight, length=length_y, cross_section=cross_section, **kwargs) straight_top = call_if_func(straight, length=length_x, cross_section=cross_section, **kwargs) bend = bend or bend_euler bend_ref = (bend(radius=radius, cross_section=cross_section, **kwargs) if callable(bend) else bend) c = Component() cb = c << coupler_ring_component wl = c << straight_side wr = c << straight_side bl = c << bend_ref br = c << bend_ref wt = c << straight_top # wt.mirror(p1=(0, 0), p2=(1, 0)) wl.connect(port="o2", destination=cb.ports["o2"]) bl.connect(port="o2", destination=wl.ports["o1"]) wt.connect(port="o2", destination=bl.ports["o1"]) br.connect(port="o2", destination=wt.ports["o1"]) wr.connect(port="o1", destination=br.ports["o1"]) c.add_port("o2", port=cb.ports["o2"]) c.add_port("o1", port=cb.ports["o1"]) return c
def ring_double_heater( gap: float = 0.2, radius: float = 10.0, length_x: float = 0.01, length_y: float = 0.01, coupler_ring: ComponentFactory = coupler_ring_function, straight: ComponentFactory = straight_function, bend: Optional[ComponentFactory] = None, cross_section_heater: gf.types.CrossSectionFactory = gf.cross_section. strip_heater_metal, cross_section: CrossSectionFactory = strip, contact: gf.types.ComponentFactory = contact_heater_m3_mini, port_orientation: int = 90, contact_offset: Float2 = (0, 0), **kwargs) -> Component: """Double bus ring made of two couplers (ct: top, cb: bottom) connected with two vertical straights (sl: left, sr: right) includes heater on top Args: gap: gap between for coupler radius: for the bend and coupler length_x: ring coupler length length_y: vertical straight length coupler_ring: ring coupler function straight: straight function bend: bend function cross_section_heater: cross_section: contact: port_orientation: for electrical ports to promote from contact contact_offset: for each contact kwargs: cross_section settings .. code:: --==ct==-- | | sl sr length_y | | --==cb==-- gap length_x """ assert_on_2nm_grid(gap) coupler_component = (coupler_ring(gap=gap, radius=radius, length_x=length_x, bend=bend, cross_section=cross_section, bend_cross_section=cross_section_heater, **kwargs) if callable(coupler_ring) else coupler_ring) straight_component = call_if_func(straight, length=length_y, cross_section=cross_section_heater, **kwargs) c = Component() cb = c.add_ref(coupler_component) ct = c.add_ref(coupler_component) sl = c.add_ref(straight_component) sr = c.add_ref(straight_component) sl.connect(port="o1", destination=cb.ports["o2"]) ct.connect(port="o3", destination=sl.ports["o2"]) sr.connect(port="o2", destination=ct.ports["o2"]) c.add_port("o1", port=cb.ports["o1"]) c.add_port("o2", port=cb.ports["o4"]) c.add_port("o3", port=ct.ports["o4"]) c.add_port("o4", port=ct.ports["o1"]) c1 = c << contact() c2 = c << contact() c1.xmax = -length_x / 2 + cb.x - contact_offset[0] c2.xmin = +length_x / 2 + cb.x + contact_offset[0] c1.movey(contact_offset[1]) c2.movey(contact_offset[1]) c.add_ports(c1.get_ports_list(orientation=port_orientation), prefix="e1") c.add_ports(c2.get_ports_list(orientation=port_orientation), prefix="e2") c.auto_rename_ports() return c
def add_fiber_single( component: ComponentOrFactory, grating_coupler: ComponentFactory = grating_coupler_te, layer_label: Tuple[int, int] = TECH.layer_label, fiber_spacing: float = TECH.fiber_spacing, bend: ComponentFactory = bend_circular, straight: ComponentFactory = straight, route_filter: Callable = get_route_from_waypoints, min_input_to_output_spacing: float = 200.0, optical_routing_type: int = 2, with_loopback: bool = True, component_name: Optional[str] = None, gc_port_name: str = "o1", get_input_label_text_loopback_function: Callable = get_input_label_text_loopback, get_input_label_text_function: Callable = get_input_label_text, select_ports: Callable = select_ports_optical, cross_section: CrossSectionFactory = strip, **kwargs, ) -> Component: r"""Returns component with grating ports and labels on each port. Can add loopback reference structure next to it. Args: component: to connect grating_coupler: grating coupler instance, function or list of functions layer_label: for test and measurement label fiber_spacing: between outputs bend: bend_circular straight: straight route_filter: max_y0_optical: None with_loopback: True, adds loopback structures straight_separation: 4.0 list_port_labels: None, adds TM labels to port indices in this list connected_port_list_ids: None # only for type 0 optical routing nb_optical_ports_lines: 1 force_manhattan: False excluded_ports: grating_indices: None routing_method: get_route gc_port_name: W0 get_input_labels_function: function to get input labels for grating couplers optical_routing_type: None: autoselection, 0: no extension gc_rotation: -90 component_name: name of component cross_section: **kwargs: cross_section settings .. code:: fiber ______ /| | | / | | | W0| | | | \ | | | | \|_|_|_ | xmin = 0 .. plot:: :include-source: import gdsfactory as gf c = gf.components.crossing() cc = gf.routing.add_fiber_single( component=c, optical_routing_type=0, grating_coupler=gf.components.grating_coupler_elliptical_te, ) cc.plot() """ component = component() if callable(component) else component optical_ports = select_ports(component.ports) optical_ports = list(optical_ports.values()) optical_port_names = [p.name for p in optical_ports] if not optical_ports: raise ValueError(f"No ports for {component.name}") component = component() if callable(component) else component component_name = component_name or component.get_parent_name() gc = grating_coupler = (grating_coupler() if callable(grating_coupler) else grating_coupler) if gc_port_name not in gc.ports: raise ValueError(f"{gc_port_name} not in {list(gc.ports.keys())}") gc_port_to_edge = abs(gc.xmax - gc.ports[gc_port_name].midpoint[0]) c = Component() c.component = component cr = c << component cr.rotate(90) for port in cr.ports.values(): if port.name not in optical_port_names: c.add_port(name=port.name, port=port) if (len(optical_ports) == 2 and abs(optical_ports[0].x - optical_ports[1].x) > min_input_to_output_spacing): grating_coupler = call_if_func(grating_coupler) grating_couplers = [] for port in cr.ports.values(): if port.name in optical_port_names: gc_ref = grating_coupler.ref() gc_ref.connect(gc_port_name, port) grating_couplers.append(gc_ref) elements = get_input_labels( io_gratings=grating_couplers, ordered_ports=list(cr.ports.values()), component_name=component_name, layer_label=layer_label, gc_port_name=gc_port_name, get_input_label_text_function=get_input_label_text_function, ) else: elements, grating_couplers = route_fiber_single( component, fiber_spacing=fiber_spacing, bend=bend, straight=straight, route_filter=route_filter, grating_coupler=grating_coupler, layer_label=layer_label, optical_routing_type=optical_routing_type, min_input_to_output_spacing=min_input_to_output_spacing, gc_port_name=gc_port_name, component_name=component_name, cross_section=cross_section, select_ports=select_ports, **kwargs, ) for e in elements: c.add(e) for gc in grating_couplers: c.add(gc) for i, io_row in enumerate(grating_couplers): if isinstance(io_row, list): for j, io in enumerate(io_row): ports = io.get_ports_list(prefix="vertical") if ports: port = ports[0] c.add_port(f"{port.name}_{i}{j}", port=port) else: ports = io_row.get_ports_list(prefix="vertical") if ports: port = ports[0] c.add_port(f"{port.name}_{i}", port=port) if isinstance(grating_coupler, list): grating_couplers = [call_if_func(g) for g in grating_coupler] grating_coupler = grating_couplers[0] else: grating_coupler = call_if_func(grating_coupler) grating_couplers = [grating_coupler] if with_loopback: length = c.ysize - 2 * gc_port_to_edge wg = c << straight( length=length, cross_section=cross_section, **kwargs) wg.rotate(90) wg.xmax = (c.xmin - fiber_spacing if abs(c.xmin) > abs(fiber_spacing) else c.xmin - fiber_spacing) wg.ymin = c.ymin + gc_port_to_edge gci = c << grating_coupler gco = c << grating_coupler gci.connect(gc_port_name, wg.ports["o1"]) gco.connect(gc_port_name, wg.ports["o2"]) port = wg.ports["o2"] text = get_input_label_text_loopback_function( port=port, gc=grating_coupler, gc_index=0, component_name=component_name) c.add_label( text=text, position=port.midpoint, anchor="o", layer=layer_label, ) port = wg.ports["o1"] text = get_input_label_text_loopback_function( port=port, gc=grating_coupler, gc_index=1, component_name=component_name) c.add_label( text=text, position=port.midpoint, anchor="o", layer=layer_label, ) c.copy_child_info(component) return c
def ring_double(gap: float = 0.2, radius: float = 10.0, length_x: float = 0.01, length_y: float = 0.01, coupler_ring: ComponentFactory = coupler_ring_function, straight: ComponentFactory = straight_function, bend: Optional[ComponentFactory] = None, cross_section: CrossSectionFactory = strip, **kwargs) -> Component: """Double bus ring made of two couplers (ct: top, cb: bottom) connected with two vertical straights (sl: left, sr: right) Args: gap: gap between for coupler radius: for the bend and coupler length_x: ring coupler length length_y: vertical straight length coupler: ring coupler function straight: straight function bend: bend function **kwargs: cross_section settings .. code:: --==ct==-- | | sl sr length_y | | --==cb==-- gap length_x """ assert_on_2nm_grid(gap) coupler_component = (coupler_ring(gap=gap, radius=radius, length_x=length_x, bend=bend, cross_section=cross_section, **kwargs) if callable(coupler_ring) else coupler_ring) straight_component = call_if_func(straight, length=length_y, cross_section=cross_section, **kwargs) c = Component() cb = c.add_ref(coupler_component) ct = c.add_ref(coupler_component) sl = c.add_ref(straight_component) sr = c.add_ref(straight_component) sl.connect(port="o1", destination=cb.ports["o2"]) ct.connect(port="o3", destination=sl.ports["o2"]) sr.connect(port="o2", destination=ct.ports["o2"]) c.add_port("o1", port=cb.ports["o1"]) c.add_port("o2", port=cb.ports["o4"]) c.add_port("o3", port=ct.ports["o4"]) c.add_port("o4", port=ct.ports["o1"]) return c