solprop.processing.coherence#

First-order coherence across an ensemble of noise realisations.

The quantity that says whether a supercontinuum is reproducible from shot to shot: the modulus of the normalised cross-correlation of the spectra of independent realisations, at each frequency (J. M. Dudley and S. Coen, Optics Letters 27, 1180 (2002), doi:10.1364/OL.27.001180).

The definition here is the unbiased one over distinct pairs, which is one for identical realisations and zero, in the mean, for independent ones. A sum over every ordered pair, the diagonal i == j included, would carry the self-terms in its numerator and tend to 1/N rather than to zero for a fully incoherent ensemble.

Functions

g12(spectra)

Return the first-order coherence of an ensemble of complex spectra.

g12_of(outputs, *[, plane, z, modes, band])

Return the first-order coherence of an ensemble of saved runs.

solprop.processing.coherence.g12(spectra)[source]#

Return the first-order coherence of an ensemble of complex spectra.

\[g_{12}(\omega) = \frac{\left| \sum_{i \neq j} \tilde E_i^{*}(\omega) \tilde E_j(\omega) \right|} {(N - 1) \sum_i \left| \tilde E_i(\omega) \right|^2}\]

evaluated with the identity \(\sum_{i \neq j} \tilde E_i^{*} \tilde E_j = \left| \sum_i \tilde E_i \right|^2 - \sum_i \left| \tilde E_i \right|^2\), which costs one pass over the ensemble rather than \(N^2\) slices. Identical realisations give exactly one; independent ones give zero in the mean, because the self-terms the identity removes are the only ones that survive the average.

Parameters:
spectranumpy.ndarray

Complex spectra of the ensemble, shape (n_realisations, ..., n_x), with at least two realisations along the leading axis.

Returns:
numpy.ndarray

The coherence, shape (...), between 0 and 1. A frequency at which every realisation is empty gives nan.

Raises:
solprop.exceptions.OutputError

If fewer than two realisations are given.

Examples

>>> import numpy as np
>>> from solprop.processing.coherence import g12
>>> one = np.array([1.0 + 0.0j, 2.0 + 0.0j])
>>> g12(np.stack([one, one])).round(12).tolist()
[1.0, 1.0]
solprop.processing.coherence.g12_of(outputs, *, plane=None, z=None, modes=None, band='active')[source]#

Return the first-order coherence of an ensemble of saved runs.

Every run must have been computed on the same grid and saved at the same planes; the spectra are read through solprop.processing.fields.get_spectrum(), so the ensemble may mix memory and HDF5 handlers.

Parameters:
outputssequence of solprop.output.schema.Output

The ensemble, at least two opened handlers.

planeint or None

Index of the plane wanted, negative from the end; with neither plane nor z, every plane is used and the result carries a leading n_z axis.

zfloat or None

Position of the plane wanted, m.

modesint, sequence of int, ‘sum’ or None

Which modes to report; 'sum' is refused, as it is for any complex amplitude.

band{‘active’, ‘all’}

Which part of the stored axis to use.

Returns:
omeganumpy.ndarray

Angular frequency, shape (n_x,), rad/s, ascending.

coherencenumpy.ndarray

The coherence, between 0 and 1, and nan at a frequency where every run of the ensemble is empty.

Raises:
solprop.exceptions.OutputError

If fewer than two runs are given, or their spectra do not have the same shape.

Examples

>>> import numpy as np
>>> from solprop.processing._examples import example_output
>>> from solprop.processing.coherence import g12_of
>>> ensemble = [example_output(), example_output()]
>>> omega, coherence = g12_of(ensemble, plane=-1)
>>> bool(np.all(coherence[np.isfinite(coherence)] == 1.0))
True