def staircase( bend90: ComponentOrFactory = bend_euler, length_v: float = 5.0, length_h: float = 5.0, rows: int = 4, straight: ComponentFactory = straight_function, ) -> Component: bend90 = gf.call_if_func(bend90) wgh = straight(length=length_h, width=bend90.ports["o1"].width) wgv = straight(length=length_v, width=bend90.ports["o1"].width) # Define a map between symbols and (component, input port, output port) symbol_to_component = { "A": (bend90, "o1", "o2"), "B": (bend90, "o2", "o1"), "-": (wgh, "o1", "o2"), "|": (wgv, "o1", "o2"), } # Generate the sequence of staircases s = "-A|B" * rows + "-" c = component_sequence(sequence=s, symbol_to_component=symbol_to_component, start_orientation=0) c.info.n_bends = 2 * rows return c
def test_cutback_phase(straight_length: float = 100.0, bend_radius: float = 12.0, n: int = 2) -> Component: """Modulator sections connected by bends""" # Define sub components bend180 = gf.components.bend_circular180(radius=bend_radius) pm_wg = gf.c.straight_pin(length=straight_length, taper=None) wg_short = straight(length=1.0) wg_short2 = straight(length=2.0) wg_heater = gf.c.straight_pin(length=10.0, taper=None) taper = taper_strip_to_ridge() # Define a map between symbols and (component, input port, output port) symbol_to_component = { "I": (taper, "o1", "o2"), "O": (taper, "o2", "o1"), "S": (wg_short, "o1", "o2"), "P": (pm_wg, "o1", "o2"), "A": (bend180, "o1", "o2"), "B": (bend180, "o2", "o1"), "H": (wg_heater, "o1", "o2"), "-": (wg_short2, "o1", "o2"), } # Generate a sequence # This is simply a chain of characters. Each of them represents a component # with a given input and and a given output repeated_sequence = "SIPOSASIPOSB" heater_seq = "-H-H-H-H-" sequence = repeated_sequence * n + "SIPO" + heater_seq component = component_sequence(sequence=sequence, symbol_to_component=symbol_to_component) return component
def cutback_component( component: ComponentFactory = taper_0p5_to_3_l36, cols: int = 4, rows: int = 5, radius: float = 5.0, port1: str = "o1", port2: str = "o2", bend180: ComponentFactory = bend_euler180, straight: ComponentFactory = straight, ) -> Component: """Returns a daisy chain of components for measuring their loss. Args: component: for cutback cols rows radius: for bend port1: name of first optical port port2: name of second optical port bend180: ubend straight: waveguide function to connect both sides """ component = component() if callable(component) else component bendu = bend180(radius=radius) straight_component = straight() # Define a map between symbols and (component, input port, output port) symbol_to_component = { "A": (component, port1, port2), "B": (component, port2, port1), "D": (bendu, "o1", "o2"), "C": (bendu, "o2", "o1"), "-": (straight_component, "o1", "o2"), "_": (straight_component, "o2", "o1"), } # Generate the sequence of staircases s = "" for i in range(rows): s += "AB" * cols s += "D" if i % 2 == 0 else "C" s = s[:-1] s += "-_" for i in range(rows): s += "AB" * cols s += "D" if (i + rows) % 2 == 0 else "C" s = s[:-1] # Create the component from the sequence c = component_sequence(sequence=s, symbol_to_component=symbol_to_component) n = len(s) - 2 c.copy_child_info(component) c.info["components"] = n c.info["parent_name"] = f"loopback_{component.get_parent_name()}_{n}" return c
def cutback_component_mirror( component: ComponentFactory = component_flipped, cols: int = 4, rows: int = 5, radius: int = 10, port1: str = "o2", port2: str = "o1", bend180: ComponentFactory = bend_euler180, straight: ComponentFactory = straight_long, ) -> Component: """Returns a daisy chain of components for measuring their loss. Flips component. Useful when 'o2' is the port that you want to route to Args: component: for cutback cols rows radius: for bend port1: name of first optical port port2: name of second optical port bend180: ubend straight: waveguide function to connect both sides """ component = component() if callable(component) else component bendu = bend180(radius=radius) straight_component = straight() # Define a map between symbols and (component, input port, output port) symbol_to_component = { "A": (component, port1, port2), "B": (component, port2, port1), "D": (bendu, "o1", "o2"), "C": (bendu, "o2", "o1"), "-": (straight_component, "o1", "o2"), "_": (straight_component, "o2", "o1"), } s = "" for i in range(rows): s += "AB" * cols s += "C" if i % 2 == 0 else "D" s = s[:-1] s += "-_" for i in range(rows): s += "AB" * cols s += "D" if (i + rows + 1) % 2 == 0 else "C" s = s[:-1] c = component_sequence(sequence=s, symbol_to_component=symbol_to_component) n = len(s) - 2 c.copy_child_info(component) c.info["components"] = n c.info["parent_name"] = f"loopback_{component.get_parent_name()}_{n}" return c
def cutback_bend(bend90: ComponentOrFactory = bend_euler, straight_length: float = 5.0, rows: int = 6, columns: int = 5, straight: ComponentFactory = straight_function, **kwargs): """Deprecated! use cutback_bend90 instead, which has smaller footprint Args: bend90: straight_length: rows: columns: straight: function for straight keyword args: cross_section: .. code:: this is a column _ _| _| _ this is a row """ bend90 = gf.call_if_func(bend90) straightx = straight(length=straight_length, width=bend90.ports["o1"].width, **kwargs) # Define a map between symbols and (component, input port, output port) symbol_to_component = { "A": (bend90, "o1", "o2"), "B": (bend90, "o2", "o1"), "S": (straightx, "o1", "o2"), } # Generate the sequence of staircases s = "" for i in range(columns): s += "ASBS" * rows s += "ASAS" if i % 2 == 0 else "BSBS" s = s[:-4] c = component_sequence(sequence=s, symbol_to_component=symbol_to_component, start_orientation=90) c.info.n_bends = rows * columns * 2 + columns * 2 - 2 return c
def cutback_bend180( bend180: ComponentOrFactory = bend_euler180, straight_length: float = 5.0, rows: int = 6, columns: int = 6, spacing: int = 3, straight: ComponentFactory = straight_function, ) -> Component: """ .. code:: _ _| |_ this is a row _ this is a column """ bend180 = gf.call_if_func(bend180) straightx = straight(length=straight_length, width=bend180.ports["o1"].width) wg_vertical = straight( length=2 * bend180.size_info.width + straight_length + spacing, width=bend180.ports["o1"].width, ) # Define a map between symbols and (component, input port, output port) symbol_to_component = { "D": (bend180, "o1", "o2"), "C": (bend180, "o2", "o1"), "-": (straightx, "o1", "o2"), "|": (wg_vertical, "o1", "o2"), } # Generate the sequence of staircases s = "" for i in range(columns): if i % 2 == 0: # even row s += "D-C-" * rows + "|" else: s += "C-D-" * rows + "|" s = s[:-1] # Create the component from the sequence c = component_sequence(sequence=s, symbol_to_component=symbol_to_component, start_orientation=0) c.info.n_bends = rows * columns * 2 + columns * 2 - 2 return c
def cutback_bend90( bend90: ComponentOrFactory = bend_euler, straight_length: float = 5.0, rows: int = 6, columns: int = 6, spacing: int = 5, straight: ComponentFactory = straight_function, ) -> Component: """ .. code:: _ |_| | """ bend90 = gf.call_if_func(bend90) straightx = straight(length=straight_length, width=bend90.ports["o1"].width) straight_length = 2 * _get_bend_size(bend90) + spacing + straight_length straighty = straight( length=straight_length, width=bend90.ports["o1"].width, ) # Define a map between symbols and (component, input port, output port) symbol_to_component = { "A": (bend90, "o1", "o2"), "B": (bend90, "o2", "o1"), "-": (straightx, "o1", "o2"), "|": (straighty, "o1", "o2"), } # Generate the sequence of staircases s = "" for i in range(columns): if i % 2 == 0: # even row s += "A-A-B-B-" * rows + "|" else: s += "B-B-A-A-" * rows + "|" s = s[:-1] # Create the component from the sequence c = component_sequence(sequence=s, symbol_to_component=symbol_to_component, start_orientation=0) c.info.n_bends = rows * columns * 4 return c
def test_cutback_pn() -> Component: # Define subcomponents bend_radius = 10.0 bend180 = bend_circular(radius=bend_radius, angle=180) wg = straight(length=5.0) wg_heater = straight_pn(length=50.0) # Define a map between symbols and (component, input port, output port) symbol_to_component = { "A": (bend180, "o1", "o2"), "B": (bend180, "o2", "o1"), "H": (wg_heater, "o1", "o2"), "-": (wg, "o1", "o2"), } # Generate a sequence # This is simply a chain of characters. Each of them represents a component # with a given input and a given output sequence = "AB-H-H-H-H-BA" component = component_sequence(sequence=sequence, symbol_to_component=symbol_to_component) return component
def mzi_arm( length_y_left: float = 0.8, length_y_right: float = 0.8, length_x: float = 0.1, bend: ComponentOrFactory = bend_euler, straight: ComponentFactory = straight_function, straight_x: Optional[ComponentFactory] = None, straight_y: Optional[ComponentFactory] = None, **kwargs, ) -> Component: """Mzi. Args: length_y_left: vertical length length_y_rigth: vertical length length_x: horizontal length bend: 90 degrees bend library straight: straight function straight_x: straight for length_x straight_y: straight for length_y kwargs: cross_section settings .. code:: B__Lx__B | | Ly Lyr | | B B """ bend = bend(**kwargs) straight_y = straight_y or straight straight_x = straight_x or straight straight_x = straight_x(length=length_x, **kwargs) symbol_to_component = { "b": (bend, "o1", "o2"), "B": (bend, "o2", "o1"), "L": (straight_y(length=length_y_left, **kwargs), "o1", "o2"), "R": ( straight_y( length=length_y_right + abs(straight_x.get_ports_ysize(port_type="optical")), **kwargs, ), "o1", "o2", ), "-": (straight_x, "o1", "o2"), } # Each character in the sequence represents a component sequence = "bLB-BRb" c = component_sequence(sequence=sequence, symbol_to_component=symbol_to_component) # Add any electrical ports from aliases for ref_name, ref in c.aliases.items(): c.add_ports(ref.get_ports_list(port_type="electrical"), prefix=ref_name) c.auto_rename_ports() c.info.length_x = float(length_x) c.info.length_xsize = straight_x.get_ports_xsize() return c
def cutback_component( component: ComponentFactory = taper_0p5_to_3_l36, cols: int = 4, rows: int = 5, radius: float = 5.0, port1: str = "o1", port2: str = "o2", bend180: ComponentFactory = bend_euler180, straight: ComponentFactory = straight_function, mirror: bool = False, straight_length: Optional[float] = None, ) -> Component: """Returns a daisy chain of components for measuring their loss. Args: component: for cutback cols rows radius: for bend port1: name of first optical port port2: name of second optical port bend180: ubend straight: waveguide function to connect both sides mirror: Flips component. Useful when 'o2' is the port that you want to route to straight_length: length of the straight section beween cutbacks """ component = component() if callable(component) else component bendu = bend180(radius=radius) straight_component = straight(length=straight_length or radius * 2) # Define a map between symbols and (component, input port, output port) symbol_to_component = { "A": (component, port1, port2), "B": (component, port2, port1), "D": (bendu, "o1", "o2"), "C": (bendu, "o2", "o1"), "-": (straight_component, "o1", "o2"), "_": (straight_component, "o2", "o1"), } # Generate the sequence of staircases s = "" for i in range(rows): s += "AB" * cols if mirror: s += "C" if i % 2 == 0 else "D" else: s += "D" if i % 2 == 0 else "C" s = s[:-1] s += "-_" for i in range(rows): s += "AB" * cols s += "D" if (i + rows) % 2 == 0 else "C" s = s[:-1] seq = component_sequence(sequence=s, symbol_to_component=symbol_to_component) c = gf.Component() ref = c << seq c.add_ports(ref.ports) n = len(s) - 2 c.copy_child_info(component) c.info["components"] = n # c.info["parent_name"] = f"loopback_{component.info_child.name}_{n}" return c