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)