Source code for herosdevices.hardware.menlo.fxe
"""HERO driver for the frequency-counter (FXE) module of a Menlo Systems frequency comb."""
from herosdevices.helper import mark_driver
from .functional_layer import FunctionalLayerModule
from .ofc import OFC
[docs]
@mark_driver(
name="Menlo FXE",
info="Frequency-counter module of a Menlo Systems frequency comb, via QWebChannel",
state="alpha",
additional_docs=["/tutorials/menlo_ofc.rst"],
product_page="https://www.menlosystems.com/",
)
class FXE(FunctionalLayerModule):
"""Driver for the frequency-counter (FXE) module of a Menlo Systems frequency comb.
Wraps the OFC's `functionalLayer.fxeSettings` sub-tree, a fixed, singleton module (there is only one FXE
counter per OFC, so unlike :py:class:`~herosdevices.hardware.menlo.DDS`/
:py:class:`~herosdevices.hardware.menlo.LaserLock` there is no `funclayer_identifier` to select). Confirmed
reachable directly at `functionalLayer.fxeSettings` (the same object is also reachable via
`modules["SYNCRO3U"].functionalLayer.fxeSettings`).
Unlike the other functional-layer modules, FXE has no lock loop or DDS - it is a pure 16-channel
frequency counter. Use :py:meth:`channel_frequency` to read a specific channel; which channel carries
which physical beat signal is deployment-specific, so there is no fixed per-channel `DEFAULT_OBSERVABLES`
here - pass `observables` to poll the channels relevant to your comb.
Args:
ofc: The OFC HERO this counter belongs to.
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, observables: dict[str, dict[str, str]] | None = None) -> None:
FunctionalLayerModule.__init__(self, ofc, "functionalLayer.fxeSettings", observables=observables)
[docs]
def channel_frequency(self, channel: int) -> float:
"""Read the currently measured frequency of one counter channel.
Args:
channel: Channel number, 1-16 (matching the device's `channel01`-`channel16` node names).
Returns:
The channel's currently measured frequency, in Hz.
"""
return self.ofc.get_node(self._path(f"counterFrequencies.channel{channel:02d}"))
@property
def rate(self) -> int:
"""The counter's update rate."""
return self.ofc.get_node(self._path("counterSettings.rate"))
@rate.setter
def rate(self, rate: int) -> None:
self.ofc.set_node(self._path("counterSettings.rate"), rate)