Step 2: PCell and Views


In this example we add a LayoutView to a parametric cell of a ring resonator. Views describe the PCell in a particular context and PCells can contain many views. In this example, the layout of a PCell will be generated in the LayoutView.


  1. how to add a view, subclassing from one of the predefined view types (here LayoutView)

  2. how to add properties to a view

  3. how to instantiate a View of a PCell.

How to run this example

To run the example, run ‘’.

Files (see: tutorials/layout_basic/02-view)

There are two files contained in this step.

  • : which is a self-contained python file that contains a description of our ringresonator. It is imported in

  • : which is the file that is ultimately executed by python. It imports the description of the ringresonator from and performs operations on it.


In IPKISS, views are defined as classes inside the PCell class. A PCell can contain many different views of different types. Each view type has its own specific methods that are needed to handle view-specific things. To achieve this, views inherit from a view type that adds those specific methods to your view class.

Within the RingResonator class we add a subclass Layout that inherits from i3.LayoutView. i3.LayoutView is the predefined view type for Layout in which all the methods relevant for layout are contained.

class RingResonator(i3.PCell):
    """A generic ring resonator class.

    It is defined by a circular waveguide evanescently coupled to a straight bus waveguide.
    _name_prefix = "RINGRES" # a prefix added to the unique identifier

    # We moved the properties from PCell level to LayoutView level as
    # ring_radius, ring_wg_width, bus_wg_width and coupler_spacing
    # are only relevant in the context of Layout.

    class Layout(i3.LayoutView):
       #.... Define your layout view here.....

Just like PCells, views can have properties


An important difference between pcell properties and view properties is that view properties are required to have default values. Enforcing this, makes sure that it’s possible to create a meaningful layout without the need to explicitly specify parameters.

Let’s see how this is done in practice:

class RingResonator(i3.PCell):

    #... Pcell definition omitted

    class Layout(i3.LayoutView):

        ring_radius = i3.PositiveNumberProperty(default=7.0, doc="radius of the ring in micrometers")
        ring_wg_width = i3.PositiveNumberProperty(default=0.5, doc="width of the ring waveguide in micrometers")
        bus_wg_width = i3.PositiveNumberProperty(default=0.5, doc="width of the bus waveguide in micrometers")
        coupler_spacing = i3.PositiveNumberProperty(default=1.0, doc="spacing between centerline of bus waveguide and ring waveguide")

        def validate_properties(self):
            # ... validation rules omitted....
            return True

The only difference with the previous example is that we moved all the properties to the layout level and gave a default value to ring_radius. The validation rules (omitted here) work in the exact same way as they did on PCells

It’s good practice to place the properties at the appropriate level. Since all the properties here are layout-specific, we place them in the LayoutView. This implies that those properties will only be needed when we create the LayoutView of our PCell.


Although recommended, there is no obligation to place all the view-specific properties at the view level. If you leave them at the PCell level, they will still be accessible in the view. Deciding if a property is a layout property or a pcell property is not always easy, a general rule of thumb is that if you reuse the same parameters in different views, you can place the property at pcell level.

Instantiating views

Views are instantiated by calling the view class the PCell instance. Let’s see how this is done in practice.

import ipkiss3.all as i3

# 1. import the ring resonator.
from ring import RingResonator

# 2. create a new RingResonator Pcell. Here no properties are needed.
my_ring = RingResonator(name="my_unique_ring_name")

# 3. create  the LayoutView object
my_ring_layout = my_ring.Layout(ring_radius=10.0)

# 4. print a property

# 5. The PCell and Layout instantiation can be done in one line as well.
my_ring_layout_2 = RingResonator().Layout(ring_radius=10.0)

  1. We import and instantiate the RingResonator class.

  2. We instantiate the ring resonator PCell. Here no properties are needed as they have all been moved to the layout level.

  3. We instantiate the layout using the my_ring.

  4. Using my_ring, we instantiate the Layout and specify the properties that are now at the layout level. The layout instance of my_ring is called my_ring_layout. The layout-specific properties can now directly be accessed from the layout instance.

  5. A PCell and a specific view can also be created using a short-hand notation.


It is important to use the instance of a PCell to create the layoutview instance of that PCell. PCell.RingResonator.Layoutview() will not work.

Referring to views

It is possible to retrieve views from a PCell without modifying them. For now, we show you two slightly different ways of doing that as shown below.

# 6. Referring the default view that inherits from i3.LayoutView
  1. my_ring.get_default_view(i3.LayoutView): refers the view of my_ring of the Layout type - That is a view that inherits from i3.LayoutView.


Do not use my_ring.Layout() to retrieve the Layout view. my_ring.Layout() will essentially reset the Layout view of my_ring to its default view by setting all the properties to their default values.


You have now learned the use of PCells, views and properties. In the next step you will learn about technologies, which allow you to define global variables which can be reused in the PCells you create (for example, a minimum bend radius).

If you want to know more about: