fanout

awg_designer.all.fanout(ports, angle_out, target_point=None, spacings=None, route_params=None)

Return the routes that fanout all the ports to an arbitrary direction angle_out.

If no target_point is provided, fanout will only route to the specified angle_out but does not align the ports (it then uses i3.RouteToAngle). If target_point is provided, it is used as reference for routing the first port, and i3.RouteToLine is used.

In contrast to FanoutPorts, this function only returns the routes. It also is slightly more flexible (arbitrary output angle + not necessarily aligning all outputs). When combined with WaveguideBundle, creates a standalone fanout cell which can then be further used to compose a circuit. Its main use case is as a utility function to build waveguide array bundles.

Parameters:
ports: List

Selection of ports to fanout.

angle_out: float

Angle of all ports after the fanout in degrees.

target_point: i3.Coord2 or list, (optional)

A target point for the fanout of the first port in the selection. If no target_point is defined the ports are routed using i3.RouteToAngle.

spacings: list (optional)

Specifies list of distances between the ports after the fanout. If None, the initial spacing between the ports is preserved.

route_params: dict (optional)

Dictionary of additional parameters that will be passed to i3.RouteToLine (or i3.RouteToAngle).

Returns:
List of routes

Examples

import si_fab.all as pdk
import numpy as np
from ipkiss3 import all as i3
import awg_designer.all as awg
from picazzo3.wg.bundle import WaveguideBundle

def ports_mounting_circular(center, radius, angles, polar_offset=0.):
    tforms = awg.mounting_circular(center, radius, angles)
    zero_port = i3.OpticalPort(position=(0, 0), angle=180)
    ports = [
        zero_port.transform_copy(tform)
        for tform in tforms
    ]

    if polar_offset != 0.:
        for port in ports:
            port.move_polar(polar_offset, port.angle)

    return ports

num_apertures = 5  # number of arms
radius = 50.0      # radius of the port circle
width = 1.0        # aperture width
center = (-radius, 0.0)

# Make a multi-aperture (num_apertures apertures) placed on a circle circle
angle_step = i3.RAD2DEG * 10. * width / radius
angles = np.linspace(
            -angle_step * (num_apertures - 1) / 2.0,
            angle_step * (num_apertures - 1) / 2.0,
            num_apertures
         ) + 180.0

ports = ports_mounting_circular(center, radius, angles)

route_params = {
    'start_straight': 5.0,
    'end_straight': 0.5,
    'min_straight': 0.2,
    'rounding_algorithm': i3.ShapeRound,
    'bend_radius': 5.0,
}
routes = awg.fanout(
    ports,
    angle_out=0.,
    target_point=i3.Coord2(40, -18),
    spacings=[10, 5, 8, 12],
    route_params=route_params,
)

fanout = WaveguideBundle(traces=[
    i3.RoundedWaveguide(trace_template=i3.TECH.PCELLS.WG.WIRE).Layout(shape=rt)
    for rt in routes
]).Layout()
import matplotlib.pyplot as plt

fanout.visualize(show=False)
ax = plt.gca()
xlim = [-15., 55.]
ylim = [-30., 30.]
dx = xlim[1] - xlim[0]
dy = ylim[1] - ylim[0]
ax.set_ylim(*ylim)
ax.set_xlim(*xlim)
linestyle = {
    'linestyle': '--',
    'c': 'k',
    'alpha': 0.6
}
for idx in range(len(ports)):
    print(routes[idx].out_ports[0].position[0], xlim[1])
    print(routes[idx].out_ports[0].position[1])
    xmin = (routes[idx].out_ports[0].position[0] - xlim[0]) / dx
    xmax = 1
    ax.axhline(y=routes[idx].out_ports[0].position[1], xmin=xmin, xmax=xmax, **linestyle)

def _annotate_distance(ax, text, start, end, offset=i3.Coord2(0,0)):
    ax.annotate(
        '',
        xy=tuple(start),
        xycoords='data',
        xytext=tuple(end),
        textcoords='data',
        arrowprops={'arrowstyle': '<->'},
    )
    ax.annotate(
        text,
        xy=tuple(np.array(start + end + offset) / 2.0),
        xytext=tuple(np.array(start + end + offset) / 2.0),
        xycoords='data',
        textcoords='data',
    )

# spacings
_annotate_distance(
    ax,
    'spacings[2]',
    routes[2].out_ports[0].position + i3.Coord2(2, 0),
    routes[3].out_ports[0].position + i3.Coord2(2, 0),
)

# angle_out
start = routes[3].out_ports[0].position
end = start + i3.Coord2(8, 0)
ax.annotate(
    '',
    xy=tuple(end),
    xycoords='data',
    xytext=tuple(start),
    textcoords='data',
    arrowprops={'arrowstyle': '->'},
)
ax.annotate(
    'angle_out',
    xy=tuple(np.array(start + end + i3.Coord2(-3, 5)) / 2.0),
    xytext=tuple(np.array(start + end + i3.Coord2(-3, 5)) / 2.0),
    xycoords='data',
    textcoords='data',
)

ax.scatter(routes[0].out_ports[0].position[0], routes[0].out_ports[0].position[1], color='C1')
ax.annotate(
    'target_point',
    xy=tuple(routes[0].out_ports[0].position + i3.Coord2(1, 2)),
    xytext=tuple(routes[0].out_ports[0].position + i3.Coord2(1, 2)),
    xycoords='data',
    textcoords='data'
)

ax.scatter(ports[0].position[0], ports[0].position[1], color='C1')
ax.annotate(
    'ports[0]',
    xy=tuple(ports[0].position + i3.Coord2(-6, 2)),
    xytext=tuple(ports[0].position + i3.Coord2(-9, 2)),
    xycoords='data',
    textcoords='data'
)

plt.show()
../../../../../_images/awg_designer-all-fanout-2.png