"""Computes the laser power in an interferometer output or the power from an electrical
signal."""
import logging
import numpy as np
from finesse.components.node import Node
from finesse.detectors import pdtypes
from finesse.detectors.general import MaskedDetector
from finesse.parameter import float_parameter
LOGGER = logging.getLogger(__name__)
[docs]@float_parameter("f", "Frequency")
@float_parameter("phase", "Phase")
class PowerDetectorDemod1(MaskedDetector):
"""Represents a power detector with one RF demodulation. It calculates the RF beat
power at a node in Watts of optical power.
If no demodulation phase is specified then this detector outputs a
complex value `I+1j*Q`.
Parameters
----------
name : str
Name of newly created power detector.
node : :class:`.Node`
Node to read output from.
f : float
Demodulation frequency in Hz
phase : float, optional
Demodulation phase in degrees
"""
def __init__(self, name: str, node: Node, f, phase=None, pdtype=None):
self.pdtype = pdtypes.get_pdtype(pdtype)
if f is None:
raise ValueError("A demodulation frequency must be provided")
if phase is not None:
self.__mode = "mixer_real"
dtype = np.float64
else:
self.__mode = "mixer_complex"
dtype = np.complex128
self._beats = None
MaskedDetector.__init__(self, name, node, dtype=dtype, unit="W", label="Power")
self.f = f
self.phase = phase
def _get_workspace(self, sim):
from finesse.detectors.compute.power import PD1Workspace
return PD1Workspace(self, sim, self.f, self.phase, pdtype=self.pdtype)
[docs]@float_parameter("f1", "Frequency 1")
@float_parameter("phase1", "Phase 1")
@float_parameter("f2", "Frequency 2")
@float_parameter("phase2", "Phase 2")
class PowerDetectorDemod2(MaskedDetector):
"""Represents a power detector with two RF demodulation. It calculates the RF beat
power at a node in Watts of optical power.
If no demodulation phase is specified for the final demodulation
this detector outputs a complex value `I+1j*Q` where I and Q are
the in-phase and quadrature parts of the signal.
Parameters
----------
name : str
Name of newly created power detector.
node : :class:`.Node`
Node to read output from.
f1 : float
First demodulation frequency in Hz
phase1 : float
First demodulation phase in degrees
f2 : float
Second demodulation frequency in Hz
phase2 : float, optional
Second demodulation phase in degrees
"""
def __init__(self, name: str, node: Node, f1, phase1, f2, phase2=None, pdtype=None):
self.pdtype = pdtypes.get_pdtype(pdtype)
if phase2 is not None:
self.__mode = "mixer_real"
dtype = np.float64
else:
self.__mode = "mixer_complex"
dtype = np.complex128
self._beats = None
MaskedDetector.__init__(self, name, node, dtype=dtype, unit="W", label="Power")
self.f1 = f1
self.phase1 = phase1
self.f2 = f2
self.phase2 = phase2
def _get_workspace(self, sim):
from finesse.detectors.compute.power import PD2Workspace
return PD2Workspace(
self, sim, self.f1, self.phase1, self.f2, self.phase2, pdtype=self.pdtype
)
[docs]class PowerDetector(MaskedDetector):
"""Represents a power detector with no RF demodulations. It calculates the DC laser
power at a node in Watts of optical power.
Parameters
----------
name : str
Name of newly created power detector.
node : :class:`.Node`
Node to read output from.
"""
def __init__(self, name: str, node: Node, *, pdtype=None):
MaskedDetector.__init__(
self, name, node, dtype=np.float64, unit="W", label="Power"
)
self.pdtype = pdtypes.get_pdtype(pdtype)
def _get_workspace(self, sim):
from finesse.detectors.compute.power import PD0Workspace
return PD0Workspace(self, sim, pdtype=self.pdtype)