def inner_product(t, abar, b, axis=None, apply_conjugate=False): """Perform a time-domain complex inner product between two waveforms <a, b>. This is implemented using spline interpolation, calling quaternion.calculus.spline_definite_integral Parameters ---------- t : array_like Time samples for waveforms abar and b. abar : array_like The conjugate of the 'a' waveform in the inner product (or simply a, if apply_conjugate=True is been passed). Must have the same shape as b. b : array_like The 'b' waveform in the inner product. Must have the same shape as a. axis : int, optional When abar and b are multidimensional, the inner product will be computed over this axis and the result will be one dimension lower. Default is None, will be inferred by `spline_definite_integral`. apply_conjugate : bool, optional Whether or not to conjugate the abar argument before computing. True means inner_product will perform the conjugation for you. Default is False, meaning you have already performed the conjugation. Returns ------- inner_product : ndarray The integral along 'axis' """ from quaternion.calculus import spline_definite_integral as sdi if not apply_conjugate: integrand = abar * b else: integrand = np.conjugate(abar) * b return sdi(integrand, t, axis=axis)
def inner_product(self, b, t1=None, t2=None, allow_LM_differ=False, allow_times_differ=False): """Compute the all-angles inner product <self, b>. self and b should have the same spin-weight, set of (ell,m) modes, and times. Differing sets of modes and times can optionally be turned on. Parameters ---------- b : WaveformModes object The other set of modes to inner product with. t1 : float, optional [default: None] t2 : float, optional [default: None] Lower and higher bounds of time integration allow_LM_differ : bool, optional [default: False] If True and if the set of (ell,m) modes between self and b differ, then the inner product will be computed using the intersection of the set of modes. allow_times_differ: bool, optional [default: False] If True and if the set of times between self and b differ, then both WaveformModes will be interpolated to the intersection of the set of times. Returns ------- inner_product : complex <self, b> """ from quaternion.calculus import spline_definite_integral as sdi from .extrapolation import intersection if self.spin_weight != b.spin_weight: raise ValueError("Spin weights must match in inner_product") LM_clip = None if (self.ell_min != b.ell_min) or (self.ell_max != b.ell_max): if allow_LM_differ: LM_clip = slice(max(self.ell_min, b.ell_min), min(self.ell_max, b.ell_max) + 1) if LM_clip.start >= LM_clip.stop: raise ValueError("Intersection of (ell,m) modes is " "empty. Assuming this is not desired.") else: raise ValueError( "ell_min and ell_max must match in inner_product " "(use allow_LM_differ=True to override)") t_clip = None if not np.array_equal(self.t, b.t): if allow_times_differ: t_clip = intersection(self.t, b.t) else: raise ValueError("Time samples must match in inner_product " "(use allow_times_differ=True to override)") ########## times = self.t A = self B = b if LM_clip is not None: A = A[:, LM_clip] B = B[:, LM_clip] if t_clip is not None: times = t_clip A = A.interpolate(t_clip) B = B.interpolate(t_clip) if t1 is None: t1 = times[0] if t2 is None: t2 = times[-1] integrand = np.sum(np.conj(A.data) * B.data, axis=1) return sdi(integrand, times, t1=t1, t2=t2)