from typing import Optional from turtle import shape import nazca as nd import numpy as np import math from .taper import taper_xs2xs from ...routing import Route from ...geometry import * from ....technologies import * class PBS_3wg: """ PBS 3wg primitive component. This component builds the PBS 3wg layout cell. Parameters ---------- name : Optional[str], optional Unique identifier for the device cell. Default is None. xs : str, optional Layer or cross-section name used by the device. Default is 'strip'. Lcp : float, optional Length parameter in microns. Default is 11.7. w1_tp : float, optional Value for the w1_tp parameter. Default is 0.55. w2_tp : float, optional Value for the w2_tp parameter. Default is 0.3. w_m : float, optional Width parameter in microns. Default is 0.45. gap : float, optional Spacing or gap parameter in microns. Default is 0.25. R_bend : int, optional Radius parameter in microns. Default is 20. A_bend : float, optional Angle parameter in degrees. Default is 7.5. w_wg : float, optional Width parameter in microns. Default is 0.45. show_pins : bool, optional Whether to draw pin markers in the generated layout. Default is False. sharp_patch : bool, optional Whether to add geometry patches for sharp corners or cladding continuity. Default is True. """ def __init__(self, name: Optional[str] = None, xs: str = 'strip', Lcp: float = 11.7 , w1_tp: float = 0.55, w2_tp: float = 0.3, w_m: float = 0.45, gap: float = 0.25, R_bend: int = 20, A_bend: float = 7.5, w_wg: float = 0.45, show_pins: bool = False, sharp_patch: bool = True ) -> None: self.Lcp = Lcp self.xs = xs self.w1_tp = w1_tp self.w2_tp = w2_tp self.w_m = w_m self.gap = gap self.R_bend = R_bend self.A_bend = A_bend self.w_wg = w_wg self.name = name if (self.name==None): self.instantiate = False else : self.instantiate = True self.cell = self.generate_gds(show_pins=show_pins, sharp_patch=sharp_patch) def generate_gds(self,show_pins=False,sharp_patch = True): w_crack = 0.002 with nd.Cell(instantiate=self.instantiate,name=self.name) as C: nd.strt(length=self.Lcp,width=self.w_m,xs=self.xs).put(-self.Lcp/2,0,0) tp_U = nd.taper(length=self.Lcp,width1=self.w1_tp,width2=self.w2_tp,xs=self.xs,shift=-(self.w1_tp-self.w2_tp)/2).put(-self.Lcp/2,self.w1_tp/2+self.gap+self.w_m/2,0) tp_D = nd.taper(length=self.Lcp,width1=self.w2_tp,width2=self.w1_tp,xs=self.xs,shift=(self.w2_tp-self.w1_tp)/2).put(-self.Lcp/2,-self.w2_tp/2-self.gap-self.w_m/2,0) Att_U = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w1_tp).put(tp_U.pin['a0'],flip=1) Att_U = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w1_tp).put(flip=0) Att_D = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w2_tp).put(tp_D.pin['a0'],flip=0) Att_D = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w2_tp).put(flip=1) if (self.w_wg!=None and self.w_wg>0) : Att_D = nd.taper(length=5,width1=self.w2_tp,width2=self.w_wg,xs=self.xs).put(Att_D.pin['b0']) Att_U = nd.taper(length=5,width1=self.w1_tp,width2=self.w_wg,xs=self.xs).put(Att_U.pin['b0']) ## revised in 2026.06.07 by Qin Yue # legacy: nd.Pin(name='a1',pin=Att_U.pin['b0']).put() nd.Pin(name='opt_a1',pin=Att_U.pin['b0'],type="optical:").put() ## revised in 2026.06.07 by Qin Yue # legacy: nd.Pin(name='a2',pin=Att_D.pin['b0']).put() nd.Pin(name='opt_a2',pin=Att_D.pin['b0'],type="optical:").put() nd.strt(length=w_crack,width=self.w_wg,xs=self.xs).put(Att_U.pin['b0'].x-w_crack/2,Att_U.pin['b0'].y,0) nd.strt(length=w_crack,width=self.w_wg,xs=self.xs).put(Att_D.pin['b0'].x-w_crack/2,Att_D.pin['b0'].y,0) Att_U = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w2_tp).put(tp_U.pin['b0'],flip=0) Att_U = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w2_tp).put(flip=1) Att_D = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w1_tp).put(tp_D.pin['b0'],flip=1) Att_D = nd.bend(angle=self.A_bend,radius=self.R_bend,xs=self.xs,width=self.w1_tp).put(flip=0) if (self.w_wg!=None and self.w_wg>0) : Att_D = nd.taper(length=5,width1=self.w1_tp,width2=self.w_wg,xs=self.xs).put(Att_D.pin['b0']) Att_U = nd.taper(length=5,width1=self.w2_tp,width2=self.w_wg,xs=self.xs).put(Att_U.pin['b0']) ## revised in 2026.06.07 by Qin Yue # legacy: nd.Pin(name='b1',pin=Att_U.pin['b0']).put() nd.Pin(name='opt_b1',pin=Att_U.pin['b0'],type="optical:").put() ## revised in 2026.06.07 by Qin Yue # legacy: nd.Pin(name='b2',pin=Att_D.pin['b0']).put() nd.Pin(name='opt_b2',pin=Att_D.pin['b0'],type="optical:").put() nd.strt(length=w_crack,width=self.w_wg,xs=self.xs).put(Att_U.pin['b0'].x-w_crack/2,Att_U.pin['b0'].y,0) nd.strt(length=w_crack,width=self.w_wg,xs=self.xs).put(Att_D.pin['b0'].x-w_crack/2,Att_D.pin['b0'].y,0) if (show_pins): nd.put_stub() return C