Source code for gdsfactory.components.coh_tx_single_pol

from __future__ import annotations

import gdsfactory as gf
from gdsfactory.cell import cell
from gdsfactory.component import Component
from gdsfactory.routing.get_route import get_route
from gdsfactory.typings import ComponentSpec, CrossSectionSpec

default_mzm = dict(
    component="mzi",
    settings=dict(
        straight_x_top="straight_pin",
        cross_section_x_top="xs_pin",
        delta_length=10.0,
    ),
)


[docs] @cell def coh_tx_single_pol( balanced_phase_shifters: bool = False, mzm_y_spacing: float = 50.0, phase_shifter: ComponentSpec = "straight_pin", phase_shifter_length: float = 100.0, mzm_ps_spacing: float = 40.0, splitter: ComponentSpec = "mmi1x2", combiner: ComponentSpec | None = None, mzm: ComponentSpec = default_mzm, mzm_length: float = 200.0, with_pads: bool = False, xspacing: float = 40.0, input_coupler: ComponentSpec | None = None, output_coupler: ComponentSpec | None = None, pad_array: ComponentSpec = "pad_array", cross_section: CrossSectionSpec = "xs_sc", **kwargs, ) -> Component: """MZM-based single polarization coherent transmitter. Args: balanced_phase_shifters: True adds phase sifters after the MZM at both the I and Q arms. False, only adds Q arm has a phase shifter. mzm_y_spacing: vertical spacing between the bottom of the I MZM and the top of the Q MZM. phase_shifter: phase_shifter spec. phase_shifter_length: length of the phase shifter. mzm_ps_spacing: spacing between the end of the mzm and the phase shifter. splitter: splitter spec. combiner: combiner spec. mzm: Mach-Zehnder modulator spec. mzm_length: length of the MZMs. xspacing: horizontal spacing between the splitter and combiner and the mzm. input_coupler: Optional coupler to add before the splitter. output_coupler: Optional coupler to add after the combiner. pad_array: array of pads spec. cross_section: for routing (splitter to mzms and mzms to combiners). kwargs: cross_section settings. .. code:: ___ mzm_i __ ps_i__ | | | | | | (in_coupler)---splitter==| |==combiner---(out_coupler) | | | | |___ mzm_q __ ps_q_| """ from gdsfactory.components.straight import straight as straight_function combiner = combiner or splitter pad_array = dict(component=pad_array, settings=dict(columns=1, rows=1)) c = Component() mzm_mod_p = gf.get_component(mzm, length_x=mzm_length) mzm_i = c << mzm_mod_p mzm_q = c << mzm_mod_p # Separate the two mzms so they don't overlap mzm_q.movey(mzm_i.ymin - mzm_y_spacing - mzm_q.ymax) phase_shifter = gf.get_component(phase_shifter, length=phase_shifter_length) if balanced_phase_shifters: ps_i = c << phase_shifter else: # only the q arm has a phase shifter straight = straight_function( length=phase_shifter_length, cross_section=cross_section, **kwargs ) ps_i = c << straight ps_q = c << phase_shifter # Connect to the right ports if mzm_ps_spacing <= 0.0: ps_i.connect("o1", mzm_i.ports["o2"]) ps_q.connect("o1", mzm_q.ports["o2"]) else: straight_conn = straight_function( length=mzm_ps_spacing, cross_section=cross_section, **kwargs ) straight_i = c << straight_conn straight_q = c << straight_conn straight_i.connect("o1", mzm_i.ports["o2"]) straight_q.connect("o1", mzm_q.ports["o2"]) ps_i.connect("o1", straight_i.ports["o2"]) ps_q.connect("o1", straight_q.ports["o2"]) # ------------ Splitters and combiners --------------- splitter = gf.get_component(splitter) sp = c << splitter sp.x = mzm_q.xmin - xspacing sp.y = (mzm_i.ports["o1"].y + mzm_q.ports["o1"].y) / 2 route = get_route( sp.ports["o2"], mzm_i.ports["o1"], cross_section=cross_section, with_sbend=False, **kwargs, ) c.add(route.references) route = get_route( sp.ports["o3"], mzm_q.ports["o1"], cross_section=cross_section, with_sbend=False, **kwargs, ) c.add(route.references) combiner = gf.get_component(combiner) comb = c << combiner comb.mirror() comb.x = ps_q.xmax + xspacing comb.y = (mzm_i.ports["o2"].y + mzm_q.ports["o2"].y) / 2 route = get_route( comb.ports["o2"], ps_i.ports["o2"], cross_section=cross_section, with_sbend=False, **kwargs, ) c.add(route.references) route = get_route( comb.ports["o3"], ps_q.ports["o2"], cross_section=cross_section, with_sbend=False, **kwargs, ) c.add(route.references) if input_coupler is not None: # Add input coupler in_coupler = gf.get_component(input_coupler) in_coup = c << in_coupler in_coup.connect("o1", sp.ports["o1"]) else: c.add_port("o1", port=sp.ports["o1"]) if output_coupler is not None: # Add output coupler output_coupler = gf.get_component(output_coupler) out_coup = c << output_coupler out_coup.connect("o1", comb.ports["o1"]) else: c.add_port("o2", port=comb.ports["o1"]) c.add_ports(ps_i.get_ports_list(port_type="electrical"), prefix="ps_i_") c.add_ports(ps_q.get_ports_list(port_type="electrical"), prefix="ps_q_") c.add_ports(mzm_i.get_ports_list(port_type="electrical"), prefix="mzm_i_") c.add_ports(mzm_q.get_ports_list(port_type="electrical"), prefix="mzm_q_") return c
if __name__ == "__main__": c = coh_tx_single_pol() c.show(show_ports=True)