Example #1
0
class __ARef1dElement__(ARef):
    period = DefinitionProperty(fdef_name="define_period")
    n_o_periods = DefinitionProperty(fdef_name="define_n_o_periods")

    period_1d = NumberProperty(default=1.0, restriction=RESTRICT_NONZERO)
    n_o_periods_1d = IntProperty(default=1, restriction=RESTRICT_POSITIVE)

    def __init__(self,
                 reference,
                 origin,
                 period_1d,
                 n_o_periods_1d,
                 transformation=None,
                 **kwargs):
        kwargs["period"] = SUPPRESSED
        kwargs["n_o_periods"] = SUPPRESSED
        super(__ARef1dElement__, self).__init__(reference=reference,
                                                origin=origin,
                                                period_1d=period_1d,
                                                n_o_periods_1d=n_o_periods_1d,
                                                transformation=transformation,
                                                **kwargs)

    def is_empty(self):
        return __RefElement__.is_empty(self) or (self.n_o_periods_1d == 0)
Example #2
0
class ShapeGrow(__ShapeModifier__):
    """ generates a shape with uniformly grows """
    offset = DefinitionProperty(fdef_name="define_offset")
    amount = NumberProperty(required=True)

    def __init__(self, original_shape, amount, **kwargs):
        super(ShapeGrow, self).__init__(original_shape=original_shape,
                                        amount=amount,
                                        **kwargs)

    def is_closed(self):
        return self.original_shape.is_closed()

    closed = FunctionProperty(is_closed, Shape.set_closed)

    def define_offset(self):
        o = self.original_shape.orientation() * self.amount
        return o

    def define_points(self, pts):
        original = Shape(self.original_shape).remove_straight_angles()
        if len(original) <= 1: return

        a2 = original.angles_rad() * 0.5
        a1 = roll(a2, 1)

        a_plus = a2 + a1

        cos_a_min = cos(a2 - a1)
        offsets = column_stack((-sin(a_plus) / cos_a_min,
                                cos(a_plus) / cos_a_min)) * (self.offset)

        # compute offsets from each point
        pts = (original.points + offsets)
        return pts
Example #3
0
class InputBasic(BasicInput):
    scaling = PositiveNumberProperty(default=1.0)
    layer_map = DefinitionProperty()
    prefix = StringProperty(default="")

    def __init__(self, i_stream=sys.stdin, **kwargs):
        super(InputBasic, self).__init__(i_stream=i_stream, **kwargs)
        self.library = None

    def read(self):
        return self.parse()

    def parse(self):
        return self.parse_library()

    def parse_library(self):
        self.library = Library("IMPORT")
        self.__parse_library__()
        return self.library

    def map_layer(self, layer):
        L = self.layer_map.get(layer, None)
        if isinstance(L, __Layer__):
            return L
        elif L is None:
            return L
        else:
            return Layer(L)

    def make_structure_name(self, name):
        return self.prefix + name

    def define_layer_map(self):
        return TECH.GDSII.IMPORT_LAYER_MAP  #FIXME : using 'default' for the property would be better, but that gives an exception ...
Example #4
0
class UnitGridContainer(StrongPropertyInitializer):
    grids_per_unit = DefinitionProperty(fdef_name="define_grids_per_unit")
    units_per_grid = DefinitionProperty(fdef_name="define_units_per_grid")
    unit = PositiveNumberProperty(default=TECH.METRICS.UNIT)
    grid = PositiveNumberProperty(default=TECH.METRICS.GRID)

    def define_grids_per_unit(self):
        return self.unit / self.grid

    def define_units_per_grid(self):
        return self.grid / self.unit

    def validate_properties(self):
        if self.grid > self.unit:
            raise Exception("The grid should be smaller than the unit.")
        return True
Example #5
0
class __ShapeStartEndAngle__(__ShapeModifier__):
    start_face_angle = DefinitionProperty(restriction=RESTRICT_NUMBER,
                                          fdef_name="define_start_face_angle")
    end_face_angle = DefinitionProperty(restriction=RESTRICT_NUMBER,
                                        fdef_name="define_end_face_angle")

    @cache()
    def __get_original_shape_without_straight_angles__(self):
        s = Shape(self.original_shape).remove_straight_angles()
        if self.original_shape.closed:
            if s[-1] != s[0]:
                s.append(s[0])
        return s

    def define_start_face_angle(self):
        s = self.__get_original_shape_without_straight_angles__()
        if not self.original_shape.start_face_angle is None:
            return self.original_shape.start_face_angle
        if len(s) > 1:
            return angle_deg(s[1], s[0])
        else:
            return 0.0

    def define_end_face_angle(self):
        s = self.__get_original_shape_without_straight_angles__()
        if not self.original_shape.end_face_angle is None:
            return self.original_shape.end_face_angle
        if len(s) > 1:
            return angle_deg(s[-1], s[-2])
        else:
            return 0.0

    @cache()
    def get_original_shape_angles_rad(self):
        s = self.__get_original_shape_without_straight_angles__()
        a = s.angles_rad()
        if len(s) < 2:
            return a
        if not s.closed:
            a[0] = self.start_face_angle * DEG2RAD
            a[-1] = self.end_face_angle * DEG2RAD
        return a
Example #6
0
class ShapeEllipse(ShapeEllipseArc):
    """ ellipse """
    start_angle = DefinitionProperty(fdef_name="define_start_angle")
    end_angle = DefinitionProperty(fdef_name="define_end_angle")

    def __init__(self, **kwargs):
        kwargs["closed"] = True
        super(ShapeEllipse, self).__init__(**kwargs)

    def define_start_angle(self):
        sa = 0.0
        return sa

    def define_end_angle(self):
        ea = self.start_angle + 360.0
        return ea

    def define_points(self, pts):
        pts = super(ShapeEllipse, self).define_points(pts)
        return pts
Example #7
0
class ShapeBend(ShapeArc):
    """ bend: circular arc but specified by its starting point insetad of center """
    start_point = Coord2Property(default=(0.0, 0.0))
    center = DefinitionProperty(fdef_name="define_center")
    start_angle = DefinitionProperty(fdef_name="define_start_angle")
    end_angle = DefinitionProperty(fdef_name="define_end_angle")
    input_angle = AngleProperty(default=0.0)
    output_angle = AngleProperty(default=90.0)

    def __init__(self, **kwargs):
        super(ShapeBend, self).__init__(**kwargs)

    def __get_sign(self):
        if self.clockwise:
            sign = -1
        else:
            sign = 1
        return sign

    def define_center(self):
        sign = self.__get_sign()
        c = (self.start_point[0] -
             sign * self.radius * math.sin(self.input_angle * DEG2RAD),
             self.start_point[1] +
             sign * self.radius * math.cos(self.input_angle * DEG2RAD))
        return c

    def define_start_angle(self):
        sign = self.__get_sign()
        a = self.input_angle - sign * 90.0
        return a

    def define_end_angle(self):
        sign = self.__get_sign()
        a = self.output_angle - sign * 90.0
        return a

    def move(self, position):
        self.start_point = Coord2(self.start_point[0] + position[0],
                                  self.start_point[1] + position[1])
        return self
Example #8
0
class ShapeArc(ShapeEllipseArc):
    """ circular arc """
    radius = PositiveNumberProperty(default=1.0)
    box_size = DefinitionProperty(fdef_name="define_box_size")

    def __init__(self, **kwargs):
        ShapeEllipseArc.__init__(self,
                                 **kwargs)  # super gives error -- why? FIXME

    def define_box_size(self):
        bs = Coord2(2 * self.radius, 2 * self.radius)
        return bs
Example #9
0
class BasicInput(StrongPropertyInitializer):
    i_stream = DefinitionProperty(default=sys.stdin)  # add limitation

    def __init__(self, i_stream=sys.stdin, **kwargs):
        super(BasicInput, self).__init__(i_stream=i_stream, **kwargs)

    def read(self, size=None):
        if size is None:
            return self.parse(self.i_stream.read())
        else:
            return self.parse(self.i_stream.read(size))

    def parse(self, item):
        return item
Example #10
0
class ShapeRectangle(ShapeRoundedRectangle):
    """ rectangle """
    radius = DefinitionProperty(fdef_name="define_radius")

    def __init__(self, **kwargs):
        kwargs["closed"] = True
        super(ShapeRectangle, self).__init__(**kwargs)

    def define_radius(self):
        return 0.0

    def define_points(self, pts):
        # overloaded for speed
        cx = self.center[0]
        cy = self.center[1]
        dx = 0.5 * self.box_size[0]
        dy = 0.5 * self.box_size[1]
        pts = [(cx + dx, cy + dy), (cx - dx, cy + dy), (cx - dx, cy - dy),
               (cx + dx, cy - dy)]
        return pts
Example #11
0
class ShapeRoundGeneric(__ShapeModifier__):
    """ returns a shape with rounded corners based on a given shape """

    radii = DefinitionProperty(fdef_name="define_radii")
    original_shape = ShapeProperty(required=True)
    angle_step = AngleProperty(default=TECH.METRICS.ANGLE_STEP)

    def define_radii(self):
        raise NotImplementedException(
            "ShapeRoundGeneric is an abstract class : must implement 'define_radii' in subclass"
        )

    def __original_shape_without_straight_angles__(self, shape, radii):
        S1 = Shape(shape)
        S = Shape(S1).remove_straight_angles()
        R = array(radii)
        straight = (abs(abs((S1.turns_rad() +
                             (0.5 * pi)) % pi) - 0.5 * pi) < 0.00001)
        R = delete(radii, straight.nonzero()[0], 0)
        return (S, R)

    def define_points(self, pts):
        (Swsa, R) = self.__original_shape_without_straight_angles__(
            self.original_shape, self.radii)
        closed = Swsa.closed
        if len(self.radii) != len(Swsa):
            raise IpcoreAttributeException(
                "ShapeRoundGeneric: length of radius vector should be identical to that of points in shape"
            )

        c = Swsa.points
        if len(c) == 0:
            return
        (r, tt, t, a1, a2, L, D) = self.__radii_and_turns__(Swsa)

        # create the bends
        Swsa = c - column_stack(
            (L * cos(a1), L * sin(a1))
        )  # bend start points (whereby we can ignore the 1st and last point for an open shape)

        S = []
        if not closed:
            S.append(array([c[0]]))
        for i in range(1, len(c) - 1):  #ignore first and last point in matrix
            sh = ShapeBendRelative(Swsa[i], r[i], a1[i] * RAD2DEG,
                                   t[i] * RAD2DEG, self.angle_step)
            S.append(sh.points)

        if closed:  #construct first and last bend in case the shape is closed
            sh = ShapeBendRelative(Swsa[-1], r[-1], a1[-1] * RAD2DEG,
                                   t[-1] * RAD2DEG, self.angle_step)
            S.append(sh.points)
            sh = ShapeBendRelative(Swsa[0], r[0], a1[0] * RAD2DEG,
                                   t[0] * RAD2DEG, self.angle_step)
            S.append(sh.points)
            self.closed = True
        else:
            # open curve
            S.append(array([c[-1]]))
            self.closed = False
        pts = vstack(S)
        return pts

    def __radii_and_turns__(self, s):
        R = self.radii
        r = array(R)
        D = s.distances()
        a2 = s.angles_rad()  # angle to next vertex
        a1 = roll(a2, 1)  # angle from previous vertex
        t = (a2 - a1 +
             pi) % (2 * pi) - pi  # turns, save an extra angle computation
        tt = abs(tan(0.5 * t))
        L = R * tt  # length of the straight section consumed by the bend
        (Swsa, dummy) = self.__original_shape_without_straight_angles__(
            self.original_shape, self.radii)
        if not Swsa.closed:
            L[0] = 0
            L[-1] = 0
        # check where the bend consumes more length than possible!
        m_L = ((L + roll(L, -1)) - D)  # missing length in the next segment
        missing_L = amax(column_stack((m_L, roll(m_L, 1))),
                         1)  # missing length over previous and next segment
        overf = (missing_L > 0.5 / settings.get_grids_per_unit())
        r[overf] = 0.5 * (amin(column_stack(
            (D[overf], roll(D, 1)[overf])), 1)) / tt[overf]
        # FIXME: Find a more robust algorithm to reduce the radius if there is insufficient space
        r_difference = R - r
        if (r_difference >
                settings.get_current_library().units_per_grid).any():
            LOG.warning(
                "Bend radius is reduced by maximum %f to round shape." %
                max(r_difference))
        if not Swsa.closed:
            r[0] = 0
            r[-1] = 0
        L = r * tt  # recompute the length of the straight section consumed by the bend
        return (r, tt, t, a1, a2, L, D)

    def length(self):
        import sys
        (Swsa, R) = self.__original_shape_without_straight_angles__(
            self.original_shape, self.radii)
        (r, tt, t, a1, a2, L, D) = self.__radii_and_turns__(Swsa)
        L2 = sum(D) + sum(abs(t) * r - 2 * L)
        if not self.original_shape.closed:
            L2 -= D[-1]
        return L2
Example #12
0
    class Layout(i3.LayoutView):
        # specified parameters used for layout purposes
        ## coupling spacing?
        ## move to the coupler level
        bend_radius = i3.PositiveNumberProperty(
            default=10., doc="bend radius of 90 degree bends")
        in1_offset = i3.PositiveNumberProperty(
            default=10., doc="offset between 90 degree bends input 1")
        in2_offset = i3.PositiveNumberProperty(
            default=10., doc="offset between 90 degree bends input 2")
        out1_offset = i3.PositiveNumberProperty(
            default=1., doc="offset between 90 degree bends output 1")
        out2_offset = i3.PositiveNumberProperty(
            default=1., doc="offset between 90 degree bends output 2")
        rounding_algorithm = DefinitionProperty(
            default=ShapeRound,
            doc="rounding algorithm for every individual bend")

        # define default of tapered MMI child cell
        def _default_coupler(self):
            ### error to be corrected. the Child Layout view needs to point to coupler first, end get the default view
            # wg_template1 = self.wg_template1
            coupler = self.cell.coupler.get_default_view(
                i3.LayoutView)  # Retrieve layout view following examples
            ### go to upper level then to define the waveguide template, as the waveguide template of DC is NOT
            ### defined in layout level
            # self.cell.coupler.trace_template1 = self.wg_template1
            # self.cell.coupler.trace_template2 = self.wg_template2
            return coupler

        # grabbing properties of child cell and setting appropriate transforms, by default do none
        def _get_components(self):
            coupler = i3.SRef(reference=self.coupler, name="coupler")
            return coupler

        # setting the output shape of the access waveguides using a shape defined by ports from MMI (hopefully..)
        def _default_wgs(self):

            # bring in parts from rest of PCell Layout, used to grab positions
            coupler = self._get_components()
            ## wgcell ? for loop operation
            wg_in1_cell, wg_in2_cell, wg_out1_cell, wg_out2_cell = self.cell.wgs
            wg_template1 = self.wg_template1
            wg_template2 = self.wg_template2
            bend_radius = self.bend_radius
            # setting variable for
            round_alg = self.rounding_algorithm

            # defining bottom left waveguide, using port from MMI and bus length
            wg_in1_layout = wg_in1_cell.get_default_view(i3.LayoutView)
            in1_port_pos = coupler.ports["in1"].position
            in1_shape = [
                in1_port_pos, (in1_port_pos[0] - bend_radius, in1_port_pos[1]),
                (in1_port_pos[0] - bend_radius,
                 in1_port_pos[1] - 2. * bend_radius - self.in1_offset),
                (in1_port_pos[0] - 2. * bend_radius,
                 in1_port_pos[1] - 2. * bend_radius - self.in1_offset)
            ]

            wg_in1_layout.set(trace_template=wg_template1,
                              shape=in1_shape,
                              rounding_algorithm=round_alg,
                              bend_radius=bend_radius,
                              manhattan=True)

            # repeat above for other ports, first in2
            wg_in2_layout = wg_in2_cell.get_default_view(i3.LayoutView)
            in2_port_pos = coupler.ports["in2"].position
            in2_shape = [
                in2_port_pos, (in2_port_pos[0] - bend_radius, in2_port_pos[1]),
                (in2_port_pos[0] - bend_radius,
                 in2_port_pos[1] + 2. * bend_radius + self.in2_offset),
                (in2_port_pos[0] - 2. * bend_radius,
                 in2_port_pos[1] + 2. * bend_radius + self.in2_offset)
            ]

            wg_in2_layout.set(trace_template=wg_template2,
                              shape=in2_shape,
                              rounding_algorithm=round_alg,
                              bend_radius=bend_radius,
                              manhattan=True)

            # out1
            wg_out1_layout = wg_out1_cell.get_default_view(i3.LayoutView)
            out1_port_pos = coupler.ports["out1"].position
            out1_shape = [
                out1_port_pos,
                (out1_port_pos[0] + bend_radius, out1_port_pos[1]),
                (out1_port_pos[0] + bend_radius,
                 out1_port_pos[1] - 2. * bend_radius - self.out1_offset),
                (out1_port_pos[0] + 2. * bend_radius,
                 out1_port_pos[1] - 2. * bend_radius - self.out1_offset)
            ]

            wg_out1_layout.set(trace_template=wg_template1,
                               shape=out1_shape,
                               rounding_algorithm=round_alg,
                               bend_radius=bend_radius,
                               manhattan=True)
            # and out2
            wg_out2_layout = wg_out2_cell.get_default_view(i3.LayoutView)
            out2_port_pos = coupler.ports["out2"].position
            out2_shape = [
                out2_port_pos,
                (out2_port_pos[0] + bend_radius, out2_port_pos[1]),
                (out2_port_pos[0] + bend_radius,
                 out2_port_pos[1] + 2. * bend_radius + self.out2_offset),
                (out2_port_pos[0] + 2. * bend_radius,
                 out2_port_pos[1] + 2. * bend_radius + self.out2_offset)
            ]

            wg_out2_layout.set(trace_template=wg_template2,
                               shape=out2_shape,
                               rounding_algorithm=round_alg,
                               bend_radius=bend_radius,
                               manhattan=True)
            # returning layouts
            return wg_in1_layout, wg_in2_layout, wg_out1_layout, wg_out2_layout

        def _generate_instances(self, insts):
            # includes the get components and the new waveguides
            insts += self._get_components()
            wg_in1_layout, wg_in2_layout, wg_out1_layout, wg_out2_layout = self.wgs

            insts += i3.SRef(reference=wg_in1_layout, name="wg_in1")
            insts += i3.SRef(reference=wg_in2_layout, name="wg_in2")
            insts += i3.SRef(reference=wg_out1_layout, name="wg_out1")
            insts += i3.SRef(reference=wg_out2_layout, name="wg_out2")
            return insts

        def _generate_ports(self, prts):
            # use output ports of all waveguides as I define shapes from the base of the coupler structure outwards
            instances = self.instances
            prts += instances["wg_in1"].ports["out"].modified_copy(name="in1")
            prts += instances["wg_in2"].ports["out"].modified_copy(name="in2")
            prts += instances["wg_out1"].ports["out"].modified_copy(
                name="out1")
            prts += instances["wg_out2"].ports["out"].modified_copy(
                name="out2")
            return prts

        ### an simple example to use Ben_Coupler_Symm class
        @i3.example_plot()
        def __example_layout(self):
            from technologies import silicon_photonics
            from picazzo3.traces.wire_wg.trace import WireWaveguideTemplate
            import ipkiss3.all as i3
            import numpy as np
            from euler_rounding_algorithm import Euler90Algorithm
            from SplittersAndCascades import Bent_Coupler_Symm

            # set waveguide templates for
            # the north waveguide (wg_t1)
            # and the south waveguide (wg_t2)
            wg_t1 = WireWaveguideTemplate(name="south_arm")
            wg_t1.Layout(core_width=2.400,
                         cladding_width=i3.TECH.WG.CLADDING_WIDTH,
                         core_process=i3.TECH.PROCESS.WG)

            wg_t2 = WireWaveguideTemplate(name="north arm")
            wg_t2.Layout(core_width=1.500,
                         cladding_width=i3.TECH.WG.CLADDING_WIDTH,
                         core_process=i3.TECH.PROCESS.WG)

            # set the directional coupler (can also be MMI)
            # and then pass it as an child PCell to Bend_Coupler PCell
            C = Bent_Coupler_Symmr(name="my_dircoup_2",
                                   trace_template1=wg_t1,
                                   trace_template2=wg_t2,
                                   coupler_length=20.0)
            layout = C.Layout(bend_radius=10.0,
                              straight_after_bend=6.0,
                              bend_angle=60.0)
            layout.visualize()