Module libquantum.doppler

This module contains functions for examining doppler shift in signals

Expand source code
"""
This module contains functions for examining doppler shift in signals
"""

import numpy as np
from typing import Tuple


def time_duration(time_vector: np.ndarray) -> float:
    """
    Compute time from max and min

    :param time_vector: array of times in seconds
    :return: duration in seconds
    """
    return np.max(time_vector) - np.min(time_vector)


def time_4d_mx(time_array: np.ndarray, space_dimensions: int) -> np.array:
    """
    Input space and convert to spacetime matrix [time x XYZ]
    i.e. if time is [1, 2, 3, 4] and dimensions is 3
    result is [[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]

    :param time_array: array of times in seconds
    :param space_dimensions: integer number of dimensions of space
    :return: time_array arranged vertically space_dimensions number of times
    """
    return np.array([time_array, ] * space_dimensions).transpose()


def space_4d_mx(space_column_vector: np.ndarray, time_number_samples: int) -> np.array:
    """
    Input XYZ space vector and convert to spacetime matrix [time x XYZ]

    :param space_column_vector: an array representing 3 dimensional space
    :param time_number_samples: number of time samples
    :return: spacetime matrix
    """
    return np.array([space_column_vector, ] * time_number_samples)


def hadamard_dot_product_mx(x_mx: np.ndarray, y_mx: np.ndarray) -> np.ndarray:
    """"
    Hadamard columm-wise dot product with summation

    :param x_mx: MxN matrix x, columns represent directional vectors
    :param y_mx: MxN matrix y
    :return: sum of matrix product over columns
    """
    test = np.sum(x_mx * y_mx, 1)
    return test


def range_vector_sr(x_initial_position_vector: np.array,
                    x_final_position_vector: np.array) -> np.array:
    """
    Start to end direction, or source vs receiver

    :param x_initial_position_vector: starting position, 3-element XYZ
    :param x_final_position_vector: ending position, 3-element XYZ
    :return: receiver - source vectors
    """
    return x_final_position_vector - x_initial_position_vector


def range_matrix_sr(x_source_mx: np.ndarray,
                    x_receiver_mx: np.ndarray) -> np.ndarray:
    """
    start to end position, source vs receiver matrix

    :param x_source_mx: starting position, 3-element XYZ columns, t rows
    :param x_receiver_mx: ending position, 3-element XYZ columns, t rows
    :return: receiver - source matrices
    """
    return x_receiver_mx - x_source_mx


def range_hadamard(r_mx: np.ndarray) -> np.ndarray:
    """
    Compute the magnitude of range and time (Square root of Hadamard dot product over columns)

    :param r_mx: positional range matrix, 3-element XYZ columns, t rows
    :return: Square root of Hadamard dot product over columns
    """
    return np.sqrt(hadamard_dot_product_mx(r_mx, r_mx))


def range_scalar(x_source_vector: np.array, x_receiver_vector: np.array) -> float:
    """
    Compute the magnitude of the range (square root of the sum of the range vector squared, element-wise)

    :param x_source_vector: starting position, 3-element XYZ
    :param x_receiver_vector: ending position, 3-element XYZ
    :return: magnitude of the range
    """
    range_vector = range_vector_sr(x_source_vector, x_receiver_vector)
    return np.sqrt(np.sum(range_vector * range_vector))


def _get_setup(time_array_s: np.array,
               num_space_dimensions: int,
               source_position_vector_initial_xyz_m: np.array,
               source_position_vector_final_xyz_m: np.array,
               receiver_position_vector_initial_xyz_m: np.array,
               receiver_position_vector_final_xyz_m: np.array) -> Tuple[int, np.array, float, float]:
    """
    Apply a doppler shift on a source moving towards the receiver

    :param time_array_s: array of source times in seconds
    :param num_space_dimensions: integer number of space dimensions. Nominal = 3, should match space position vectors.
    :param source_position_vector_initial_xyz_m: initial source position in space (where it initially started)
    :param source_position_vector_final_xyz_m: final source position in space
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: number of time samples, matrix for time, matrix for trajectory range for source and receiver
    """
    num_samples = len(time_array_s)
    temp_mx_s = time_4d_mx(time_array_s, num_space_dimensions)
    source_trajectory_m = range_scalar(source_position_vector_initial_xyz_m, source_position_vector_final_xyz_m)
    receiver_trajectory_m = range_scalar(receiver_position_vector_initial_xyz_m, receiver_position_vector_final_xyz_m)

    return num_samples, temp_mx_s, source_trajectory_m, receiver_trajectory_m


def _get_velocity_mps(speed_mps: float,
                      trajectory_m: float,
                      num_samples: int,
                      position_vector_initial_xyz_m: np.array,
                      position_vector_final_xyz_m: np.array) -> np.array:
    """
    Compute velocity (in meter per second)

    :param speed_mps: object's speed
    :param trajectory_m: magnitude of trajectory in meters
    :param num_samples: number of samples
    :param position_vector_initial_xyz_m: position in space where object initially started
    :param position_vector_final_xyz_m: position in space where object ends up
    :return: velocity in XYZ + time matrix
    """
    if speed_mps > 0:
        velocity_direction = range_vector_sr(position_vector_initial_xyz_m, position_vector_final_xyz_m) / trajectory_m
        velocity_mps = speed_mps * velocity_direction
    else:
        velocity_mps = np.zeros(3)
    velocity_mx_mps = space_4d_mx(velocity_mps, num_samples)
    return velocity_mx_mps


def _get_final_vals(spacetime_matrix: np.array,
                    receiver_velocity_mx_mps: np.array,
                    source_velocity_mx_mps: np.array,
                    time_array_s: np.array,
                    receiver_position_vector_initial_xyz_m: np.array,
                    source_position_vector_initial_xyz_m: np.array,
                    signal_speed_mps: float,
                    object_speed_mps: float,
                    num_dimensions: int,
                    num_samples: int,
                    inverse: bool = False) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Compute array of times in seconds, Magnitude of range and time, omega over omega center

    :param spacetime_matrix: spacetime matrix
    :param time_array_s: array of times
    :param receiver_velocity_mx_mps: receiver velocity in meters per second
    :param source_velocity_mx_mps: source velocity in meters per second
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param signal_speed_mps: signal speed in meters per second
    :param object_speed_mps: object speed in meters per second
    :param num_dimensions: number of dimensions
    :param num_samples: number of samples
    :param inverse: is this an inverse calculation?  Default False
    :return: array of times in seconds, Magnitude of range and time, omega over omega center
    """
    # Initial range vector, source to receiver (sr) at start of segment
    range_vector_sr_initial_m = receiver_position_vector_initial_xyz_m - source_position_vector_initial_xyz_m
    range_initial_mx_m = space_4d_mx(range_vector_sr_initial_m, num_samples)
    # Compute object values and phase
    denom = 1. / (signal_speed_mps**2 - object_speed_mps**2)
    # Dot product contracts to 1D size
    if inverse:
        temp_range_mx_m = range_initial_mx_m + receiver_velocity_mx_mps * spacetime_matrix
        term1 = (signal_speed_mps**2) * time_array_s - hadamard_dot_product_mx(source_velocity_mx_mps, temp_range_mx_m)
    else:
        temp_range_mx_m = range_initial_mx_m - source_velocity_mx_mps * spacetime_matrix
        term1 = (signal_speed_mps**2) * time_array_s + \
            hadamard_dot_product_mx(receiver_velocity_mx_mps, temp_range_mx_m)
    term1 *= denom

    temp_range_m = range_hadamard(temp_range_mx_m)
    term2 = temp_range_m**2 - (time_array_s * signal_speed_mps)**2
    term2 *= denom
    if inverse:
        time_s = term1 - np.sqrt(term1**2 + term2)
        range_mx_m = temp_range_mx_m - source_velocity_mx_mps * time_4d_mx(time_s, num_dimensions)
    else:
        time_s = term1 + np.sqrt(term1**2 + term2)
        range_mx_m = temp_range_mx_m + receiver_velocity_mx_mps * time_4d_mx(time_s, num_dimensions)

    range_time_m = range_hadamard(range_mx_m)
    omega_over_omega_center = \
        (signal_speed_mps - hadamard_dot_product_mx(range_mx_m, receiver_velocity_mx_mps) / range_time_m) / \
        (signal_speed_mps - hadamard_dot_product_mx(range_mx_m, source_velocity_mx_mps) / range_time_m)

    return time_s, range_time_m, omega_over_omega_center


def doppler_forward(tau_source_s: np.array,
                    signal_speed_mps: float,
                    source_speed_mps: float,
                    receiver_speed_mps: float,
                    space_dimensions: int,
                    source_position_vector_initial_xyz_m: np.array,
                    source_position_vector_final_xyz_m: np.array,
                    receiver_position_vector_initial_xyz_m: np.array,
                    receiver_position_vector_final_xyz_m: np.array) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Apply a doppler shift on a source moving towards the receiver

    :param tau_source_s: array of source times in seconds
    :param signal_speed_mps: speed of the signal in meters per second
    :param source_speed_mps: speed of the source in meters per second
    :param receiver_speed_mps: speed of the receiver in meters per second
    :param space_dimensions: integer number of dimensions everything is moving in
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param source_position_vector_final_xyz_m: position in space where source ends up
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center
    """
    tau_number_samples, tau_mx_s, source_trajectory_m, receiver_trajectory_m = \
        _get_setup(tau_source_s, space_dimensions, source_position_vector_initial_xyz_m,
                   source_position_vector_final_xyz_m, receiver_position_vector_initial_xyz_m,
                   receiver_position_vector_final_xyz_m)

    source_velocity_mx_mps = _get_velocity_mps(source_speed_mps, source_trajectory_m, tau_number_samples,
                                               source_position_vector_initial_xyz_m,
                                               source_position_vector_final_xyz_m)

    receiver_velocity_mx_mps = _get_velocity_mps(receiver_speed_mps, receiver_trajectory_m, tau_number_samples,
                                                 receiver_position_vector_initial_xyz_m,
                                                 receiver_position_vector_final_xyz_m)
    # Observation time
    return _get_final_vals(tau_mx_s, receiver_velocity_mx_mps, source_velocity_mx_mps, tau_source_s,
                           receiver_position_vector_initial_xyz_m, source_position_vector_initial_xyz_m,
                           signal_speed_mps, receiver_speed_mps, space_dimensions, tau_number_samples, False)


def image_doppler_forward(tau_source_s: np.array,
                          signal_speed_mps: float,
                          source_speed_mps: float,
                          receiver_speed_mps: float,
                          space_dimensions: int,
                          source_position_vector_initial_xyz_m: np.array,
                          source_position_vector_final_xyz_m: np.array,
                          receiver_position_vector_initial_xyz_m: np.array,
                          receiver_position_vector_final_xyz_m: np.array) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Apply a doppler shift on a perceived source moving towards the receiver

    :param tau_source_s: array of source times in seconds
    :param signal_speed_mps: speed of the signal in meters per second
    :param source_speed_mps: speed of the source in meters per second
    :param receiver_speed_mps: speed of the receiver in meters per second
    :param space_dimensions: integer number of dimensions everything is moving in
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param source_position_vector_final_xyz_m: position in space where source ends up
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center
    """
    # Flip the z-axis - everything else is the same
    image_source_position_vector_initial_xyz_m = source_position_vector_initial_xyz_m*np.array([1., 1., -1.])
    image_source_position_vector_final_xyz_m = source_position_vector_final_xyz_m*np.array([1., 1., -1.])

    return doppler_forward(tau_source_s, signal_speed_mps, source_speed_mps, receiver_speed_mps,
                           space_dimensions, image_source_position_vector_initial_xyz_m,
                           image_source_position_vector_final_xyz_m, receiver_position_vector_initial_xyz_m,
                           receiver_position_vector_final_xyz_m)


def doppler_inverse(inv_time_receiver_s: np.array,
                    signal_speed_mps: float,
                    source_speed_mps: float,
                    receiver_speed_mps: float,
                    space_dimensions: int,
                    source_position_vector_initial_xyz_m: np.array,
                    source_position_vector_final_xyz_m: np.array,
                    receiver_position_vector_initial_xyz_m: np.array,
                    receiver_position_vector_final_xyz_m: np.array) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Apply a doppler shift on an inverse

    :param inv_time_receiver_s: array of receiver times in seconds
    :param signal_speed_mps: speed of the signal in meters per second
    :param source_speed_mps: speed of the source in meters per second
    :param receiver_speed_mps: speed of the receiver in meters per second
    :param space_dimensions: integer number of dimensions everything is moving in
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param source_position_vector_final_xyz_m: position in space where source ends up
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center
    """
    time_number_samples, time_mx_s, source_trajectory_m, receiver_trajectory_m = \
        _get_setup(inv_time_receiver_s, space_dimensions, source_position_vector_initial_xyz_m,
                   source_position_vector_final_xyz_m, receiver_position_vector_initial_xyz_m,
                   receiver_position_vector_final_xyz_m)

    source_velocity_mx_mps = _get_velocity_mps(source_speed_mps, source_trajectory_m, time_number_samples,
                                               source_position_vector_initial_xyz_m,
                                               source_position_vector_final_xyz_m)

    receiver_velocity_mx_mps = _get_velocity_mps(receiver_speed_mps, receiver_trajectory_m, time_number_samples,
                                                 receiver_position_vector_initial_xyz_m,
                                                 receiver_position_vector_final_xyz_m)

    # compute range and terms and find Source tau
    return _get_final_vals(time_mx_s, receiver_velocity_mx_mps, source_velocity_mx_mps, inv_time_receiver_s,
                           receiver_position_vector_initial_xyz_m, source_position_vector_initial_xyz_m,
                           signal_speed_mps, source_speed_mps, space_dimensions, time_number_samples, True)


def image_doppler_inverse(inv_time_receiver_s: np.array,
                          signal_speed_mps: float,
                          source_speed_mps: float,
                          receiver_speed_mps: float,
                          space_dimensions: int,
                          source_position_vector_initial_xyz_m: np.array,
                          source_position_vector_final_xyz_m: np.array,
                          receiver_position_vector_initial_xyz_m: np.array,
                          receiver_position_vector_final_xyz_m: np.array) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Apply a doppler shift on an image inverse

    :param inv_time_receiver_s: array of receiver times in seconds
    :param signal_speed_mps: speed of the signal in meters per second
    :param source_speed_mps: speed of the source in meters per second
    :param receiver_speed_mps: speed of the receiver in meters per second
    :param space_dimensions: integer number of dimensions everything is moving in
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param source_position_vector_final_xyz_m: position in space where source ends up
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center
    """
    # Flip the z-axis - everything else is the same
    image_source_position_vector_initial_xyz_m = source_position_vector_initial_xyz_m*np.array([1., 1., -1.])
    image_source_position_vector_final_xyz_m = source_position_vector_final_xyz_m*np.array([1., 1., -1.])

    return doppler_inverse(inv_time_receiver_s, signal_speed_mps, source_speed_mps, receiver_speed_mps,
                           space_dimensions, image_source_position_vector_initial_xyz_m,
                           image_source_position_vector_final_xyz_m, receiver_position_vector_initial_xyz_m,
                           receiver_position_vector_final_xyz_m)

Functions

def doppler_forward(tau_source_s: , signal_speed_mps: float, source_speed_mps: float, receiver_speed_mps: float, space_dimensions: int, source_position_vector_initial_xyz_m: , source_position_vector_final_xyz_m: , receiver_position_vector_initial_xyz_m: , receiver_position_vector_final_xyz_m: ) ‑> Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

Apply a doppler shift on a source moving towards the receiver

:param tau_source_s: array of source times in seconds :param signal_speed_mps: speed of the signal in meters per second :param source_speed_mps: speed of the source in meters per second :param receiver_speed_mps: speed of the receiver in meters per second :param space_dimensions: integer number of dimensions everything is moving in :param source_position_vector_initial_xyz_m: position in space where source initially started :param source_position_vector_final_xyz_m: position in space where source ends up :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started :param receiver_position_vector_final_xyz_m: position in space where receiver ends up :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center

Expand source code
def doppler_forward(tau_source_s: np.array,
                    signal_speed_mps: float,
                    source_speed_mps: float,
                    receiver_speed_mps: float,
                    space_dimensions: int,
                    source_position_vector_initial_xyz_m: np.array,
                    source_position_vector_final_xyz_m: np.array,
                    receiver_position_vector_initial_xyz_m: np.array,
                    receiver_position_vector_final_xyz_m: np.array) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Apply a doppler shift on a source moving towards the receiver

    :param tau_source_s: array of source times in seconds
    :param signal_speed_mps: speed of the signal in meters per second
    :param source_speed_mps: speed of the source in meters per second
    :param receiver_speed_mps: speed of the receiver in meters per second
    :param space_dimensions: integer number of dimensions everything is moving in
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param source_position_vector_final_xyz_m: position in space where source ends up
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center
    """
    tau_number_samples, tau_mx_s, source_trajectory_m, receiver_trajectory_m = \
        _get_setup(tau_source_s, space_dimensions, source_position_vector_initial_xyz_m,
                   source_position_vector_final_xyz_m, receiver_position_vector_initial_xyz_m,
                   receiver_position_vector_final_xyz_m)

    source_velocity_mx_mps = _get_velocity_mps(source_speed_mps, source_trajectory_m, tau_number_samples,
                                               source_position_vector_initial_xyz_m,
                                               source_position_vector_final_xyz_m)

    receiver_velocity_mx_mps = _get_velocity_mps(receiver_speed_mps, receiver_trajectory_m, tau_number_samples,
                                                 receiver_position_vector_initial_xyz_m,
                                                 receiver_position_vector_final_xyz_m)
    # Observation time
    return _get_final_vals(tau_mx_s, receiver_velocity_mx_mps, source_velocity_mx_mps, tau_source_s,
                           receiver_position_vector_initial_xyz_m, source_position_vector_initial_xyz_m,
                           signal_speed_mps, receiver_speed_mps, space_dimensions, tau_number_samples, False)
def doppler_inverse(inv_time_receiver_s: , signal_speed_mps: float, source_speed_mps: float, receiver_speed_mps: float, space_dimensions: int, source_position_vector_initial_xyz_m: , source_position_vector_final_xyz_m: , receiver_position_vector_initial_xyz_m: , receiver_position_vector_final_xyz_m: ) ‑> Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

Apply a doppler shift on an inverse

:param inv_time_receiver_s: array of receiver times in seconds :param signal_speed_mps: speed of the signal in meters per second :param source_speed_mps: speed of the source in meters per second :param receiver_speed_mps: speed of the receiver in meters per second :param space_dimensions: integer number of dimensions everything is moving in :param source_position_vector_initial_xyz_m: position in space where source initially started :param source_position_vector_final_xyz_m: position in space where source ends up :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started :param receiver_position_vector_final_xyz_m: position in space where receiver ends up :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center

Expand source code
def doppler_inverse(inv_time_receiver_s: np.array,
                    signal_speed_mps: float,
                    source_speed_mps: float,
                    receiver_speed_mps: float,
                    space_dimensions: int,
                    source_position_vector_initial_xyz_m: np.array,
                    source_position_vector_final_xyz_m: np.array,
                    receiver_position_vector_initial_xyz_m: np.array,
                    receiver_position_vector_final_xyz_m: np.array) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Apply a doppler shift on an inverse

    :param inv_time_receiver_s: array of receiver times in seconds
    :param signal_speed_mps: speed of the signal in meters per second
    :param source_speed_mps: speed of the source in meters per second
    :param receiver_speed_mps: speed of the receiver in meters per second
    :param space_dimensions: integer number of dimensions everything is moving in
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param source_position_vector_final_xyz_m: position in space where source ends up
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center
    """
    time_number_samples, time_mx_s, source_trajectory_m, receiver_trajectory_m = \
        _get_setup(inv_time_receiver_s, space_dimensions, source_position_vector_initial_xyz_m,
                   source_position_vector_final_xyz_m, receiver_position_vector_initial_xyz_m,
                   receiver_position_vector_final_xyz_m)

    source_velocity_mx_mps = _get_velocity_mps(source_speed_mps, source_trajectory_m, time_number_samples,
                                               source_position_vector_initial_xyz_m,
                                               source_position_vector_final_xyz_m)

    receiver_velocity_mx_mps = _get_velocity_mps(receiver_speed_mps, receiver_trajectory_m, time_number_samples,
                                                 receiver_position_vector_initial_xyz_m,
                                                 receiver_position_vector_final_xyz_m)

    # compute range and terms and find Source tau
    return _get_final_vals(time_mx_s, receiver_velocity_mx_mps, source_velocity_mx_mps, inv_time_receiver_s,
                           receiver_position_vector_initial_xyz_m, source_position_vector_initial_xyz_m,
                           signal_speed_mps, source_speed_mps, space_dimensions, time_number_samples, True)
def hadamard_dot_product_mx(x_mx: numpy.ndarray, y_mx: numpy.ndarray) ‑> numpy.ndarray

" Hadamard columm-wise dot product with summation

:param x_mx: MxN matrix x, columns represent directional vectors :param y_mx: MxN matrix y :return: sum of matrix product over columns

Expand source code
def hadamard_dot_product_mx(x_mx: np.ndarray, y_mx: np.ndarray) -> np.ndarray:
    """"
    Hadamard columm-wise dot product with summation

    :param x_mx: MxN matrix x, columns represent directional vectors
    :param y_mx: MxN matrix y
    :return: sum of matrix product over columns
    """
    test = np.sum(x_mx * y_mx, 1)
    return test
def image_doppler_forward(tau_source_s: , signal_speed_mps: float, source_speed_mps: float, receiver_speed_mps: float, space_dimensions: int, source_position_vector_initial_xyz_m: , source_position_vector_final_xyz_m: , receiver_position_vector_initial_xyz_m: , receiver_position_vector_final_xyz_m: ) ‑> Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

Apply a doppler shift on a perceived source moving towards the receiver

:param tau_source_s: array of source times in seconds :param signal_speed_mps: speed of the signal in meters per second :param source_speed_mps: speed of the source in meters per second :param receiver_speed_mps: speed of the receiver in meters per second :param space_dimensions: integer number of dimensions everything is moving in :param source_position_vector_initial_xyz_m: position in space where source initially started :param source_position_vector_final_xyz_m: position in space where source ends up :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started :param receiver_position_vector_final_xyz_m: position in space where receiver ends up :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center

Expand source code
def image_doppler_forward(tau_source_s: np.array,
                          signal_speed_mps: float,
                          source_speed_mps: float,
                          receiver_speed_mps: float,
                          space_dimensions: int,
                          source_position_vector_initial_xyz_m: np.array,
                          source_position_vector_final_xyz_m: np.array,
                          receiver_position_vector_initial_xyz_m: np.array,
                          receiver_position_vector_final_xyz_m: np.array) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Apply a doppler shift on a perceived source moving towards the receiver

    :param tau_source_s: array of source times in seconds
    :param signal_speed_mps: speed of the signal in meters per second
    :param source_speed_mps: speed of the source in meters per second
    :param receiver_speed_mps: speed of the receiver in meters per second
    :param space_dimensions: integer number of dimensions everything is moving in
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param source_position_vector_final_xyz_m: position in space where source ends up
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center
    """
    # Flip the z-axis - everything else is the same
    image_source_position_vector_initial_xyz_m = source_position_vector_initial_xyz_m*np.array([1., 1., -1.])
    image_source_position_vector_final_xyz_m = source_position_vector_final_xyz_m*np.array([1., 1., -1.])

    return doppler_forward(tau_source_s, signal_speed_mps, source_speed_mps, receiver_speed_mps,
                           space_dimensions, image_source_position_vector_initial_xyz_m,
                           image_source_position_vector_final_xyz_m, receiver_position_vector_initial_xyz_m,
                           receiver_position_vector_final_xyz_m)
def image_doppler_inverse(inv_time_receiver_s: , signal_speed_mps: float, source_speed_mps: float, receiver_speed_mps: float, space_dimensions: int, source_position_vector_initial_xyz_m: , source_position_vector_final_xyz_m: , receiver_position_vector_initial_xyz_m: , receiver_position_vector_final_xyz_m: ) ‑> Tuple[numpy.ndarray, numpy.ndarray, numpy.ndarray]

Apply a doppler shift on an image inverse

:param inv_time_receiver_s: array of receiver times in seconds :param signal_speed_mps: speed of the signal in meters per second :param source_speed_mps: speed of the source in meters per second :param receiver_speed_mps: speed of the receiver in meters per second :param space_dimensions: integer number of dimensions everything is moving in :param source_position_vector_initial_xyz_m: position in space where source initially started :param source_position_vector_final_xyz_m: position in space where source ends up :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started :param receiver_position_vector_final_xyz_m: position in space where receiver ends up :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center

Expand source code
def image_doppler_inverse(inv_time_receiver_s: np.array,
                          signal_speed_mps: float,
                          source_speed_mps: float,
                          receiver_speed_mps: float,
                          space_dimensions: int,
                          source_position_vector_initial_xyz_m: np.array,
                          source_position_vector_final_xyz_m: np.array,
                          receiver_position_vector_initial_xyz_m: np.array,
                          receiver_position_vector_final_xyz_m: np.array) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Apply a doppler shift on an image inverse

    :param inv_time_receiver_s: array of receiver times in seconds
    :param signal_speed_mps: speed of the signal in meters per second
    :param source_speed_mps: speed of the source in meters per second
    :param receiver_speed_mps: speed of the receiver in meters per second
    :param space_dimensions: integer number of dimensions everything is moving in
    :param source_position_vector_initial_xyz_m: position in space where source initially started
    :param source_position_vector_final_xyz_m: position in space where source ends up
    :param receiver_position_vector_initial_xyz_m: position in space where receiver initially started
    :param receiver_position_vector_final_xyz_m: position in space where receiver ends up
    :return: array of receiver times in seconds, Magnitude of range and time, omega over omega center
    """
    # Flip the z-axis - everything else is the same
    image_source_position_vector_initial_xyz_m = source_position_vector_initial_xyz_m*np.array([1., 1., -1.])
    image_source_position_vector_final_xyz_m = source_position_vector_final_xyz_m*np.array([1., 1., -1.])

    return doppler_inverse(inv_time_receiver_s, signal_speed_mps, source_speed_mps, receiver_speed_mps,
                           space_dimensions, image_source_position_vector_initial_xyz_m,
                           image_source_position_vector_final_xyz_m, receiver_position_vector_initial_xyz_m,
                           receiver_position_vector_final_xyz_m)
def range_hadamard(r_mx: numpy.ndarray) ‑> numpy.ndarray

Compute the magnitude of range and time (Square root of Hadamard dot product over columns)

:param r_mx: positional range matrix, 3-element XYZ columns, t rows :return: Square root of Hadamard dot product over columns

Expand source code
def range_hadamard(r_mx: np.ndarray) -> np.ndarray:
    """
    Compute the magnitude of range and time (Square root of Hadamard dot product over columns)

    :param r_mx: positional range matrix, 3-element XYZ columns, t rows
    :return: Square root of Hadamard dot product over columns
    """
    return np.sqrt(hadamard_dot_product_mx(r_mx, r_mx))
def range_matrix_sr(x_source_mx: numpy.ndarray, x_receiver_mx: numpy.ndarray) ‑> numpy.ndarray

start to end position, source vs receiver matrix

:param x_source_mx: starting position, 3-element XYZ columns, t rows :param x_receiver_mx: ending position, 3-element XYZ columns, t rows :return: receiver - source matrices

Expand source code
def range_matrix_sr(x_source_mx: np.ndarray,
                    x_receiver_mx: np.ndarray) -> np.ndarray:
    """
    start to end position, source vs receiver matrix

    :param x_source_mx: starting position, 3-element XYZ columns, t rows
    :param x_receiver_mx: ending position, 3-element XYZ columns, t rows
    :return: receiver - source matrices
    """
    return x_receiver_mx - x_source_mx
def range_scalar(x_source_vector: , x_receiver_vector: ) ‑> float

Compute the magnitude of the range (square root of the sum of the range vector squared, element-wise)

:param x_source_vector: starting position, 3-element XYZ :param x_receiver_vector: ending position, 3-element XYZ :return: magnitude of the range

Expand source code
def range_scalar(x_source_vector: np.array, x_receiver_vector: np.array) -> float:
    """
    Compute the magnitude of the range (square root of the sum of the range vector squared, element-wise)

    :param x_source_vector: starting position, 3-element XYZ
    :param x_receiver_vector: ending position, 3-element XYZ
    :return: magnitude of the range
    """
    range_vector = range_vector_sr(x_source_vector, x_receiver_vector)
    return np.sqrt(np.sum(range_vector * range_vector))
def range_vector_sr(x_initial_position_vector: , x_final_position_vector: ) ‑> 

Start to end direction, or source vs receiver

:param x_initial_position_vector: starting position, 3-element XYZ :param x_final_position_vector: ending position, 3-element XYZ :return: receiver - source vectors

Expand source code
def range_vector_sr(x_initial_position_vector: np.array,
                    x_final_position_vector: np.array) -> np.array:
    """
    Start to end direction, or source vs receiver

    :param x_initial_position_vector: starting position, 3-element XYZ
    :param x_final_position_vector: ending position, 3-element XYZ
    :return: receiver - source vectors
    """
    return x_final_position_vector - x_initial_position_vector
def space_4d_mx(space_column_vector: numpy.ndarray, time_number_samples: int) ‑> 

Input XYZ space vector and convert to spacetime matrix [time x XYZ]

:param space_column_vector: an array representing 3 dimensional space :param time_number_samples: number of time samples :return: spacetime matrix

Expand source code
def space_4d_mx(space_column_vector: np.ndarray, time_number_samples: int) -> np.array:
    """
    Input XYZ space vector and convert to spacetime matrix [time x XYZ]

    :param space_column_vector: an array representing 3 dimensional space
    :param time_number_samples: number of time samples
    :return: spacetime matrix
    """
    return np.array([space_column_vector, ] * time_number_samples)
def time_4d_mx(time_array: numpy.ndarray, space_dimensions: int) ‑> 

Input space and convert to spacetime matrix [time x XYZ] i.e. if time is [1, 2, 3, 4] and dimensions is 3 result is [[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]

:param time_array: array of times in seconds :param space_dimensions: integer number of dimensions of space :return: time_array arranged vertically space_dimensions number of times

Expand source code
def time_4d_mx(time_array: np.ndarray, space_dimensions: int) -> np.array:
    """
    Input space and convert to spacetime matrix [time x XYZ]
    i.e. if time is [1, 2, 3, 4] and dimensions is 3
    result is [[1, 1, 1], [2, 2, 2], [3, 3, 3], [4, 4, 4]]

    :param time_array: array of times in seconds
    :param space_dimensions: integer number of dimensions of space
    :return: time_array arranged vertically space_dimensions number of times
    """
    return np.array([time_array, ] * space_dimensions).transpose()
def time_duration(time_vector: numpy.ndarray) ‑> float

Compute time from max and min

:param time_vector: array of times in seconds :return: duration in seconds

Expand source code
def time_duration(time_vector: np.ndarray) -> float:
    """
    Compute time from max and min

    :param time_vector: array of times in seconds
    :return: duration in seconds
    """
    return np.max(time_vector) - np.min(time_vector)