Skip to content

Commit

Permalink
Merge pull request #21 from lukasc-ubc/master
Browse files Browse the repository at this point in the history
Update from Master
  • Loading branch information
jaspreetj committed Apr 11, 2016
2 parents 6eeccc7 + 4cddd87 commit 89b7211
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 89 deletions.
Binary file modified Lumerical_EBeam_CML/ebeam_v1.2/ebeam_gc_te1550.ice
Binary file not shown.
Binary file modified Lumerical_EBeam_CML/ebeam_v1.2_2016_04_10.cml
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ Lukas Chrostowski 2015/12/04
Lukas Chrostowski 2015/12/9
- .index() is a list method; replaced Optical_*.idx with .idx
- Convert all Si paths to waveguides if nothing is selected.

Lukas Chrostowski 2016/05/10
- Snap waveguide only to pins with the same orientation; fixes.


"""

Expand Down Expand Up @@ -224,7 +228,10 @@ for o in object_selection:
# Calculate the distance between every pin and each path endpoint
for pin in optical_pins:
# check if pin / path segment are in the same orientation
angle_pin_path = angle_segments(pin.points,[path_endpoint, path_endpointb])
if pin.pin_type==1: # only snap to component pins.
angle_pin_path = angle_segments(pin.points,[path_endpoint, path_endpointb])
else:
angle_pin_path = -1
if angle_pin_path == 0 or abs(angle_pin_path) == 180:
# this updates "optical_pins" via the "pin" pointer
# print( "path endpoint: %s, pin %s: %s" % (path_endpoint, pin.n, [pin.x, pin.y] ) )
Expand Down
107 changes: 59 additions & 48 deletions klayout_dot_config/pymacros/SiEPIC_EBeam_Snap_Component.lym
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Lukas Chrostowski 2016/03/08
"""

# Configure variables to draw structures in the presently selected cell:
mw = pya.Application.instance().main_window()
lv = pya.Application.instance().main_window().current_view()
if lv == None:
raise Exception("No view selected")
Expand All @@ -45,6 +46,7 @@ ly = pya.Application.instance().main_window().current_view().active_cellview().l
if ly == None:
raise Exception("No layout")
# find the currently selected cell:
cv = pya.Application.instance().main_window().current_view().active_cellview()
topcell = pya.Application.instance().main_window().current_view().active_cellview().cell
if topcell == None:
raise Exception("No cell")
Expand All @@ -68,6 +70,7 @@ layout_errors = []

# Record a transaction, to enable "undo"
lv.transaction("Object snapping")
proceed = True

# extract the circuit netlist from the physical layout:
optical_waveguides, optical_components = netlist_extraction(topcell)[:2]
Expand All @@ -78,66 +81,74 @@ if lv.has_transient_object_selection() == False:
else:
# find the transient selection:
o_transient_iter = lv.each_object_selected_transient()
o_transient = next(o_transient_iter); # returns ObjectInstPath[].
o_transient = next(o_transient_iter) # returns ObjectInstPath[].

# Find the selected objects
o_selection = lv.object_selection # returns ObjectInstPath[].
if len(o_selection) < 1:
v = pya.MessageBox.warning("No selection", "Select the object you wish to be moved.", pya.MessageBox.Ok)
else:
o_selection = o_selection[0]
if o_transient == o_selection:
v = pya.MessageBox.warning("Same selection", "We need two different objects: one selected, and one transient (hover mouse over).", pya.MessageBox.Ok)
else:

if o_selection.inst().is_regular_array() | o_transient.inst().is_regular_array():
v = pya.MessageBox.warning("Array", "Selection was an array. \nThe array was 'exploded' (Edit | Selection | Resolve Array). \nPlease select the objects and try again.", pya.MessageBox.Ok)
o_transient.inst().explode()
o_selection.inst().explode()
proceed = False

if proceed:
if o_transient == o_selection:
v = pya.MessageBox.warning("Same selection", "We need two different objects: one selected, and one transient (hover mouse over).", pya.MessageBox.Ok)
else:

# we have two instances:
# print o_transient.inst()
# print o_selection.inst()

# find the instances in the optical_components database; use the x,y coordinates for identification
x1 = o_transient.inst().trans.disp.x
y1 = o_transient.inst().trans.disp.y
x2 = o_selection.inst().trans.disp.x
y2 = o_selection.inst().trans.disp.y

idx1 = -1
idx2 = -1
for o in optical_components:
if int(o.x / dbu) == x1 and int(o.y / dbu) == y1:
idx1 = o.idx
if int(o.x / dbu) == x2 and int(o.y / dbu) == y2:
idx2 = o.idx
if idx1 < 0 or idx2 < 0:
v = pya.MessageBox.warning("Optical components not found", "Optical components not found.", pya.MessageBox.Ok)
else:
# we have two optical components. Proceed with alignment

# find the closest pins between the two objects; calculate the move/transform required
dist = 1e100
for p1 in optical_components[idx1].pins:
for p2 in optical_components[idx2].pins:
# check if both pins are type "1 = component"
if optical_pins[p1].pin_type == 1 and optical_pins[p2].pin_type == 1:
# check if pins are in the same orientation
angle_p1_p2 = angle_segments(optical_pins[p1].points,optical_pins[p2].points)
# print check_segments_same_direction( optical_pins[p1].points, optical_pins[p2].points )
if angle_p1_p2 == 0 or abs(angle_p1_p2) == 180:
# find the closest ones
dx = optical_pins[p1].x - optical_pins[p2].x
dy = optical_pins[p1].y - optical_pins[p2].y
dist_comp = dx*dx + dy*dy
if dist > dist_comp:
# save this dx/dy as the shortest distance transformation
dist = dist_comp
dx12 = dx
dy12 = dy
# print o_selection.inst().trans.disp.x
if dist < 1e100:
# Move the selected object
trans = pya.Trans(dx12,dy12)
o_selection.inst().transform(trans)
# find the instances in the optical_components database; use the x,y coordinates for identification
x1 = o_transient.inst().trans.disp.x
y1 = o_transient.inst().trans.disp.y
x2 = o_selection.inst().trans.disp.x
y2 = o_selection.inst().trans.disp.y

idx1 = -1
idx2 = -1
for o in optical_components:
if int(o.x / dbu) == x1 and int(o.y / dbu) == y1:
idx1 = o.idx
if int(o.x / dbu) == x2 and int(o.y / dbu) == y2:
idx2 = o.idx
if idx1 < 0 or idx2 < 0:
v = pya.MessageBox.warning("Optical components not found", "Optical components not found.", pya.MessageBox.Ok)
else:
v = pya.MessageBox.warning("Snapping failed", "Snapping failed. No matching pins found.", pya.MessageBox.Ok)
# we have two optical components. Proceed with alignment

# find the closest pins between the two objects; calculate the move/transform required
dist = 1e100
for p1 in optical_components[idx1].pins:
for p2 in optical_components[idx2].pins:
# check if both pins are type "1 = component"
if optical_pins[p1].pin_type == 1 and optical_pins[p2].pin_type == 1:
# check if pins are in the same orientation
angle_p1_p2 = angle_segments(optical_pins[p1].points,optical_pins[p2].points)
# print check_segments_same_direction( optical_pins[p1].points, optical_pins[p2].points )
if angle_p1_p2 == 0 or abs(angle_p1_p2) == 180:
# find the closest ones
dx = optical_pins[p1].x - optical_pins[p2].x
dy = optical_pins[p1].y - optical_pins[p2].y
dist_comp = dx*dx + dy*dy
if dist > dist_comp:
# save this dx/dy as the shortest distance transformation
dist = dist_comp
dx12 = dx
dy12 = dy
# print o_selection.inst().trans.disp.x
if dist < 1e100:
# Move the selected object
trans = pya.Trans(dx12,dy12)
o_selection.inst().transform(trans)
else:
v = pya.MessageBox.warning("Snapping failed", "Snapping failed. No matching pins found.", pya.MessageBox.Ok)

# Record a transaction, to enable "undo"
lv.commit()
Expand Down
63 changes: 63 additions & 0 deletions klayout_dot_config/pymacros/qt_dialog_python.lym
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<klayout-macro>
<description/>
<version/>
<category>pymacros</category>
<prolog/>
<epilog/>
<doc/>
<autorun>false</autorun>
<autorun-early>false</autorun-early>
<shortcut/>
<show-in-menu>false</show-in-menu>
<group-name/>
<menu-path/>
<interpreter>python</interpreter>
<dsl-interpreter-name/>
<text>import pya

class ScreenshotDialog(pya.QDialog):
"""
This class implements a dialog with a screenshot display area and a
screenshot button
"""

def button_clicked(self, checked):
""" Event handler: "Screenshot" button clicked """

view = pya.Application.instance().main_window().current_view()

# get the screenshot and place it in the image label
if not view is None:
self.image.setPixmap(pya.QPixmap.fromImage(view.get_image(400, 400)))
else:
self.image.setText("No layout opened to take screenshot from")

def __init__(self, parent = None):
""" Dialog constructor """

super(ScreenshotDialog, self).__init__()

self.setWindowTitle("Screenshot Saver")

self.resize(400, 120)

layout = pya.QVBoxLayout(self)
self.setLayout(layout)

self.image = pya.QLabel("Press the button to fetch a screenshot", self)
layout.addWidget(self.image)

button = pya.QPushButton('Screenshot', self)
button.setFont(pya.QFont('Times', 18, pya.QFont.Bold))
layout.addWidget(button)

# attach the event handler
button.clicked(self.button_clicked)

# Instantiate the dialog and make it visible initially.
# Passing the main_window will make it stay on top of the main window.
dialog = ScreenshotDialog(pya.Application.instance().main_window())
dialog.show()
</text>
</klayout-macro>
Loading

0 comments on commit 89b7211

Please sign in to comment.