Exemplo n.º 1
0
    def marker_positions(self):
        center_port = Port(self._origin, self._angle, 1.)

        angle = max((2 + max(self._in_ports, self._out_ports)) / 2. *
                    self._angular_spacing, np.pi / 4)
        radius = max(self._radius, 40)
        return [
            center_port.rotated(angle).longitudinal_offset(radius).origin,
            center_port.rotated(angle).longitudinal_offset(-radius).origin,
            center_port.rotated(-angle).longitudinal_offset(radius).origin,
            center_port.rotated(-angle).longitudinal_offset(-radius).origin
        ]
Exemplo n.º 2
0
class Spiral:
    def __init__(self, origin, angle, width, num, gap, inner_gap):
        """
        Creates a Spiral around the given origin

        :param origin: position of the center of the spiral
        :param angle: angle of the outer two waveguides
        :param width: width of the waveguide
        :param num: number of turns
        :param gap: gap between two waveguides
        :param inner_gap: inner radius of the spiral
        """
        self._origin_port = Port(origin, angle, width)
        self.gap = gap
        self.inner_gap = inner_gap
        self.num = num
        self.wg_in = None
        self.wg_out = None

    @classmethod
    def make_at_port(cls, port, num, gap, inner_gap, **kwargs):
        default_port_param = dict(port.get_parameters())
        default_port_param.update(kwargs)
        del default_port_param['origin']
        del default_port_param['angle']
        del default_port_param['width']

        return cls(
            port.parallel_offset(-num * (port.width + gap) - inner_gap).origin,
            port.angle, port.width, num, gap, inner_gap, **default_port_param)

    ###
    # Let's allow the user to change the values
    # hidden in _origin_port. Hence the internal use
    # of a Port is transparent.
    @property
    def origin(self):
        return self._origin_port.origin

    @origin.setter
    def origin(self, origin):
        self._origin_port.origin = origin

    @property
    def angle(self):
        return self._origin_port.angle

    @angle.setter
    def angle(self, angle):
        self._origin_port.angle = angle

    @property
    def width(self):
        return self._origin_port.width

    @width.setter
    def width(self, width):
        self._origin_port.width = width

    @property
    def in_port(self):
        return self._origin_port.inverted_direction.parallel_offset(
            -self.num * (self._origin_port.width + self.gap) - self.inner_gap)

    @property
    def out_port(self):
        return self._origin_port.parallel_offset(
            -self.num * (self._origin_port.width + self.gap) - self.inner_gap)

    @property
    def length(self):
        if not self.wg_in or not self.wg_out:
            self._generate()
        return self.wg_in.length + self.wg_out.length

    def _generate(self):
        def path(a):
            return (self.num * (self.width + self.gap) * np.abs(1 - a) +
                    self.inner_gap) * np.array((np.sin(
                        np.pi * a * self.num), np.cos(np.pi * a * self.num)))

        self.wg_in = Waveguide.make_at_port(self._origin_port)
        self.wg_in.add_parameterized_path(path)

        self.wg_out = Waveguide.make_at_port(
            self._origin_port.inverted_direction)
        self.wg_out.add_parameterized_path(path)

        self.wg_in.add_route_single_circle_to_port(
            self._origin_port.rotated(-np.pi * (self.num % 2)))
        self.wg_in.add_route_single_circle_to_port(self.wg_out.port)

    def get_shapely_object(self):
        if not self.wg_in or not self.wg_out:
            self._generate()
        return geometric_union([self.wg_in, self.wg_out])
Exemplo n.º 3
0
    def _calculate(self, do_in_wgs=True, do_out_wgs=True):
        angular_spacing = self._angular_spacing
        assert angular_spacing * self._out_ports < np.pi, 'Not enough space for output ports'
        assert angular_spacing * self._in_ports < np.pi, 'Not enough space for input ports'

        if do_out_wgs:
            # Do the output side
            out_origin_port = Port(self._origin, self._angle,
                                   1.).longitudinal_offset(
                                       -self._displacement / 2)
            out_fanout_wgs = [
                Waveguide.make_at_port(
                    out_origin_port.rotated(angle).longitudinal_offset(
                        self._radius))
                for angle in (np.arange(self._out_ports) -
                              (self._out_ports - 1) / 2.) * angular_spacing
            ]

            for wg in out_fanout_wgs:
                wg.add_parameterized_path(
                    path=lambda t: [t * self._taper_length,
                                    np.zeros_like(t)],
                    path_derivative=lambda t:
                    [np.ones_like(t) * self._taper_length,
                     np.zeros_like(t)],
                    path_function_supports_numpy=True,
                    width=self._taper_function,
                    **self._taper_options)

            if self._minimal_final_spacing is None:
                for wg in out_fanout_wgs:
                    wg.add_bend(normalize_phase(-wg.angle + self._angle),
                                self._wg_bend_radius)

            else:
                offsets = (
                    np.arange(self._out_ports) -
                    (self._out_ports - 1) / 2.) * self._minimal_final_spacing
                final_port_heights = [
                    out_origin_port.parallel_offset(offset)
                    for offset in offsets
                ]

                for wg, final_port_height, offset in zip(
                        out_fanout_wgs, final_port_heights, offsets):
                    if np.isclose(offset, 0):
                        continue

                    try:
                        wg.add_route_single_circle_to_port(
                            final_port_height.inverted_direction,
                            on_line_only=True)
                    except AssertionError:
                        # No curve possible, use normal bend
                        wg.add_bend(normalize_phase(-wg.angle + self._angle),
                                    self._wg_bend_radius)

            final_ports = [wg.current_port for wg in out_fanout_wgs]
            for wg in out_fanout_wgs:
                wg.add_straight_segment_until_level_of_port(final_ports)
            self._out_wgs = out_fanout_wgs

        if do_in_wgs:
            # Do the input side
            in_origin_port = Port(self._origin, self._angle + np.pi,
                                  1.).longitudinal_offset(-self._displacement /
                                                          2)
            in_fanout_wgs = [
                Waveguide.make_at_port(
                    in_origin_port.rotated(angle).longitudinal_offset(
                        self._radius))
                for angle in (np.arange(self._in_ports) -
                              (self._in_ports - 1) / 2.) * angular_spacing
            ]

            for wg in in_fanout_wgs:
                wg.add_parameterized_path(
                    path=lambda t: [t * self._taper_length,
                                    np.zeros_like(t)],
                    path_derivative=lambda t:
                    [np.ones_like(t) * self._taper_length,
                     np.zeros_like(t)],
                    path_function_supports_numpy=True,
                    width=self._taper_function,
                    **self._taper_options)

            if self._minimal_final_spacing is None:
                for wg in in_fanout_wgs:
                    wg.add_bend(
                        normalize_phase(-wg.angle + self._angle - np.pi),
                        self._wg_bend_radius)

            else:
                offsets = (
                    np.arange(self._in_ports) -
                    (self._in_ports - 1) / 2.) * self._minimal_final_spacing
                final_port_heights = [
                    in_origin_port.parallel_offset(offset)
                    for offset in offsets
                ]

                for wg, final_port_height, offset in zip(
                        in_fanout_wgs, final_port_heights, offsets):
                    if np.isclose(offset, 0):
                        continue

                    # wg.add_route_single_circle_to_port(final_port_height.inverted_direction, on_line_only=True)

                    try:
                        wg.add_route_single_circle_to_port(
                            final_port_height.inverted_direction,
                            on_line_only=True)
                    except AssertionError:
                        # No curve possible, use normal bend
                        wg.add_bend(
                            normalize_phase(-wg.angle + self._angle - np.pi),
                            self._wg_bend_radius)

            final_ports = [wg.current_port for wg in in_fanout_wgs]
            for wg in in_fanout_wgs:
                wg.add_straight_segment_until_level_of_port(final_ports)

            self._in_wgs = in_fanout_wgs