Definition of each component class in fnpcell

In the PhotoCAD platform, each parameterizable component is generated by a Python script, which first defines the component as a class containing parameters that can be adjusted by the user, who generates the component by creating an instance of it using the class.

Then the design of the component is customized by adjusting the parameter settings. The following code is intercepted from gpdk > components > bend > bend_bezier.py and belongs to the BendBezier class definition part of the Pcell bend_bezier.

Full script

from functools import cached_property
from typing import Sequence, Tuple

from fnpcell import all as fp
from gpdk.technology import get_technology



class BendBezier(fp.IWaveguideLike, fp.PCell):
    """
    Attributes:
        start: start point of bezier curve
        controls: control points of bezier, 1 for Quadratic Bezier, 2 for Cubic Bezier, ...
        end: end point of bezier curve
        waveguide_type: type of waveguide of the bend
        port_names: defaults to ["op_0", "op_1"]

    Examples:
    ```python
    TECH = get_technology()
        bend = BendBezier(name="q", start=(0, 0), controls=[(31, 30)], end=(60, 0), waveguide_type=TECH.WG.FWG.C.WIRE)
    fp.plot(bend)
    ```
    ![BendBezier](images/bend_bezier_q.png)
    """

    start: fp.Point2D = fp.PositionParam(default=(0, 0), doc="position where bend start, eg. (x, y)")
    controls: Sequence[fp.Point2D] = fp.PointsParam(default=[(10, 0)], min_count=1, doc="control points, count >= 1, eg. [(x1, y1), (x2, y2)]")
    end: fp.Point2D = fp.PositionParam(default=(10, 10), doc="position where bend end, eg. (x, y)")
    waveguide_type: fp.IWaveguideType = fp.WaveguideTypeParam(doc="Waveguide parameters")
    port_names: fp.IPortOptions = fp.PortOptionsParam(count=2, default=["op_0", "op_1"])

    def _default_waveguide_type(self):
        return get_technology().WG.FWG.C.WIRE

    @cached_property
    def raw_curve(self):
        return fp.g.Bezier(
            start=self.start,
            controls=self.controls,
            end=self.end,
        )

    def build(self) -> Tuple[fp.InstanceSet, fp.ElementSet, fp.PortSet]:
        insts, elems, ports = super().build()
        wg = self.waveguide_type(curve=self.raw_curve).with_ports(self.port_names)
        insts += wg
        ports += wg.ports
        return insts, elems, ports

Section Script Description

The script firstly imports python function modules such as cached_property, Sequence, Tuple, etc. (users can temporarily ignore their specific meaning). Secondly, it imports the process information in the function modules fnpcell and gpdk.technology module:

from functools import cached_property
from typing import Sequence, Tuple

from fnpcell import all as fp
from gpdk.technology import get_technology

The BendBezier class is defined by class BendBezier( ). The BendBezier class contains several parameters for the cell layout: start, controls, end, waveguide_type, ports_names.

Please refer to the source code and its comments for detailed information about the parameters and how to use them. Some of the parameters have default values, so if users do not make special settings when using them, then they will be treated as default values. Secondly, users can modify the parameters to generate specific layout units.

class BendBezier(fp.IWaveguideLike, fp.PCell):

       start: fp.Point2D = fp.PositionParam(default=(0, 0), doc="position where bend start, eg. (x, y)")
       controls: Sequence[fp.Point2D] = fp.PointsParam(default=[(10, 0)], min_count=1, doc="control points, count >= 1, eg. [(x1, y1), (x2, y2)]")
       end: fp.Point2D = fp.PositionParam(default=(10, 10), doc="position where bend end, eg. (x, y)")
       waveguide_type: fp.IWaveguideType = fp.WaveguideTypeParam(doc="Waveguide parameters")
       port_names: fp.IPortOptions = fp.PortOptionsParam(count=2, default=["op_0", "op_1"])

If no waveguide type is given, the default waveguide type will be returned:

def _default_waveguide_type(  ):
    return get_technology().WG.FWG.C.WIRE

This function is used to control the bezier curve design using user-defined parameters, and the return value is the new bezier curve generated:

def raw_curve(self):
    return fp.g.Bezier(
        start=self.start,
        controls=self.controls,
        end=self.end,
    )

Define the method to build user-defined parametric design to generate bezier bend, return the graphical unit and the port information of the device. Then generate the device according to the set parameters, i.e., a customized bend_bezier layout unit:

def build(self) -> Tuple[fp.InstanceSet, fp.ElementSet, fp.PortSet]:
        insts, elems, ports = super().build()
        wg = self.waveguide_type(curve=self.raw_curve).with_ports(self.port_names)
        insts += wg
        ports += wg.ports
        return insts, elems, ports