Source code for phise.modules.phase

"""Phase operations: shifting, wrapping and random perturbations.

Utility functions to apply wavelength-dependent phase shifts, wrap phases
into an interval, and add Gaussian noise.
"""
from astropy import units as u
import numpy as np
import numba as nb
from typing import Union

@nb.njit()
def shift_jit(
    ψ: Union[complex, np.ndarray],
    δφ: Union[float, np.ndarray],
    λ: float,
) -> Union[complex, np.ndarray]:
    """Phase rotation (njit) of an electric field.

    Args:
        ψ: Complex electric field (scalar or array).
        δφ: Applied phase shift (same unit as ``λ`` once converted).
        λ: Wavelength (scalar, in length units).

    Returns:
        Field with phase shift applied, same shape as ``ψ``.
    """
    return ψ * np.exp(1j * 2 * np.pi * δφ / λ)

[docs] def shift( ψ: Union[complex, np.ndarray], δφ: u.Quantity, λ: u.Quantity, ) -> Union[complex, np.ndarray]: """Apply a phase shift with unit handling. Converts ``Quantity`` inputs to numeric values then calls :func:`shift_jit`. Args: ψ: Complex electric field (scalar or array). δφ: Phase shift (length ``Quantity``, e.g. meters). λ: Wavelength (length ``Quantity``) used in 2π δφ/λ. Returns: Field with phase shift applied, same shape as ``ψ``. """ δφ = δφ.to(λ.unit).value λ = λ.value return shift_jit(ψ, δφ, λ)
[docs] def bound(φ: u.Quantity, λ: u.Quantity) -> u.Quantity: """Wrap a phase into [0, λ[ while preserving units. Args: φ: Phase (length ``Quantity``) to wrap. λ: Wavelength (length ``Quantity``) defining the interval. Returns: Wrapped phase in [0, λ[ with the unit of ``φ``. """ return bound_jit(φ.value, λ.to(φ.unit).value) * φ.unit
@nb.njit() def bound_jit(φ: float, λ: float) -> float: """Wrap a scalar phase into [0, λ[ (njit version). Args: φ: Scalar phase to wrap. λ: Scalar wavelength defining the interval. Returns: Wrapped phase in [0, λ[ (implicit same unit as inputs). """ return np.mod(φ, λ)
[docs] def perturb(φ: np.ndarray, rms: u.Quantity) -> u.Quantity: """Add Gaussian noise to phases with standard deviation ``rms``. Args: φ: Array of phases as ``Quantity`` (all with the same unit). rms: Noise standard deviation, same unit as ``φ``. Returns: ``Quantity`` array of the same shape as ``φ`` with noisy phases. """ rms = rms.to(φ.unit).value err = np.random.normal(0, rms, size=len(φ)) * φ.unit return φ + err