Beispiel #1
0
def gen_sref(structure, rotation_angle, x_reflection, port_name, position):
    """
    place sref of `port_name` of `structure` at `position`
    # Keep this convention, otherwise phidl port transform won't work
    # 1 ) Mirror
    # 2 ) Rotate
    # 3 ) Move
    """
    position = np.array(position)

    if port_name is None:
        port_position = np.array([0, 0])
    else:
        port_position = structure.ports[port_name].midpoint

    device_ref = pp.ComponentReference(device=structure, origin=(0, 0))

    if x_reflection:  # Vertical mirror: Reflection across x-axis
        y0 = port_position[1]
        device_ref.reflect(p1=(0, y0), p2=(1, y0))

    device_ref.rotate(rotation_angle, center=port_position)

    device_ref.move(port_position, position)

    return device_ref
def gen_sref(
    structure: Component,
    rotation_angle: int,
    x_reflection: bool,
    port_name: str,
    position: ndarray,
) -> ComponentReference:
    """Place reference of `port_name` of `structure` at `position`.

    Keep this convention, otherwise phidl port transform won't work
    - 1 Mirror
    - 2 Rotate
    - 3 Move
    """
    position = np.array(position)

    if port_name is None:
        port_position = np.array([0, 0])
    else:
        port_position = structure.ports[port_name].midpoint

    ref = pp.ComponentReference(component=structure, origin=(0, 0))

    if x_reflection:  # Vertical mirror: Reflection across x-axis
        y0 = port_position[1]
        ref.reflect(p1=(0, y0), p2=(1, y0))

    ref.rotate(rotation_angle, center=port_position)

    ref.move(port_position, position)

    return ref
Beispiel #3
0
def round_corners(
    points,
    bend90,
    straight_factory,
    taper=None,
    straight_factory_fall_back_no_taper=None,
    mirror_straight=False,
    straight_ports=None,
):
    """
    returns a rounded waveguide route from a list of manhattan points
    Args:
        points: manhattan route defined by waypoints
        bend90: the bend to use for 90Deg turns
        straight_factory: the straight factory to use to generate straight portions
        taper: the taper to use in straight portion. If None, no tapering is done
            in straight portions
            
        straight_factory_fall_back_no_taper: factory to use for straights
        in case there is no space to put a pair of tapers
        straight_ports: port names for straights
            If not specified, will use some heuristic to find them
    """
    ## If there is a taper, make sure its length is known
    if taper != None:
        if not "length" in taper.info:
            _taper_ports = list(taper.ports.values())
            taper.info["length"] = _taper_ports[-1].x - _taper_ports[0].x

    if straight_factory_fall_back_no_taper is None:
        straight_factory_fall_back_no_taper = straight_factory

    ## Remove any flat angle, otherwise the algorithm won't work
    points = remove_flat_angles(points)

    cell_tmp_name = "connector_{}".format(uuid.uuid4())

    cell = pp.Component(name=cell_tmp_name)

    points = np.array(points)

    straight_sections = []  # (p0, angle, length)
    p0_straight = points[0]
    p1 = points[1]

    total_length = 0  # Keep track of the total path length

    if "length" in bend90.info:
        bend_length = bend90.info["length"]
    else:
        bend_length = 0

    dp = p1 - p0_straight
    a0 = None
    if _is_vertical(p0_straight, p1):
        if dp[1] > 0:
            a0 = 90
        elif dp[1] < 0:
            a0 = 270
    elif _is_horizontal(p0_straight, p1):
        if dp[0] > 0:
            a0 = 0
        elif dp[0] < 0:
            a0 = 180

    assert a0 != None, "Points should be manhattan, got {} {}".format(
        p0_straight, p1)

    pname_west, pname_north = [p.name for p in _get_bend_ports(bend90)]

    n_o_bends = points.shape[0] - 2
    total_length += n_o_bends * bend_length
    # Add bend sections and record straight-section information
    for i in range(1, points.shape[0] - 1):
        bend_origin, rotation, x_reflection = _get_bend_reference_parameters(
            points[i - 1], points[i], points[i + 1], bend90)

        bend_ref = gen_sref(bend90, rotation, x_reflection, pname_west,
                            bend_origin)
        cell.add(bend_ref)

        straight_sections += [(p0_straight, a0,
                               get_straight_distance(p0_straight,
                                                     bend_origin))]

        p0_straight = bend_ref.ports[pname_north].midpoint
        a0 = bend_ref.ports[pname_north].orientation

    straight_sections += [(p0_straight, a0,
                           get_straight_distance(p0_straight, points[-1]))]

    wg_refs = []
    for straight_origin, angle, length in straight_sections:
        with_taper = False
        wg_width = list(bend90.ports.values())[0].width

        total_length += length

        if taper != None and length > 2 * taper.info["length"] + 1.0:
            length = length - 2 * taper.info["length"]
            with_taper = True

        if with_taper:

            # First taper:
            # Taper starts where straight would have started
            taper_origin = straight_origin

            pname_west, pname_east = [
                p.name for p in _get_straight_ports(taper)
            ]
            taper_ref = taper.ref(position=taper_origin,
                                  port_id=pname_west,
                                  rotation=angle)

            wg_width = taper.ports[pname_east].width

            cell.add(taper_ref)
            wg_refs += [taper_ref]

            # Update start straight position
            straight_origin = taper_ref.ports[pname_east].midpoint

        # Straight waveguide
        if with_taper or taper is None:
            wg = straight_factory(length=length, width=wg_width)
        else:
            wg = straight_factory_fall_back_no_taper(length=length,
                                                     width=wg_width)

        if straight_ports is None:
            straight_ports = [p.name for p in _get_straight_ports(wg)]
        pname_west, pname_east = straight_ports

        wg.move(wg.ports[pname_west], (0, 0))
        wg_ref = pp.ComponentReference(wg)
        if mirror_straight:
            wg_ref.reflect_v(list(wg_ref.ports.values())[0].name)

        wg_ref.rotate(angle)
        wg_ref.move(straight_origin)
        cell.add(wg_ref)
        wg_refs += [wg_ref]

        port_index_out = 1
        if with_taper:
            # Second taper:
            # Origin at end of straight waveguide, starting from east side of taper

            taper_origin = wg_ref.ports[pname_east]
            pname_west, pname_east = [
                p.name for p in _get_straight_ports(taper)
            ]
            taper_ref = taper.ref(position=taper_origin,
                                  port_id=pname_east,
                                  rotation=angle + 180)

            cell.add(taper_ref)
            wg_refs += [taper_ref]
            port_index_out = 0

    cell.add_port(name="input", port=list(wg_refs[0].ports.values())[0])
    cell.add_port(name="output",
                  port=list(wg_refs[-1].ports.values())[port_index_out])
    """
    # Update name with uuid - too expensive to compute geometrical hash every time
    # Prefix with zz to make connectors appear at end of cell lists

    # The geometrical hash lacks caching right now and ends up taking a 
    # lot of time to compute on every single connector
    """

    cell_name = "zz_conn_{}".format(uuid.uuid4())
    cell.name = cell_name
    cell.info["length"] = total_length
    return cell
def round_corners(
    points,
    bend90,
    straight_factory,
    taper=None,
    straight_factory_fall_back_no_taper=None,
    mirror_straight=False,
    straight_ports=None,
):
    """Return dict with reference list with rounded waveguide route from a list of manhattan points.
    Also returns a dict of ports
    As well as settings

    Args:
        points: manhattan route defined by waypoints
        bend90: the bend to use for 90Deg turns
        straight_factory: the straight factory to use to generate straight portions
        taper: taper for straight portions. If None, no tapering
        straight_factory_fall_back_no_taper: factory to use for straights in case there is no space to put a pair of tapers
        mirror_straight: mirror_straight waveguide
        straight_ports: port names for straights. If not specified, will use some heuristic to find them
    """
    references = []
    ports = dict()
    settings = dict()

    # If there is a taper, make sure its length is known
    if taper:
        if "length" not in taper.info:
            _taper_ports = list(taper.ports.values())
            taper.info["length"] = _taper_ports[-1].x - _taper_ports[0].x

    if straight_factory_fall_back_no_taper is None:
        straight_factory_fall_back_no_taper = straight_factory

    # Remove any flat angle, otherwise the algorithm won't work
    points = remove_flat_angles(points)
    points = np.array(points)

    straight_sections = []  # (p0, angle, length)
    p0_straight = points[0]
    p1 = points[1]

    total_length = 0  # Keep track of the total path length

    if "length" in bend90.info:
        bend_length = bend90.info["length"]
    else:
        bend_length = 0

    dp = p1 - p0_straight
    a0 = None
    if _is_vertical(p0_straight, p1):
        if dp[1] > 0:
            a0 = 90
        elif dp[1] < 0:
            a0 = 270
    elif _is_horizontal(p0_straight, p1):
        if dp[0] > 0:
            a0 = 0
        elif dp[0] < 0:
            a0 = 180

    assert a0 is not None, "Points should be manhattan, got {} {}".format(
        p0_straight, p1
    )

    pname_west, pname_north = [p.name for p in _get_bend_ports(bend90)]

    n_o_bends = points.shape[0] - 2
    total_length += n_o_bends * bend_length
    # Add bend sections and record straight-section information
    for i in range(1, points.shape[0] - 1):
        bend_origin, rotation, x_reflection = _get_bend_reference_parameters(
            points[i - 1], points[i], points[i + 1], bend90
        )

        bend_ref = gen_sref(bend90, rotation, x_reflection, pname_west, bend_origin)
        references.append(bend_ref)

        straight_sections += [
            (p0_straight, a0, get_straight_distance(p0_straight, bend_origin))
        ]

        p0_straight = bend_ref.ports[pname_north].midpoint
        a0 = bend_ref.ports[pname_north].orientation

    straight_sections += [
        (p0_straight, a0, get_straight_distance(p0_straight, points[-1]))
    ]

    wg_refs = []
    for straight_origin, angle, length in straight_sections:
        with_taper = False
        wg_width = list(bend90.ports.values())[0].width

        total_length += length

        if taper is not None and length > 2 * taper.info["length"] + 1.0:
            length = length - 2 * taper.info["length"]
            with_taper = True

        if with_taper:
            # Taper starts where straight would have started
            taper_origin = straight_origin

            pname_west, pname_east = [p.name for p in _get_straight_ports(taper)]
            taper_ref = taper.ref(
                position=taper_origin, port_id=pname_west, rotation=angle
            )

            wg_width = taper.ports[pname_east].width

            references.append(taper_ref)
            wg_refs += [taper_ref]

            # Update start straight position
            straight_origin = taper_ref.ports[pname_east].midpoint

        # Straight waveguide
        if with_taper or taper is None:
            wg = straight_factory(length=length, width=wg_width)
        else:
            wg = straight_factory_fall_back_no_taper(length=length, width=wg_width)

        if straight_ports is None:
            straight_ports = [p.name for p in _get_straight_ports(wg)]
        pname_west, pname_east = straight_ports

        wg.move(wg.ports[pname_west], (0, 0))
        wg_ref = pp.ComponentReference(wg)
        if mirror_straight:
            wg_ref.reflect_v(list(wg_ref.ports.values())[0].name)

        wg_ref.rotate(angle)
        wg_ref.move(straight_origin)
        references.append(wg_ref)
        wg_refs += [wg_ref]

        port_index_out = 1
        if with_taper:
            # Second taper:
            # Origin at end of straight waveguide, starting from east side of taper

            taper_origin = wg_ref.ports[pname_east]
            pname_west, pname_east = [p.name for p in _get_straight_ports(taper)]
            taper_ref = taper.ref(
                position=taper_origin, port_id=pname_east, rotation=angle + 180
            )

            references.append(taper_ref)
            wg_refs += [taper_ref]
            port_index_out = 0

    ports["input"] = list(wg_refs[0].ports.values())[0]
    ports["output"] = list(wg_refs[-1].ports.values())[port_index_out]
    settings["length"] = snap_to_1nm_grid(float(total_length))
    return dict(references=references, ports=ports, settings=settings)