Pulse envelopes, grids and trains¶
Wave/Envelope construction, temporal grids, pulse trains and hygiene helpers. Docstrings are the source of truth, rendered with
mkdocstrings (numpydoc style).
photonics_helper.pulse ¶
Pulse envelopes, temporal grids, and pulse trains.
Envelope-field convention
An :class:Envelope describes a normalized complex envelope A(t). The
absolute scale of A is whatever peak_amplitude the user chose, so
Wave.envelope_intensity (|A|²) and the metrics derived from it
(pulse_energy, peak_power) are in normalized envelope units, not
W/m², joules, or watts, unless a physical effective mode area is attached with
:meth:Wave.with_effective_area. Without one, peak_power/pulse_energy
emit a one-time :class:UserWarning and the visualization summary labels the
value as normalized. With an effective area A_eff the library uses
P = ½·n·c·ε₀·A_eff·|A|² (see :class:~photonics_helper.base.PeakPower).
SHAPE_FACTORS
module-attribute
¶
SHAPE_FACTORS: dict[str, float] = {'gaussian': 2 * sqrt(log(2)), 'sech': 2 * acosh(sqrt(2)), 'lorentzian': 2 * sqrt(sqrt(2) - 1), 'rectangular': 2.0}
Envelope ¶
shape
instance-attribute
¶
shape: Literal['gaussian', 'sech', 'lorentzian', 'rectangular', 'super-gaussian', 'triangular', 'parabolic', 'cosine', 'exponential', 'gauss-hermite', 'airy', 'custom']
from_fwhm
classmethod
¶
from_fwhm(shape: Literal['gaussian', 'sech', 'lorentzian', 'rectangular', 'super-gaussian', 'triangular', 'cosine', 'exponential', 'airy'], peak_amplitude: float, fwhm: Time) -> Self
Construct an Envelope from a desired full-width at half-maximum.
calc_width ¶
calc_width(level: float = 0.5) -> Time
Calculate the pulse width using linear interpolation at crossing points.
Finds the width between the widest pair of crossings where the
intensity envelope drops to level * peak_intensity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
float — fraction of peak to calculate width at.
|
0.5 gives FWHM, 1/e ≈ 0.368, 1/e² ≈ 0.135. Default 0.5. |
0.5
|
Returns:
| Name | Type | Description |
|---|---|---|
width |
Time — pulse width in seconds (use ``.as_ps`` etc. for display units).
|
|
apply_dispersion ¶
apply_dispersion(GDD: float = 0.0, TOD: float = 0.0, FOD: float = 0.0, N: int = 2 ** 12) -> Envelope
Apply group-delay dispersion (GDD), TOD, FOD in the frequency domain.
Multiplies the spectral amplitude by exp(−i·φ(ω)) where
φ(ω) = ½·GDD·Ω² + ⅙·TOD·Ω³ + ¹⁄₂₄·FOD·Ω⁴ and Ω is the
offset from the central angular frequency. Uses the same sign as
:meth:~photonics_helper.gnlse.SplitStepEngine._linear_step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
GDD
|
float — group-delay dispersion (ps²). Default 0.
|
|
0.0
|
TOD
|
float — third-order dispersion (ps³). Default 0.
|
|
0.0
|
FOD
|
float — fourth-order dispersion (ps⁴). Default 0.
|
|
0.0
|
N
|
int — number of points for the internal grid (default 2¹²).
|
|
2 ** 12
|
Returns:
| Type | Description |
|---|---|
Envelope — a new Envelope with the dispersion-applied field.
|
|
Notes
The returned envelope has shape="custom" and owns the numerical
field computed on an internal grid sized to contain the broadened
pulse (estimated from the input bandwidth and the requested GDD,
TOD, FOD; N controls the sampling resolution). Requests outside
that window are clamped to the edge values. The analytic parameters
of the input envelope no longer describe the broadened pulse, so
peak_amplitude and pulse_width are re-measured numerically
and the chirp is reset to zero (any input chirp is already baked
into the dispersed field).
visualize_2d ¶
visualize_2d(backend: Literal['plotly', 'matplotlib'] = 'plotly', N: int = 2 ** 12, show_phase: bool = True, show_fwhm: bool = True, figsize: tuple[float, float] | None = None, title: str | None = None, theme: Literal['light', 'dark'] = 'light')
Plot temporal intensity, spectral intensity, and phase.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
backend
|
"plotly" or "matplotlib" (default "plotly")
|
|
'plotly'
|
N
|
number of time points (default 2^12)
|
|
2 ** 12
|
show_phase
|
show instantaneous phase overlay (default True)
|
|
True
|
show_fwhm
|
show FWHM markers (default True)
|
|
True
|
figsize
|
figure size for matplotlib backend (default None)
|
|
None
|
title
|
optional title override (default uses shape name)
|
|
None
|
theme
|
"light" or "dark" (default "light")
|
|
'light'
|
visualize_3d ¶
visualize_3d(N: int = 2 ** 12, title: str | None = None, theme: Literal['light', 'dark'] = 'light')
Plot 3D spectrogram (time vs frequency vs intensity).
Shows how the frequency content evolves over time. Useful for visualizing chirp and time-frequency structure.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
N
|
number of time points (default 2^12)
|
|
2 ** 12
|
title
|
optional title override
|
|
None
|
theme
|
"light" or "dark" (default "light")
|
|
'light'
|
from_parabolic_asymptotic
classmethod
¶
from_parabolic_asymptotic(peak_amplitude: float, pulse_width: Time, gain: float, length: float, chirp: float = 0.0) -> Self
Construct a parabolic pulse with asymptotic amplifier chirp.
The chirp coefficient follows the asymptotic parabolic solution:
α ≈ 0.2726 × z × gain.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
peak_amplitude
|
A₀
|
|
required |
pulse_width
|
T₀
|
|
required |
gain
|
Small-signal gain coefficient (unitless or per-length as used in the amplifier model)
|
|
required |
length
|
Propagation length in the amplifier
|
|
required |
chirp
|
Additional chirp on top of the asymptotic value (default 0)
|
|
0.0
|
Wave ¶
central_frequency
cached
property
¶
central_frequency: float
Carrier angular frequency at the central wavelength (rad/s).
wavelength_nm
property
¶
wavelength_nm: NDArray
Absolute wavelength grid (nm) for each frequency sample on grid.w.
electric_field
property
¶
electric_field
Physical electric field (V/m) reconstructed from the envelope.
spectrum
cached
property
¶
spectrum: NDArray
Frequency-domain envelope obtained via the configured FFT backend.
pulse_energy ¶
pulse_energy() -> float
Pulse energy (or normalized integral ∫|A|²dt).
Returns:
| Type | Description |
|---|---|
float
|
Joules when an effective mode area has been attached with
:meth: |
calc_width ¶
calc_width(level: float = 0.5) -> Time
Calculate the pulse width using linear interpolation at crossing points.
Finds the width between the widest pair of crossings where the
intensity envelope drops to level * peak_intensity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
level
|
float — fraction of peak to calculate width at.
|
0.5 gives FWHM, 1/e ≈ 0.368, 1/e² ≈ 0.135. Default 0.5. |
0.5
|
Returns:
| Name | Type | Description |
|---|---|---|
width |
Time — pulse width in seconds (use ``.as_ps`` etc. for display units).
|
|
peak_power ¶
peak_power() -> float
Peak power (or normalized peak intensity max|A|²).
Returns:
| Type | Description |
|---|---|
float
|
Watts when an effective mode area has been attached with
:meth: |
**Unit hazard:** the return value changes by many orders of
|
|
magnitude depending on whether ``A_eff`` is attached. For a field
|
|
built as ``sqrt(5.0)``, ``peak_power()`` returns ``5.0`` without an
|
|
effective area and ``5.3e-13`` with one — the same field, 13 orders
|
|
of magnitude apart. ``add_ase_noise`` defaults ``reference_power``
|
|
to ``wave.peak_power()``, so passing a wave with an effective area
|
|
to one without silently changes the ASE level by 13 orders of
|
|
magnitude. Always check which convention you are in before using
|
|
the result.
|
|
with_effective_area ¶
with_effective_area(A_eff: Area) -> Self
Return a copy of this Wave bound to a physical mode area.
Once an effective area is attached, :meth:peak_power and
:meth:pulse_energy return physical watts and joules via the
intensity relation P = ½·n·c·ε₀·A_eff·|A|² (with
:attr:refractive_index as n). Without one they stay in
normalized envelope units.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
A_eff
|
Area — effective mode area (e.g. ``Area(80, "um^2")``).
|
|
required |
Returns:
| Type | Description |
|---|---|
Wave — a copy sharing this wave's field with the area attached.
|
|
average_power ¶
average_power(repetition_rate: Frequency) -> float
Average power = pulse energy × repetition_rate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
repetition_rate
|
Hz
|
|
required |
from_pulse_train
classmethod
¶
from_pulse_train(envelope: Envelope, central_wavelength: Wavelength, grid: TemporalGrid, repetition_rate: Frequency, n_pulses: int = 10, refractive_index: float = 1.0) -> Self
Construct a pulse train Wave from a single-envelope shape.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
envelope
|
The single-pulse envelope shape to repeat
|
|
required |
central_wavelength
|
Central wavelength of the carrier
|
|
required |
grid
|
TemporalGrid covering the full window (all pulses + padding)
|
|
required |
repetition_rate
|
Hz — spacing between consecutive pulses
|
|
required |
n_pulses
|
number of pulses (default 10)
|
|
10
|
refractive_index
|
background refractive index (default 1.0)
|
|
1.0
|
with_field ¶
with_field(field: NDArray) -> Self
Return this Wave with an explicit envelope-field override.
Used by :meth:from_pulse_train for precomputed multi-pulse fields.
time_bandwidth_product ¶
time_bandwidth_product() -> float
RMS time-bandwidth product. ≈0.707 for transform-limited Gaussian.
visualize ¶
visualize(t_unit: str = 's', w_unit: str = 'rad/s', t_scale: float = 1.0, w_scale: float = 1.0, show_electric_field: bool = False, show_phase: bool = True, show_spectrogram: bool = False, figsize: tuple[float, float] | None = None, save_path: str | None = None)
Plot a comprehensive overview of the pulse.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
t_unit
|
label for the time axis (e.g. "ps", "fs")
|
|
's'
|
w_unit
|
label for the frequency axis (e.g. "THz", "rad/ps")
|
|
'rad/s'
|
t_scale
|
multiply grid.t by this before plotting (e.g. 1e12 for ps)
|
|
1.0
|
w_scale
|
multiply grid.w by this before plotting
|
|
1.0
|
show_electric_field
|
add a panel with the real electric field
|
|
False
|
show_phase
|
overlay instantaneous phase on the temporal panel
|
|
True
|
show_spectrogram
|
add a spectrogram (STFT) panel
|
|
False
|
figsize
|
passed to plt.figure()
|
|
None
|
save_path
|
if given, save figure to this path
|
|
None
|
FROGTrace ¶
Represents a FROG trace I(ω, τ).
Attributes:
| Name | Type | Description |
|---|---|---|
trace |
2D array of shape (N_omega, N_tau)
|
The FROG trace (normalized if normalize=True in from_field). |
unnormalized_trace |
2D array of shape (N_omega, N_tau)
|
The raw trace before normalization (used for retrieval). |
omega |
angular frequency axis (rad/s), centered at 0.
|
|
tau |
delay axis (s), centered at 0.
|
|
dt |
time step (s).
|
|
dw |
frequency step (rad/s).
|
|
field |
reconstructed field E(t) (set after retrieval).
|
|
from_field
classmethod
¶
from_field(E_field: NDArray, dt: float, normalize: bool = True) -> FROGTrace
Generate a FROG trace from a complex electric field E(t).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
E_field
|
complex 1D array, the electric field on a uniform time grid.
|
|
required |
dt
|
time step in seconds.
|
|
required |
normalize
|
normalize trace to [0, 1] (default True).
|
|
True
|
Returns:
| Type | Description |
|---|---|
FROGTrace
|
|
visualize ¶
visualize(retrieved: FROGTrace | None = None, figsize: tuple[float, float] | None = None, save_path: str | None = None)
Plot the FROG trace and optionally the retrieved pulse.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
retrieved
|
optional FROGTrace with .field set (from retrieve()).
|
|
None
|
figsize
|
figure size.
|
|
None
|
save_path
|
if given, save figure to this path.
|
|
None
|
generate_trace ¶
generate_trace(E_field: NDArray, dt: float, normalize: bool = True) -> FROGTrace
Generate a SHG-FROG trace from an electric field.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
E_field
|
complex 1D array, electric field on uniform time grid.
|
|
required |
dt
|
time step in seconds.
|
|
required |
normalize
|
normalize trace to [0, 1] (default True).
|
|
True
|
Returns:
| Type | Description |
|---|---|
FROGTrace
|
|
fidelity ¶
fidelity(trace1: FROGTrace, trace2: FROGTrace) -> float
Compute FROG fidelity between two traces.
fidelity = 1 - ||I1 - I2|| / ||I1||
Returns:
| Type | Description |
|---|---|
float in [0, 1], where 1 = perfect match.
|
|
retrieve ¶
retrieve(trace: FROGTrace, max_iter: int = 100, tol: float = 0.0001, verbose: bool = True, *, seed: int | None = 0, n_restarts: int = 5) -> FROGTrace
Retrieve the electric field E(t) from a FROG trace using PCGPA.
Implements the generalized-projections / PCGPA material-constraint step: after replacing the trace magnitude with the measurement (keeping the phase), the new field is the least-squares solution
E_new(t) = Σ_τ G'(t, τ)·E*(t+τ) / Σ_τ |E(t+τ)|²
for the bilinear SHG signal G(t, τ) = E(t)E(t+τ). Retrieval is
initialized from the dominant SVD component of the trace plus one or more
random complex fields (seeded for reproducibility); the lowest-error result
is returned.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trace
|
FROGTrace — the measured (or generated) trace.
|
|
required |
max_iter
|
maximum iterations per restart (default 100).
|
|
100
|
tol
|
convergence tolerance on the change in the normalized FROG error
|
(default 1e-4). |
0.0001
|
verbose
|
print iteration progress (default True).
|
|
True
|
seed
|
RNG seed for the random initialization (default 0). ``None`` uses
|
fresh entropy. |
0
|
n_restarts
|
number of random restarts (default 5). Together with the
|
SVD initialization these are ranked by FROG error and the lowest-error result is returned. |
5
|
Returns:
| Type | Description |
|---|---|
FROGTrace with ``.field`` set to the retrieved E(t).
|
|
Notes
SHG-FROG cannot distinguish E(t) from E*(−t) or a global phase, so
compare retrieved and reference fields up to those symmetries (comparing
traces is ambiguity-free).