fintrace.utils ============== .. py:module:: fintrace.utils .. autoapi-nested-parse:: A module for utility functions to help populate both finesse and gtrace models. Attributes ---------- .. autoapisummary:: fintrace.utils.FRONT_PORTS fintrace.utils.BACK_PORTS fintrace.utils.ALL_PORTS Functions --------- .. autoapisummary:: fintrace.utils._is_front_port fintrace.utils._is_back_port fintrace.utils._norm_pos fintrace.utils._get_thickness fintrace.utils._get_n fintrace.utils._edge_exists fintrace.utils._bs_back_exit_xy fintrace.utils._bs_back_entry_xy fintrace.utils._add_mirror_edge fintrace.utils._add_bs_edge fintrace.utils.calculate_space_angle fintrace.utils.calculate_angle fintrace.utils.calculate_length fintrace.utils.set_params fintrace.utils.pop_beamsplitter fintrace.utils.pop_mirror fintrace.utils.pop_lens fintrace.utils.pop_laser fintrace.utils.pop_cavity fintrace.utils.pop_pd Module Contents --------------- .. py:data:: FRONT_PORTS :type: frozenset[str] .. py:data:: BACK_PORTS :type: frozenset[str] .. py:data:: ALL_PORTS :type: frozenset[str] .. py:function:: _is_front_port(port: str) -> bool .. py:function:: _is_back_port(port: str) -> bool .. py:function:: _norm_pos(params: dict) -> tuple[float, float] Return (x, y) from *params['Position']*, normalising keys to upper-case in-place. Works for both ``{'x': …, 'y': …}`` and ``{'X': …, 'Y': …}``. .. py:function:: _get_thickness(params: dict, default: float = 0.005) -> float Return substrate thickness from component params, with a safe fallback. .. py:function:: _get_n(params: dict, default: float = 1.45) -> float Return refractive index from component params. .. py:function:: _edge_exists(graph: dict, name: str, port1: str, connect: str, port2: str) -> bool Return True if either direction of this space is already in *graph*. .. py:function:: _bs_back_exit_xy(x0: float, y0: float, port: str, thickness: float, n: float, aoi_deg: float, norm_angle_deg: float) -> tuple[float, float] **port1 side** — AR surface exit point for a beam travelling HR → AR. Starting from the HR surface centre (*x0*, *y0*), follow the refracted central ray through the substrate to find where it exits the AR surface. This is the correct *start* of the free-space segment after a Back port. Convention: Back1 → refracted toward the +α_sub side. Back2 → refracted toward the −α_sub side. Back → straight through (normal incidence). .. py:function:: _bs_back_entry_xy(x_start: float, y_start: float, x_hr: float, y_hr: float, norm_angle_deg: float, thickness: float) -> tuple[float, float] **port2 side** — AR surface entry point for the incoming beam. Finds where the ray travelling from (*x_start*, *y_start*) toward the connected component's HR centre (*x_hr*, *y_hr*) intersects the AR surface plane of that component. This is the correct *end* of the free-space segment before a Back port. The AR surface plane passes through ``HR_centre + thickness * n̂_AR`` with outward normal ``n̂_AR = (cos(normAngle+180°), sin(normAngle+180°))``. .. py:function:: _add_mirror_edge(graph: dict, name: str, port1: str, connect: str, port2: str, self_params: dict, other_params: dict) -> None Compute the space length for a mirror (or lens / wedge-mirror) edge and insert it into *graph*. For Back-family ports the substrate thickness is subtracted from the centre-to-centre distance, because the Back surface is displaced inward by exactly one thickness along the surface normal. Does nothing if the edge already exists in either direction. .. py:function:: _add_bs_edge(graph: dict, name: str, port1: str, connect: str, port2: str, self_params: dict, other_params: dict, info: dict) -> None Compute the space length for a beamsplitter edge and insert it into *graph*. For Back-family ports the *effective* XY position of the port is used port1 Back ports use :func:`_bs_back_exit_xy` (AR exit point of the outgoing ray); port2 Back ports use :func:`_bs_back_entry_xy` (ray-plane intersection of the incoming beam with the connected AR surface). *info* must contain at least ``'normAngle'`` and ``'AOI'`` (degrees). Does nothing if the edge already exists in either direction. .. py:function:: calculate_space_angle(comp: list, compForward: list = None, compBackward: list = None, degree: bool = False, verbose: bool = False) -> dict Calculate angle of incidence and spaces between optics. :param comp: name, X, Y :type comp: list :param compForward: name, X, Y :type compForward: list :param compBackward: name, X, Y. Defaults to None. :type compBackward: list, optional :param verbose: Print helpful messages. Defaults to False. :type verbose: bool, optional :returns: AOI, space to each component. :rtype: dict .. py:function:: calculate_angle(comp1: list, comp2: list) -> float .. py:function:: calculate_length(comp1: list, comp2: list) -> float .. py:function:: set_params(component, parameters) .. py:function:: pop_beamsplitter(name: str, mirror_params: dict, graph: dict, all_mirrors: dict) -> Tuple[cosmicexplorer.finesse.components.ThickBeamsplitter, dict] Build a ThickBeamsplitter, populate *graph* with space lengths. *connections* may use any combination of Front / Front1 / Front2 and Back / Back1 / Back2 port names. At minimum two connections from the same face-family (both fronts or both backs) are needed to derive the normal angle automatically; otherwise *normAngle* must be supplied in *mirror_params*. .. py:function:: pop_mirror(name: str, mirror_params: dict, graph: dict, all_mirrors: dict) -> Tuple[cosmicexplorer.finesse.components.ThickMirror, dict] Build a ThickMirror (wedge variant) and populate *graph*. Accepts ``Front`` / ``Front1`` / ``Front2`` and ``Back`` / ``Back1`` / ``Back2`` port names interchangeably. Back ports subtract the substrate thickness from the centre-to-centre length. .. py:function:: pop_lens(name: str, mirror_params: dict, graph: dict, all_mirrors: dict) -> Tuple[cosmicexplorer.finesse.components.ThickMirror, dict] Build a ThickMirror used as a lens and populate *graph*. Thin-lens mode is selected when ``'Focal Length'`` is present in *mirror_params*. Otherwise a thick-lens model is constructed from ``Rc: {Front: …, Back: …}``. Accepts ``Front`` / ``Front1`` / ``Front2`` and ``Back`` / ``Back1`` / ``Back2`` port names. Back ports subtract the substrate thickness from the computed space length. .. py:function:: pop_laser(name: str, mirror_params: dict, graph: dict, all_mirrors: dict) -> Tuple[cosmicexplorer.finesse.components.Laser, dict] Build a Laser and register its outgoing space in *graph*. .. py:function:: pop_cavity(name: str, params: dict, components, model) -> cosmicexplorer.finesse.components.Cavity Build a Cavity and add it to *model*. .. py:function:: pop_pd(name: str, params: dict, components, model) -> finesse.detectors.PowerDetector Build a PowerDetector (or demodulated variant) and add it to *model*.