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()