Source code for herosdevices.hardware.menlo.dual_laser_lock

"""HERO driver for a dual-wavelength laser-lock channel of a Menlo Systems frequency comb."""

from herosdevices.helper import mark_driver

from .laser_lock import LaserLock
from .mixins import FrequencyDistribution, Tec
from .ofc import OFC


[docs] @mark_driver( name="Menlo Dual Laser Lock", info="Dual-wavelength laser-lock channel of a Menlo Systems frequency comb, via QWebChannel", state="alpha", additional_docs=["/tutorials/menlo_ofc.rst"], product_page="https://www.menlosystems.com/", ) class DualLaserLock(LaserLock): """Driver for a dual-wavelength laser-lock channel of a Menlo Systems frequency comb. Some CW channels (e.g. "CW 507 / 1014 / 1542", "CW 578 / 1157 / 1542" in Menlo's vendor software) lock two wavelengths through one shared `dds`/`mainControls`/`frequencyControl`/`amp*` node set, but have two separate `frequencyDistribution<wavelength>` blocks (one per wavelength) instead of a single plain `frequencyDistribution`, plus a single-wavelength thermo-electric-cooler node. Deploying plain :py:class:`~herosdevices.hardware.menlo.LaserLock` against one of these channels fails, since its `frequencyDistribution.*` properties hardcode a node name these channels don't have - use `DualLaserLock` instead, which composes both wavelength-suffixed nodes plus the TEC node explicitly. Args: ofc: The OFC HERO this dual-wavelength channel belongs to. funclayer_identifier: Identifier of the module's functional-layer settings object, e.g. "cw507_1014" for the sub-tree at `functionalLayer.cw507_1014Settings`. primary_frequency_distribution_node: Relative node name of the first wavelength's frequency-distribution block (mapped to :py:attr:`frequency_distribution`, inherited from `LaserLock`), e.g. `"frequencyDistribution507"`. secondary_frequency_distribution_node: Relative node name of the second wavelength's frequency-distribution block (mapped to :py:attr:`secondary_frequency_distribution`), e.g. `"frequencyDistribution1014"`. tec_node: Relative node name of the channel's thermo-electric-cooler block, e.g. `"spt1014Tec"`. amp_node: Relative node name of the channel's shared laser-diode current-control block (`amp*`), see :py:class:`~herosdevices.hardware.menlo.LaserLock`. observables: Additional observables to poll, merged on top of `DEFAULT_OBSERVABLES`, see :py:class:`~herosdevices.hardware.menlo.functional_layer.FunctionalLayerModule`. """ def __init__( self, ofc: OFC, funclayer_identifier: str, primary_frequency_distribution_node: str, secondary_frequency_distribution_node: str, tec_node: str, amp_node: str | None = None, observables: dict[str, dict[str, str]] | None = None, ) -> None: LaserLock.__init__( self, ofc, funclayer_identifier, frequency_distribution_node=primary_frequency_distribution_node, amp_node=amp_node, observables=observables, ) self.secondary_frequency_distribution = FrequencyDistribution(self, secondary_frequency_distribution_node) self.tec = Tec(self, tec_node)