Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve docs #189

Merged
merged 2 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 28 additions & 51 deletions docs/source/notebooks/00_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@

# %%
c.shapes(c.kcl.layer(1, 0)).insert(poly1)
# show it in matplotlib and KLayout (you need to have KLayout open and install gdsfactory from the git repo with make install)

# %%
c.show() # show in klayout
Expand All @@ -59,26 +58,25 @@
# %% [markdown]
# **Exercise** :
#
# Make a cell similar to the one above that has a second polygon in layer (1, 1)
# Make a cell similar to the one above that has a second polygon in layer (2, 0)
#
# **Solution** :

# %%
c = kf.KCell()
points = np.array([(-8, -6), (6, 8), (7, 17), (9, 5)])
poly = kf.polygon_from_array(points)
c.shapes(c.kcl.layer(1, 0)).insert(poly1)
c.shapes(c.kcl.layer(1, 1)).insert(poly1)
c.shapes(c.kcl.layer(2, 0)).insert(poly1)
c

# %%
import kfactory as kf

# %%
c = kf.KCell()

# %%
# Create some new geometry from the functions available in the geometry library
textgenerator = kf.kdb.TextGenerator.default_generator()
t = textgenerator.text("Hello!", c.kcl.dbu)
c.shapes(kf.kcl.layer(1, 0)).insert(t)
c.show() # show in klayout
c.plot()

# %%
r = kf.kdb.DBox(-2.5, -5, 2.5, 5)
Expand All @@ -88,18 +86,21 @@
# Add instances to the new geometry to c, our blank cell

# %%
c.shapes(kf.kcl.layer(1, 0)).insert(t)
c.show() # show in klayout
c.plot()

# %% [markdown]
# Using the << operator (identical to add_ref()), add the same geometry a second time
c = kf.KCell()
c.shapes(c.kcl.layer(1, 0)).insert(r)
c.shapes(c.kcl.layer(2, 0)).insert(r)
c

# %%
# Now that the geometry has been added to "c", we can move everything around:
c = kf.KCell()
textgenerator = kf.kdb.TextGenerator.default_generator()
text1 = t.transformed(
kf.kdb.DTrans(0.0, 10.0).to_itype(c.kcl.dbu)
) # DTrans is a transformation in microns with arguments (<rotation in 90° increments>, <mirror boolean>, <x in microns>, <y in microns>)
# Now that the geometry has been added to "c", we can move everything around:


# %%
### complex transformation example:ce
# magnification(float): magnification, DO NOT USE on cells or instances, only shapes, most foundries will not allow magnifications on actual cell instances or cells
# rotation(float): rotation in degrees
Expand All @@ -118,7 +119,6 @@
) # boxes can be moved like this, other shapes and cellss/refs need to be moved with .transform
r.move(-5, 0)


# %%
c.shapes(c.kcl.layer(1, 0)).insert(text1)
c.shapes(c.kcl.layer(2, 0)).insert(text2)
Expand Down Expand Up @@ -163,45 +163,30 @@ def straight(length=10, width=1, layer=(1, 0)):

# %%
c = kf.KCell()

# %%
wg1 = c << straight(length=6, width=2.5, layer=(1, 0))
wg2 = c << straight(length=11, width=2.5, layer=(1, 0))
wg3 = c << straight(length=15, width=2.5, layer=(1, 0))

# %%
# wg2.transform(kf.kdb.DCplxTrans(1, 10, False, 10, 0))
# wg3.transform(kf.kdb.DCplxTrans(1, 15, False, 20, 0))
# wg2.movey(10).rotate(10)
# wg3.movey(20).rotate(15)
print(c.name)
c.show() # show in klayout
# c.plot()
wg1 = c << straight(length=1, width=2.5, layer=(1, 0))
wg2 = c << straight(length=2, width=2.5, layer=(1, 0))
wg3 = c << straight(length=3, width=2.5, layer=(1, 0))
c

# %% [markdown]
# Now we can align everything together using the ports:

# %% [markdown]
# Each straight has two ports: 'W0' and 'E0'. These are arbitrary
# names defined in our straight() function above
# Each straight has two ports: 'o1' and 'o2'. These are arbitrary names defined in our straight() function above

# %%
# Let's keep wg1 in place on the bottom, and connect the other straights to it.
# To do that, on wg2 we'll grab the "W0" port and connect it to the "E0" on wg1:
wg2.connect("o1", wg1.ports["o2"])
# Next, on wg3 let's grab the "W0" port and connect it to the "E0" on wg2:
wg3.connect("o1", wg2.ports["o2"])

# %%
c.show() # show in klayout
# c.plot()

c

# %%
c.add_port(name="o1", port=wg1.ports["o1"])
c.add_port(name="o2", port=wg3.ports["o2"])
c.show() # show in klayout
# c.plot()
c.plot()

# %% [markdown]
# As you can see the `red` labels are for the cell ports while
Expand Down Expand Up @@ -236,7 +221,7 @@ def straight(length=10, width=1, layer=(1, 0)):

# %%
c.show() # show in klayout
# c.plot()
c.plot()

# %% [markdown]
# ## Ports
Expand Down Expand Up @@ -311,9 +296,7 @@ def straight(length=10, width=1, layer=(1, 0)):

# %%
c2.shapes(c2.kcl.layer(1, 0)).insert(kf.kdb.Text("First label", mwg1_ref.trans))
# c2.shapes(c2.kcl.layer(1,0).insert(kf.kdb.Text("First label", position=mwg1_ref.center)
c2.shapes(c2.kcl.layer(1, 0)).insert(kf.kdb.Text("Second label", mwg2_ref.trans))
# c2.add_label(text="Second label", position=mwg2_ref.center)

# %%
# It's very useful for recording information about the devices or layout
Expand All @@ -323,9 +306,8 @@ def straight(length=10, width=1, layer=(1, 0)):
kf.kdb.Trans(c2.bbox().right, c2.bbox().top),
)
)

# %%
c2
c2.show()
c2.plot()

# %% [markdown]
# ## Boolean shapes
Expand Down Expand Up @@ -428,15 +410,10 @@ def straight(length=10, width=1, layer=(1, 0)):
# %% [markdown]
# ## Write GDS
#
# [GDSII](https://en.wikipedia.org/wiki/GDSII) is the Standard format for exchanging CMOS and Photonic circuits.
# [GDSII](https://en.wikipedia.org/wiki/GDSII) is the Standard format for exchanging CMOS circuits with foundries
#
# You can write your Cell to GDS file.


# %%
c.write("demo.gds")

# %% [markdown]
# You can see the GDS file in Klayout viewer.
#
# Sometimes you also want to save the GDS together with metadata (settings, port names, widths, locations ...) in YAML
59 changes: 2 additions & 57 deletions docs/source/notebooks/01_references.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,6 @@
# In GDS, there's a type of structure called a "Instance" which takes a cell and repeats it NxM times on a fixed grid spacing. For convenience, `Cell` includes this functionality with the add_array() function.
# Note that CellArrays are not compatible with ports (since there is no way to access/modify individual elements in a GDS cellarray)
#
# gdsfactory also provides with more flexible arrangement options if desired, see for example `grid()` and `packer()`.
#
# As well as `gf.cells.array`
#
# Let's make a new Cell and put a big array of our Cell `c` in it:

# %%
Expand All @@ -204,59 +200,6 @@
) # instance the Cell "c" 3 instances in it with a 3 rows, 6 columns array
c3

# %% [markdown]
# CellArrays don't have ports and there is no way to access/modify individual elements in a GDS cellarray.
#
# gdsfactory provides you with similar functions in `gf.cells.array` and `gf.cells.array_2d`

# %%
# c4 = gf.Cell("demo_array") # Create a new blank Cell
# aref = c4 << gf.cells.array(cell=c, columns=3, rows=2)
# c4.add_ports(aref.get_ports_list())
# c4


# %%
# # gf.cells.array?

# %% [markdown]
# You can also create an array of instances for periodic structures. Lets create a [Distributed Bragg Reflector](https://picwriter.readthedocs.io/en/latest/cells/dbr.html)


# %%
# @gf.cell
# def dbr_period(w1=0.5, w2=0.6, l1=0.2, l2=0.4, straight=gf.cells.straight):
# """Return one DBR period."""
# c = gf.Cell()
# r1 = c << straight(length=l1, width=w1)
# r2 = c << straight(length=l2, width=w2)
# r2.connect(port="o1", destination=r1.ports["o2"])
# c.add_port("o1", port=r1.ports["o1"])
# c.add_port("o2", port=r2.ports["o2"])
# return c


# l1 = 0.2
# l2 = 0.4
# n = 3
# period = dbr_period(l1=l1, l2=l2)
# period

# %%
# dbr = gf.Cell("DBR")
# dbr.add_array(period, columns=n, rows=1, spacing=(l1 + l2, 100))
# dbr

# %% [markdown]
# Finally we need to add ports to the new cell

# %%
# p0 = dbr.add_port("o1", port=period.ports["o1"])
# p1 = dbr.add_port("o2", port=period.ports["o2"])

# p1.center = [(l1 + l2) * n, 0]
# dbr

# %% [markdown]
# ## connect instances
#
Expand Down Expand Up @@ -339,3 +282,5 @@
c = kf.cells.euler.bend_euler(radius=5, width=1, layer=0, angle=90)
c.draw_ports()
c

# %%
36 changes: 28 additions & 8 deletions docs/source/notebooks/04_KCL.py
Original file line number Diff line number Diff line change
@@ -1,68 +1,83 @@
# ---
# jupyter:
# jupytext:
# custom_cell_magics: kql
# text_representation:
# extension: .py
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.15.0
# format_name: percent
# format_version: '1.3'
# jupytext_version: 1.11.2
# kernelspec:
# display_name: Python 3 (ipykernel)
# language: python
# name: python3
# ---

# %% [markdown]
# # Multi - KCLayout / PDK

# Using multiple KCLayout objects as PDKs or Libraries of KCells and parametric KCell-Functions
# %% [markdown]
# You can also use multiple KCLayout objects as PDKs or Libraries of KCells and parametric KCell-Functions

# %% [markdown]
# ## Use multiple KCLayout objects as PDKs/Libraries
#
# KCLayouts can act as PDKs. They can be seamlessly instantiated into each other

# +
# %%
import kfactory as kf

kcl_default = kf.kcl
# -

# %% [markdown]
# Empty default KCLayout

# %%
kcl_default.kcells

# %%
# Create a default straight waveguide in the default KCLayout with dbu==0.001 (1nm grid)
s_default = kf.cells.straight.straight(
width=1, length=10, layer=kcl_default.layer(1, 0)
)

# %%
# There is now a a KCell in the KCLayout
kcl_default.kcells

# %%
# Control the dbu is still 1nm
kcl_default.dbu

# %%
# Create a new KCLayout to simulate pdk (could be package with e.g. `from test_pdk import kcl as pdk` or similar)
kcl2 = kf.KCLayout("TEST_PDK")
# Set the dbu to 0.005 (5nm)
kcl2.dbu = 0.005
kcl2.layout.dbu

# %%
# Since it's a new KCLayout, it's empty
kcl2

# %%
# Create an parametric KCell-Function for straights on the new pdk
sf2 = kf.cells.dbu.Straight(kcl=kcl2)

# %%
# The function hasn't been added to the function yes, so it's still empty
sf2.kcl

# %%
# Add it to the pdk factories
kcl2.factories.update({"straight": kf.cells.dbu.Straight(kcl2)})

# %%
# Make an instance with
s2 = kcl2.factories["straight"](length=10000, width=200, layer=kcl2.layer(1, 0))
s2.settings

# %%
# The default kcl's straight uses 1nm grid and is therefore 1000dbu (1um) high and 10000dbu (10um) wide
print(f"{s_default.bbox().height()=}")
print(f"{s_default.dbbox().height()=}")
Expand All @@ -74,30 +89,35 @@
print(f"{s2.bbox().width()=}")
print(f"{s2.dbbox().width()=}")

# %%
# The ports of the default kcl also have different dbu dimensions, but are the same in um
print(f"{s_default.ports=}")
print(f"{s2.ports=}")
# But in um they are the same
print(f"{[port.d for port in s_default.ports]=}")
print(f"{[port.d for port in s2.ports]=}")

# %%
# Both can be instantiated into the same KCell
c = kcl_default.kcell()
si_d = c << s_default
si_2 = c << s2

# %%
si_2.connect("o1", si_d, "o2")

# %%
c


# %%
class LAYER2(kf.LayerEnum):
kcl = kf.constant(kcl2)
WG = (1, 0)


# %%
kcl2.layers = LAYER2

# %%
kcl2.layers

LAYER2
Loading