diff --git a/src/scgenerator/physics/pulse.py b/src/scgenerator/physics/pulse.py index ca9de62..ba41134 100644 --- a/src/scgenerator/physics/pulse.py +++ b/src/scgenerator/physics/pulse.py @@ -488,6 +488,41 @@ def gaussian_pulse(t: np.ndarray, t0: float, P0: float): return np.sqrt(P0) * np.exp(-((t / t0) ** 2)) +def pulse_envelope( + t: np.ndarray, + fwhm: float, + peak_power: float | None = None, + energy: float | None = None, + shape: str = "gaussian", +) -> np.ndarray: + """ + convenience function to create a pulse envelope + + Parameters + ---------- + t : np.ndarray + time array + fwhm : float + full width at half maximum of intensity (although the amplitude envelope is returned) + peak_power, energy : float | None, optional + provide either peak power or energy information + shape : {'gaussian', 'sech'} + pulse shape, by default Gaussian + """ + if peak_power is None and energy is None: + raise ValueError("please provide either peak power or energy data") + t0 = fwhm_to_T0_fac[shape] * fwhm + if peak_power is None: + peak_power = E0_to_P0(energy, t0, shape) + + if shape == "gaussian": + return gaussian_pulse(t, t0, peak_power) + elif shape == "sech": + return sech_pulse(t, t0, peak_power) + else: + raise ValueError(f"shape {shape} not recognized") + + def photon_number(spec2: np.ndarray, w: np.ndarray, dw: float, gamma: float) -> float: return np.sum(1 / gamma * spec2 / w * dw) diff --git a/tests/test_pulse.py b/tests/test_pulse.py new file mode 100644 index 0000000..dcf9fa2 --- /dev/null +++ b/tests/test_pulse.py @@ -0,0 +1,11 @@ +import numpy as np +import pytest + +import scgenerator as sc + + +def test_pulse_envelope(): + t = np.linspace(-100, 100, 2049) + + assert np.trapz(sc.pulse.pulse_envelope(t, 10, energy=3) ** 2, x=t) == pytest.approx(3) + assert (sc.pulse.pulse_envelope(t, 10, peak_power=3) ** 2).max() == pytest.approx(3)