ipkiss3.all.Place¶

class ipkiss3.all.Place(pos_selector, position, angle=None)

Specifies that an instance or its port should be placed on a given position and angle (angle is optional).

If angle is not specified (i.e. angle=None), then the instance will keep its original transformations.

If angle is specified, the original transformations will be overridden and the instance will be rotated.

If you specify an angle and choose to place a port that has an angle, then the instance is rotated such that the port’s angle will equal this desired angle.

If you place a port with an undefined port angle (angle=None), and you specify an angle in Place, then the port’s angle will stay ‘None’ but its instance will be rotated.

Examples

>>> i3.Place('inst', (0, 0))                 # Place 'inst' at (0, 0), original transformations are kept
>>> i3.Place('inst', (0, 0), angle=90)       # Place 'inst at (0, 0) with a rotation of 90 degrees, original transformations are discarded
>>> i3.Place('inst:out', (0, 0))             # Place port 'out' of 'inst' at (0, 0) with the angle of the port of the instance
>>> i3.Place('inst:out', (0, 0), angle=90)   # Place port 'out' of 'inst' (original port angle = 180) at (0, 0), with port angle 90 degrees, original transformations are discarded
>>> i3.Place('inst:out', (0, 0), angle=90)   # Place port 'out' of 'inst' (original port angle is None) at (0, 0), with a rotation of 90 degrees, original transformations are discarded


Below a few examples that illustrate how to use the Place spec to put instances or ports on a specified position. In the examples we use LayoutCell to quickly visualize the results.

Optical components¶

import ipkiss3.all as i3
from pylab import plt

wg = i3.RoundedWaveguide().Layout(shape=[
(-10, 0),
(0, 0),
(10, 10),
])

insts = i3.place_insts({
'wg': wg
}, [
# this specifies that the origin '(0, 0)' of 'wg' should be at (10, 0)
i3.Place('wg', (10, 0))
])

i3.LayoutCell().Layout(instances=insts, ports=insts['wg'].ports).visualize(annotate=True)
ax = plt.gca()
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


Instead of specifying the position of the origin of an instance, we can also specify that a port should be placed at a given position.

insts = i3.place_insts({
'wg': wg
}, [
# We specify that the 'out' port of 'wg' should be at (10, 0)
i3.Place('wg:out', (10, 0))
])

lv = i3.LayoutCell().Layout(instances=insts, ports=insts['wg'].ports)
lv.visualize(annotate=True)
ax = plt.gca()
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


By default the rotation of the instance or the port remains untouched. But by specifying the angle attribute, we can place the instance or port with a different rotation.

insts = i3.place_insts({
'wg': wg
}, [
# origin of 'wg' must be at (0, 0) with an angle of 45 deg
i3.Place('wg', (0, 0), angle=45)
])

lv = i3.LayoutCell().Layout(instances=insts, ports=insts['wg'].ports)
lv.visualize(annotate=True)
ax = plt.gca()
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


This works as well for ports:

insts = i3.place_insts({
'wg': wg
}, [
# port 'wg:out' must be at (0, 0) with an angle of 90 deg
i3.Place('wg:out', (0, 0), angle=90)
])

lv = i3.LayoutCell().Layout(instances=insts, ports=insts['wg'].ports)
lv.visualize(annotate=True)
ax = plt.gca()
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


Use the FlipH/FlipV specs to declare that you want to place a mirrored version of your component.

insts = i3.place_insts({
'wg': wg
}, [
# Place a horizontally mirrored instance of 'wg' instead of
# the normal one.
i3.FlipH('wg'),
i3.Place('wg', (0, 0))
])

lv = i3.LayoutCell().Layout(instances=insts, ports=insts['wg'].ports)
lv.visualize(annotate=True)
ax = plt.gca()
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


When you’re providing an already rotated instance as input to place_insts and don’t specify the angle attribute of Place, the transformation, in this case a rotation, will be kept.

insts = i3.place_insts(i3.InstanceDict([
i3.SRef(name='wg',
reference=wg,
transformation=i3.Rotation(rotation=45.))
]), [
i3.Place('wg', (-10, 0))
])

lv = i3.LayoutCell().Layout(instances=insts, ports=insts['wg'].ports)
lv.visualize(annotate=True)
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


Electrical components¶

The examples above are easily replicated in the electrical domain by changing i3.RoundedWaveguide to i3.ElectricalWire. For example:

import ipkiss3.all as i3
from pylab import plt

wire = i3.ElectricalWire().Layout(shape=[
(-10, 0),
(0, 0),
(10, 10),
])

insts = i3.place_insts({
'wire': wire
}, [
# We specify that the 'out' port of 'wire' should be at (10, 0)
i3.Place('wire:out', (10, 0))
])

lv = i3.LayoutCell().Layout(instances=insts, ports=insts['wire'].ports)
lv.visualize(annotate=True)
ax = plt.gca()
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


The results will mostly be the same, but there is a difference when placing electrical ports and specifiying an angle. If the angle is undefined (which may happen with some type of electrical ports), its instance is rotated instead:

insts = i3.place_insts({
'wire': wire
}, [
# port 'wire:out' must be at (0, 0) with its instance rotated 90 degress.
i3.Place('wire:out', (0, 0), angle=90)
])

lv = i3.LayoutCell().Layout(instances=insts, ports=insts['wire'].ports)
lv.visualize(annotate=True)
ax = plt.gca()
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


Compare this to the same situation in the optical domain:

insts = i3.place_insts({
'wg': wg
}, [
# port 'wg:out' must be at (0, 0) with an angle of 90 deg
i3.Place('wg:out', (0, 0), angle=90)
])

lv = i3.LayoutCell().Layout(instances=insts, ports=insts['wg'].ports)
lv.visualize(annotate=True)
ax = plt.gca()
ax.hlines(xmin=-20, xmax=20, y=0, linestyle='dashed')
ax.vlines(ymin=-20, ymax=20, x=0, linestyle='dashed')


Note

If the electrical ports have defined port angles (just like optical ports), then the placement specifications of those ports will work exactly the same as with optical ports.