def METHOD_NAME(
    sequence: str,
    symbol_to_component: dict[str, tuple[ComponentSpec, str, str]],
    ports_map: dict[str, tuple[str, str]] | None = None,
    port_name1: str = "o1",
    port_name2: str = "o2",
    start_orientation: float = 0.0,
) -> Component:
    """Returns component from ASCII sequence.
    if you prefix a symbol with ! it mirrors the component
    Args:
        sequence: a string or a list of symbols.
        symbol_to_component: maps symbols to (component, input, output).
        ports_map: (optional) extra port mapping using the convention.
            {port_name: (alias_name, port_name)}
        port_name1: input port_name.
        port_name2: output port_name.
        start_orientation: in degrees.
    Returns:
        component: containing the sequence of sub-components
            instantiated and connected together in the sequence order.
    .. plot::
        :include-source:
        import gdsfactory as gf
        bend180 = gf.components.bend_circular180()
        wg_pin = gf.components.straight_pin(length=40)
        wg = gf.components.straight()
        # Define a map between symbols and (component, input port, output port)
        symbol_to_component = {
            "A": (bend180, 'o1', 'o2'),
            "B": (bend180, 'o2', 'o1'),
            "H": (wg_pin, 'o1', 'o2'),
            "-": (wg, 'o1', 'o2'),
        }
        # Each character in the sequence represents a component
        s = "AB-H-H-H-H-BA"
        c = gf.components.component_sequence(sequence=s, symbol_to_component=symbol_to_component)
        c.plot()
    """
    named_references_counter = Counter()
    ports_map = ports_map or {}
    component = Component()
    # Add first component reference and input port
    symbol = sequence[0] if "!" not in sequence[0] else sequence[:2]
    index = 2 if "!" in sequence[0] else 1
    name_start_device, do_flip = parse_component_name(symbol)
    component_input, input_port, prev_port = symbol_to_component[name_start_device]
    named_references_counter.update({name_start_device: 1})
    alias = f"{name_start_device}{named_references_counter[name_start_device]}"
    prev_device = component.add_ref(component_input, alias=alias)
    if do_flip:
        prev_device = _flip_ref(prev_device, input_port)
    prev_device.rotate(angle=start_orientation)
    try:
        component.add_port(name=port_name1, port=prev_device.ports[input_port])
    except KeyError as exc:
        raise KeyError(
            f"{prev_device.parent.name!r} input_port {input_port!r} "
            f"not in {list(prev_device.ports.keys())}"
        ) from exc
    while index < len(sequence):
        s = sequence[index]
        if s == "!":
            # if it's the last character skip
            if index + 1 >= len(sequence):
                index += 1
                continue
            s = sequence[index + 1]
            do_flip = True
            index += 1
        else:
            do_flip = False
        index += 1
        component_i, input_port, next_port = symbol_to_component[s]
        component_i = gf.get_component(component_i)
        named_references_counter.update({s: 1})
        alias = f"{s}{named_references_counter[s]}"
        ref = component.add_ref(component_i, alias=alias)
        if do_flip:
            ref = _flip_ref(ref, input_port)
        try:
            ref.connect(input_port, prev_device.ports[prev_port])
        except KeyError as exc:
            raise KeyError(
                f"{prev_device.parent.name!r} port {prev_port!r} "
                f"not in {list(prev_device.ports.keys())}"
            ) from exc
        prev_device = ref
        prev_port = next_port
    # Deal with edge case where the sequence contains only one component
    if len(sequence) == 1:
        ref = prev_device
        next_port = prev_port
    try:
        component.add_port(name=port_name2, port=ref.ports[next_port])
    except BaseException:
        print(sequence)
        raise
    # Add any extra port specified in ports_map
    for name, (alias, alias_port_name) in ports_map.items():
        component.add_port(name=name, port=component[alias].ports[alias_port_name])
    return component