Skip to content

Commit

Permalink
Merge pull request #189 from gdsfactory/improve_docs
Browse files Browse the repository at this point in the history
Improve docs
  • Loading branch information
sebastian-goeldi authored Oct 5, 2023
2 parents 17f5bae + df3420b commit 95102e6
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 116 deletions.
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

0 comments on commit 95102e6

Please sign in to comment.