Skip to content

Commit 4d13e69

Browse files
AbdullahKazi500qpavsmi
authored andcommitted
Visualise ports in KLayout preview when simulation is exported
1 parent e83a110 commit 4d13e69

1 file changed

Lines changed: 77 additions & 0 deletions

File tree

klayout_package/python/kqcircuits/simulations/simulation.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,9 @@ def create_simulation_layers(self):
902902
if part.visualise:
903903
self.visualise_region(part.region, part.name, f"part_reg_{part.name}")
904904

905+
# Finally, visualise all ports
906+
self.visualise_ports()
907+
905908
def produce_layers(self, parts):
906909
"""Finalizes and partitions self.layers.
907910
@@ -1455,3 +1458,77 @@ def visualise_region(
14551458
else:
14561459
for i, p in enumerate(points):
14571460
self.cell.shapes(visualisation_layer).insert(pya.DText(f"{label}_{i+1}", p.x, p.y))
1461+
1462+
def visualise_ports(self, edge_port_thickness=500):
1463+
"""Visualise all ports in a dedicated 'simulation_ports' layer using get_port_data().
1464+
1465+
Args:
1466+
edge_port_thickness (float): Extra outward extension (µm) for EdgePorts to make them more visible.
1467+
"""
1468+
dbu = self.layout.dbu
1469+
port_json = self.get_port_data()
1470+
1471+
for port in self.ports:
1472+
# Initialize visualise_point at the start of each iteration
1473+
visualise_point = None
1474+
1475+
# Try to find a matching entry in port_json
1476+
port_data_list = [p for p in port_json if p.get("number") == port.number]
1477+
if not port_data_list:
1478+
logging.warning(f"Port {port.number} not found in get_port_data() output, skipping visualisation.")
1479+
continue
1480+
port_data = port_data_list[0]
1481+
1482+
# Label based on port type
1483+
if isinstance(port, EdgePort):
1484+
label = f"edge_port_{port.number}"
1485+
elif isinstance(port, InternalPort):
1486+
label = f"internal_port_{port.number}"
1487+
else:
1488+
logging.warning(f"Unsupported port type {type(port).__name__} for port {port.number}")
1489+
continue
1490+
1491+
# Construct 2D polygon from port_data["polygon"] (ignoring z coordinate)
1492+
if "polygon" in port_data and port_data["polygon"]:
1493+
points_2d = [pya.DPoint(p[0], p[1]) for p in port_data["polygon"]]
1494+
1495+
if isinstance(port, EdgePort) and edge_port_thickness > 0:
1496+
direction = None
1497+
if port.signal_location.x == self.box.p1.x:
1498+
# Port on left border of simulation box
1499+
direction = pya.DPoint(-edge_port_thickness, 0)
1500+
elif port.signal_location.x == self.box.p2.x:
1501+
# on right border
1502+
direction = pya.DPoint(edge_port_thickness, 0)
1503+
elif port.signal_location.y == self.box.p1.y:
1504+
# on bottom border
1505+
direction = pya.DPoint(0, -edge_port_thickness)
1506+
elif port.signal_location.y == self.box.p2.y:
1507+
# on top border
1508+
direction = pya.DPoint(0, edge_port_thickness)
1509+
1510+
if not direction:
1511+
# draw
1512+
poly = pya.DPolygon(points_2d)
1513+
else:
1514+
# Some points are duplicates when projected to 2D. Ensure you get two different points
1515+
points_2d = list(set(points_2d))
1516+
p1 = points_2d[0]
1517+
p2 = points_2d[1]
1518+
# Build a thick polygon from shifted points
1519+
poly = pya.DPolygon(
1520+
[
1521+
p1,
1522+
p2,
1523+
p2 + direction,
1524+
p1 + direction,
1525+
]
1526+
)
1527+
visualise_point = port.signal_location
1528+
else:
1529+
poly = pya.DPolygon(points_2d)
1530+
1531+
region = pya.Region(poly.to_itype(dbu))
1532+
self.visualise_region(region, label, "simulation_ports", visualise_point)
1533+
else:
1534+
logging.warning(f"Port {port.number} has no polygon data in get_port_data(), skipping visualisation.")

0 commit comments

Comments
 (0)