RoutePortsAroundCorner
- class picazzo3.container.route_ports.RoutePortsAroundCorner
Routes ports around a corner of the component in a given direction.
- Parameters:
- trace_template: ( PCell and _WaveguideTemplate ), *None allowed*
Template for all ports, defaults to TECH.PCELLS.WG.DEFAULT.When set to None, the waveguide templates of the ports will be used.
- auto_transition: ( bool, bool_ or int )
If True, automatically transition all ports of contents to the given trace template. If False, no transitions are applied, which might lead to a discontinuity in the waveguide. Also, if trace_template is None, no transitions are applied.
- port_labels: ( List with type restriction, allowed types: <class ‘str’> ), *None allowed*
Labels of the ports to be processed. Set to None to process all ports.
- external_port_names: str
Dictionary for remapping of the port names of the contents to the external ports
- contents: PCell
the contents of the container: the child cell
- name: String that contains only ISO/IEC 8859-1 (extended ASCII py3) or pure ASCII (py2) characters
The unique name of the pcell
- Other Parameters:
- bundle: ( PCell ), locked, *None allowed*
bundle of waveguides added to the contents, generated based on the supplied waveguides list
- waveguides: List with type restriction, allowed types: <class ‘ipkiss3.pcell.cell.pcell.PCell’>, locked
- trace_templates: List with type restriction, allowed types: <class ‘ipkiss3.pcell.cell.pcell.PCell’>, locked
list of templates to apply to all ports
Views
- class Layout
- Parameters:
- first_step_spacing: float and number > 0
The spacing between the routes ( in the section after the first bend )
- reference_coordinate_first_step: float
The minimum 1D coordinate of the first bend of the routes
- first_step_direction: List with value restriction, allowed values: [C2(0.000000, 1.000000), C2(0.000000, -1.000000), C2(1.000000, 0.000000), C2(-1.000000, 0.000000)]
The direction to take when rounding the corner. By default it is 90 degrees off the output direction
- target_coordinate: ( float ), *None allowed*
The coordinate where the endpoints of the waveguides are aligned. An x-coordinate when routing toEAST or WEST, a y-coordinate when routing to NORTH or SOUTH. When the waveguides extend beyond thetarget coordinate, the value is ignored.
- max_s_bend_angle: float and ]0.0,90.0]
- spacing: float
spacing between adjacent output waveguides
- align_outputs: ( bool, bool_ or int )
If True, all outputs will be aligned to the outermost waveguide end, even if it extends beyond its target coordinate.
- reference_coordinate: ( float ), *None allowed*
The coordinate where the first waveguide will be aligned. An x-coordinate if routed towards NORTH or SOUTH,a y-coordinate when routed towards EAST or WEST. If not specified, the x or y coordinate of the first port is taken.
- output_direction: List with value restriction, allowed values: [C2(1.000000, 0.000000), C2(-1.000000, 0.000000), C2(0.000000, 1.000000), C2(0.000000, -1.000000)]
direction of the output waveguides. Should be EAST, WEST, NORTH or SOUTH
- area_layer_on: ( bool, bool_ or int )
When True, the waveguide area will be covered by i3.Rectangles on all cover layers.
- routes:
routes along which the waveguides will be generated
- contents_transformation: GenericNoDistortTransform
transformation to apply to the contents
- flatten_contents: ( bool, bool_ or int )
if True, it will insert the contents as elements in the layout, rather than as an Instance
- view_name: String that contains only alphanumeric characters from the ASCII set or contains _$. ASCII set is extended on PY3.
The name of the view
- manhattan: ( bool, bool_ or int )
Adds rectangular blocks in the bends to avoid as much as possible non-manhattan angles.
- angle_step: float and number > 0
Angle step for rounding.
- rounding_algorithm:
Rounding algorithm used to generate the bends. Can be circular, spline, ….
- bend_radius: float and number > 0
Bend radius for the auto-generated bends.
- Other Parameters:
- target_coordinates: locked
- max_s_bend_angles: locked
- spacings_from_reference: locked
Examples
import si_fab.all as pdk # noqa: F401 import ipkiss3.all as i3 from picazzo3.filters.ring import RingRect180DropFilter from picazzo3.container.route_ports import RoutePortsAroundCorner def annotate_label(ax, text, pos, **kwargs): ax.annotate( text, xy=pos, horizontalalignment="center", verticalalignment="center", xytext=pos, **kwargs ) def annotate_direction(ax, text, direction=i3.DIRECTION.NORTH, pos=(0.0, 0.0), **kwargs): kws = { "ha": "center", "va": "center", "rotation": i3.angle_deg(direction), "bbox": { "boxstyle": "rarrow,pad=0.3", "fc": "white", }, "size": 15, } kws.update(kwargs) return ax.text(pos[0], pos[1], text, **kws) def annotate_distance( ax, text, start=(0.0, 0.0), end=(0.0, 10.0), offset=0.0, offset_direction=i3.DIRECTION.EAST, **kwargs ): start = (offset_direction * offset) + start end = (offset_direction * offset) + end ax.annotate( "", xy=tuple(start), xycoords="data", xytext=tuple(end), textcoords="data", arrowprops={"arrowstyle": "<->"}, ) text_pos = tuple((e + s) / 2.0 for e, s in zip(start, end)) if len(text) > 0: ax.annotate(text, xy=text_pos, xytext=text_pos, xycoords="data", textcoords="data") def annotate_y(ax, y, label="", **kwargs): return ax.axhline(y, linestyle="dashed", label=label, **kwargs) def annotate_x(ax, x, label="", **kwargs): return ax.axvline(x, linestyle="dashed", label=label, **kwargs) def annotate( ax, output_direction=None, size_info=None, first_step_direction=None, first_step_spacing=None, reference_coordinate=None, reference_coordinate_first_step=None, target_coordinate=None, spacing=None, ports=None, ): annotate_label(ax, "contents", (0.0, 0.0), bbox={"fc": "white", "boxstyle": "round", "ec": "black"}) legend_handles = [] legend_labels = [] if first_step_direction is not None: pos = (size_info.west - 10.0, (size_info.south + size_info.north) / 2.0) annotate_direction(ax, "first_step_direction", direction=first_step_direction, pos=pos) if output_direction is not None: pos = ((size_info.west + size_info.east) / 2.0, size_info.south - 5.0) annotate_direction(ax, "output_direction", direction=output_direction, pos=pos) if reference_coordinate is not None: legend_handles.append(annotate_y(ax, reference_coordinate, label="reference_coordinate", c="r")) legend_labels.append("reference_coordinate") if reference_coordinate_first_step is not None: legend_handles.append( annotate_x( ax, reference_coordinate_first_step, label="reference_coordinate_first_step", c="black" ) ) legend_labels.append("reference_coordinate_first_step") if target_coordinate is not None: legend_handles.append(annotate_x(ax, target_coordinate, label="target_coordinate")) legend_labels.append("target_coordinate") if spacing is not None: end = tuple(ports.east_ports[0].position) start = tuple(ports.east_ports[1].position) annotate_distance(ax, f"spacing = {spacing}", start=start, end=end, offset=1.0) ax.legend(legend_handles, legend_labels) def visualize_routearoundports(layout): size_info = layout.size_info() margin = 15.0 west_margin, east_margin, south_margin, north_margin = [margin] * 4 box = ( size_info.west - west_margin, size_info.east + east_margin, size_info.south - south_margin, size_info.north + north_margin, ) fig = layout.visualize(show=False, box=box, canvas_size=(1000.0, 1000.0)) ax = fig.get_axes()[-1] ax.set_aspect("equal", "datalim") annotate( ax, reference_coordinate=layout.reference_coordinate, reference_coordinate_first_step=layout.reference_coordinate_first_step, first_step_spacing=layout.first_step_spacing, target_coordinate=layout.target_coordinate, first_step_direction=layout.first_step_direction, spacing=layout.spacing, output_direction=layout.output_direction, ports=layout.ports, size_info=size_info, ) from matplotlib.pyplot import show show() my_ring = RingRect180DropFilter() my_ring_routed = RoutePortsAroundCorner(contents=my_ring, port_labels=["W1", "W0"]) # ports to be routed layout = my_ring_routed.Layout( first_step_direction=i3.DIRECTION.SOUTH, # when rounding corner, go this direction first output_direction=i3.DIRECTION.EAST, # final output direction target_coordinate=30.0, reference_coordinate_first_step=-20.0, first_step_spacing=15.0, # Spacing between the waveguides. ) visualize_routearoundports(layout)
import si_fab.all as pdk # noqa: F401 import ipkiss3.all as i3 from picazzo3.filters.ring import RingRect180DropFilter from picazzo3.container.route_ports import RoutePortsAroundCorner my_ring = RingRect180DropFilter() my_ring_routed = RoutePortsAroundCorner(contents=my_ring, port_labels=["W1", "W0"]) # ports to be routed layout = my_ring_routed.Layout( first_step_direction=i3.DIRECTION.SOUTH, # when rounding corner, go this direction first output_direction=i3.DIRECTION.EAST, # final output direction first_step_spacing=8.0, # Spacing between the waveguides. ) layout.visualize(annotate=True)
"""By default, the area between the routes is drawn, you can override this using the area_layer_on parameter""" import si_fab.all as pdk # noqa: F401 import ipkiss3.all as i3 from picazzo3.filters.ring import RingRect180DropFilter from picazzo3.container.route_ports import RoutePortsAroundCorner my_ring = RingRect180DropFilter() my_ring_routed = RoutePortsAroundCorner(contents=my_ring, port_labels=["W1", "W0"]) # ports to be routed layout = my_ring_routed.Layout( first_step_direction=i3.DIRECTION.SOUTH, # when rounding corner, go this direction first output_direction=i3.DIRECTION.EAST, # final output direction area_layer_on=False, first_step_spacing=8.0, # Spacing between the waveguides. ) layout.visualize(annotate=True)
"""Instead of E0, W0, E1, (east 0, west 0 ) ... we can also use the actual port names as port labels""" import si_fab.all as pdk # noqa: F401 import ipkiss3.all as i3 from picazzo3.filters.ring import RingRect180DropFilter from picazzo3.container.route_ports import RoutePortsAroundCorner my_ring = RingRect180DropFilter() my_ring_routed = RoutePortsAroundCorner(contents=my_ring, port_labels=["in1", "out2"]) # ports to be routed layout = my_ring_routed.Layout( first_step_direction=i3.DIRECTION.SOUTH, # when rounding corner, go this direction first output_direction=i3.DIRECTION.EAST, # final output direction first_step_spacing=8.0, # Spacing between the waveguides. ) layout.visualize(annotate=True)
"""Be aware that the order of the port_labels is used to determine to the order of the created routes. If you encounter crossing routes, you might want to change the order of the labels""" import si_fab.all as pdk # noqa: F401 import ipkiss3.all as i3 from picazzo3.filters.ring import RingRect180DropFilter from picazzo3.container.route_ports import RoutePortsAroundCorner my_ring = RingRect180DropFilter() layout = my_ring.Layout() # We first route the E0 (east0 ) port, if we had chosen # ['W1', 'W0', 'E0'] this would have resulted in crossing waveguides my_ring = RoutePortsAroundCorner(contents=layout, port_labels=["E0", "W1", "W0"]) layout = my_ring.Layout( first_step_direction=i3.DIRECTION.SOUTH, # when rounding corner, go this direction first output_direction=i3.DIRECTION.EAST, # final output direction reference_coordinate_first_step=-20.0, first_step_spacing=8.0, # Spacing between the waveguides. ) layout.visualize(annotate=True)
"""As most containers, RoutePortsAroundCorner supports auto transitions. This means that you can choose a trace template for the routes that's different from the one used in the contents. """ import si_fab.all as pdk # noqa: F401 import ipkiss3.all as i3 from picazzo3.filters.ring import RingRect180DropFilter from picazzo3.container.route_ports import RoutePortsAroundCorner from picazzo3.traces.wire_wg import WireWaveguideTemplate my_ring = RingRect180DropFilter() my_ring.Layout() wtpl = WireWaveguideTemplate() wtpl.Layout(core_width=0.7) my_ring = RoutePortsAroundCorner( trace_template=wtpl, auto_transition=True, contents=my_ring, port_labels=["E0", "W1", "W0"] ) layout = my_ring.Layout( first_step_direction=i3.DIRECTION.SOUTH, # when rounding corner, go this direction first output_direction=i3.DIRECTION.EAST, # final output direction reference_coordinate_first_step=-20.0, target_coordinate=40.0, first_step_spacing=8.0, # Spacing between the waveguides. ) layout.visualize(annotate=True)
"""The target_coordinate parameter can be used to specify the 'target coordinate' of the routes. This is illustrated in this example""" import si_fab.all as pdk # noqa: F401 import ipkiss3.all as i3 from picazzo3.filters.ring import RingRect180DropFilter from picazzo3.container.route_ports import RoutePortsAroundCorner my_ring = RingRect180DropFilter() layout = my_ring.Layout() # We first route the E0 (east0 ) port, if we had chosen # ['W1', 'W0', 'E0'] this would have resulted in crossing waveguides my_ring = RoutePortsAroundCorner(contents=layout, port_labels=["E0", "W1", "W0"]) layout = my_ring.Layout( first_step_direction=i3.DIRECTION.SOUTH, # when rounding corner, go this direction first output_direction=i3.DIRECTION.EAST, # final output direction reference_coordinate_first_step=-20.0, target_coordinate=40.0, first_step_spacing=8.0, # Spacing between the waveguides. ) layout.visualize(annotate=True)