""" Define the super Signal class """ import numpy as np class Signal(): """ An arbitrary signal that can be translated to another position and time. Note that position can be of any length. Super object, cannot be used directly. """ def __init__(self, t_0 = 0, x_0 = 0, velocity=None, t_f = None, x_f = None): """ Parameters ---------- t_0 : float, optional Time that this signal is sent out. x_0 : float, optional Location that this signal is sent out from. velocity : float, optional Defaults to the speed of light in m/s. t_f : float, optional Default time that this signal is received. x_f : float, optional Default Location that this signal is received. """ if t_0 is None: raise ValueError("t_0 cannot be None") if x_0 is None: raise ValueError("x_0 cannot be None") self.x_0 = np.asarray(x_0) # m self.t_0 = np.asarray(t_0) # s self.velocity = 299792458 if velocity is None else velocity # m / s # Default final positions t_f = np.asarray(t_f) if t_f is not None else None x_f = np.asarray(x_f) if x_f is not None else None self.x_f = x_f self.t_f = t_f def __call__(self, t_f = None, x_f = None, **kwargs): """ Allow this class to be used as a function. """ return self._translate(t_f, x_f, **kwargs)[0] def _translate(self, t_f = None, x_f = None, t_0 = None, x_0 = None, velocity = None): """ Translate the signal from (t_0, x_0) to (t_f, x_f) with optional velocity. Returns the signal at (t_f, x_f) """ raise NotImplementedError def spatial_time_offset(self, x_f=None, x_0=None, velocity=None): """ Calculate the time offset caused by a spatial distance. """ if velocity is None: velocity = self.velocity if x_0 is None: x_0 = self.x_0 if x_f is None: x_f = self.x_f ## make sure they are arrays x_0 = np.asarray(x_0) if x_0 is not None else None x_f = np.asarray(x_f) if x_f is not None else None return np.sqrt( np.sum((x_f - x_0)**2, axis=-1) )/velocity def temporal_time_offset(self, t_f=None, t_0=None): """ Calculate the time offset caused by a temporal distance. """ if t_0 is None: t_0 = self.t_0 if t_f is None: t_f = self.t_f ## make sure they are arrays t_0 = np.asarray(t_0) if t_0 is not None else None t_f = np.asarray(t_f) if t_f is not None else None return t_f - t_0 def total_time_offset(self, t_f = None, x_f = None, t_0 = None, x_0 = None, velocity = None): """ Calculate how much time shifting is needed to go from (t_0, x_0) to (t_f, x_f). Convention: (t_0, x_0) < (t_f, x_0) gives a positive time shift, (t_0, x_0) != (t_0, x_f) gives a negative time shift Returns: the time shift """ # Get default values ## starting point if t_0 is None: t_0 = self.t_0 if x_0 is None: x_0 = self.x_0 ## final point if x_f is None: x_f = self.x_f if t_f is None: t_f = self.t_f ## make sure they are arrays t_0 = np.asarray(t_0) if t_0 is not None else None x_0 = np.asarray(x_0) if x_0 is not None else None t_f = np.asarray(t_f) if t_f is not None else None x_f = np.asarray(x_f) if x_f is not None else None # spatial offset if x_f is None: spatial_time_offset = 0 else: spatial_time_offset = self.spatial_time_offset(x_f, x_0=x_0, velocity=velocity) # temporal offset if t_f is None: temporal_time_offset = 0 else: temporal_time_offset = self.temporal_time_offset(t_f, t_0=t_0) return temporal_time_offset - spatial_time_offset