Source code for GWForge.fisher.inner_product


import numpy
from bilby.gw.utils import noise_weighted_inner_product


[docs] def inner_product(aa, bb, interferometer): """Noise-weighted inner product of two frequency-domain series. Wraps :func:`bilby.gw.utils.noise_weighted_inner_product` -- the same routine bilby uses for its own SNRs, so a Fisher SNR and an injection SNR are guaranteed to agree -- and takes the real part, which is what the Fisher matrix is built from. Only bins inside the interferometer's ``frequency_mask`` contribute. Outside it bilby leaves the PSD at an arbitrary sentinel value, so including those bins would silently corrupt the integral. Parameters ---------- aa, bb : array_like Frequency-domain series on the interferometer's frequency grid. ``aa`` is the one that gets conjugated. Either may be complex. interferometer : bilby.gw.detector.Interferometer Supplies the PSD, the frequency mask and the segment duration. Returns ------- float The real inner product. """ mask = interferometer.frequency_mask psd = interferometer.power_spectral_density_array[mask] return float( numpy.real( noise_weighted_inner_product( numpy.asarray(aa)[mask], numpy.asarray(bb)[mask], psd, interferometer.strain_data.duration, ) ) )
[docs] def optimal_snr_squared(signal, interferometer): """:math:`\\langle h \\mid h \\rangle` for a signal in one detector. Parameters ---------- signal : array_like Frequency-domain detector response. interferometer : bilby.gw.detector.Interferometer Detector whose PSD is used. Returns ------- float """ return inner_product(signal, signal, interferometer)
[docs] def inner_product_matrix(left, right, interferometer): """Gram matrix of inner products between two stacks of series. Building the Fisher matrix means taking ``len(left) * len(right)`` inner products that all share the same PSD weighting, so the weighting is applied once and the rest is a single matrix product. For an 11-parameter Fisher over a 65537-bin grid this is roughly two orders of magnitude faster than looping over :func:`inner_product`. Parameters ---------- left, right : array_like Arrays of shape ``(n_left, n_frequencies)`` and ``(n_right, n_frequencies)``. ``left`` is conjugated. interferometer : bilby.gw.detector.Interferometer Supplies the PSD, the frequency mask and the segment duration. Returns ------- numpy.ndarray Real array of shape ``(n_left, n_right)``. """ mask = interferometer.frequency_mask psd = interferometer.power_spectral_density_array[mask] duration = interferometer.strain_data.duration left = numpy.atleast_2d(numpy.asarray(left))[:, mask] right = numpy.atleast_2d(numpy.asarray(right))[:, mask] weighted = right / psd return (4.0 / duration) * numpy.real(numpy.conj(left) @ weighted.T)