In [3]:
from math import pi
import math
import datetime

from config import AMP_heading
from config import M3_swath
from config import M3_avgeraging_time
from targets import TargetSpace
from targets import Target
import rules
import comms
import classification as classif

In [4]:
ts = TargetSpace()

In [13]:
ts.tables = {'adcp': [[datetime.datetime(2016, 3, 8, 23, 47, 16, 600000),1.2,4.5],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 600000),5.6,2.5]],
 'camera': [],
 'classifier_classifications': [1],
 'classifier_features': [],
 'nims': [[datetime.datetime(2016, 3, 8, 23, 47, 16, 606170),
   213,
   1225,
   26648,
   3.255762865359059,
   1.009538904487781,
   0.33651296816259363,
   0.3397229332247963,
   1,
   0,
   0,
   120,
   50,
   81.59374223255094,
   38.3912730413624,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 606170),
   221,
   764,
   27109,
   2.6585455797134,
   0.9990226307834469,
   0.3330075435944823,
   0.3326820722724931,
   4.749735623188873e-05,
   0,
   0,
   120,
   50,
   46.89115349587096,
   36.90071673015692,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 606170),
   230,
   662,
   27211,
   -1.4252885390060634,
   3.144248887280707,
   1.0480829624269024,
   3.2954336883886546,
   1,
   0,
   0,
   120,
   50,
   64.45498648235723,
   45.6643834242734,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 606170),
   232,
   532,
   27341,
   2.890572359393626,
   3.632297183140556,
   1.2107657277135186,
   4.397860942216939,
   1,
   0,
   0,
   120,
   50,
   62.32347596039271,
   36.98009428240289,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 606170),
   233,
   243,
   27630,
   0.765336539780397,
   2.0736340537675213,
   0.6912113512558404,
   1.4333193963147746,
   0.006207837847612895,
   0,
   0,
   120,
   50,
   49.21580297831671,
   23.907033796827886,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 18, 880554),
   213,
   1226,
   26648,
   3.327882881606094,
   1.009538904487781,
   0.33651296816259363,
   0.3397229332247963,
   0.04768479173654866,
   0,
   0,
   120,
   50,
   82.17312165722745,
   38.70562258528113,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 880554),
   221,
   765,
   27109,
   2.561834802661609,
   0.9990226307834469,
   0.3330075435944823,
   0.3326820722724931,
   4.2568959617736036e-06,
   0,
   0,
   120,
   50,
   46.89112643708125,
   36.90070054109199,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 880554),
   230,
   663,
   27211,
   -1.347039165042165,
   3.144248887280707,
   1.0480829624269024,
   3.2954336883886546,
   1,
   0,
   0,
   120,
   50,
   65.05607597023428,
   45.51592097830661,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 880554),
   232,
   533,
   27341,
   2.844387888261456,
   3.632297183140556,
   1.2107657277135186,
   4.397860942216939,
   0.06967176481633819,
   0,
   0,
   120,
   50,
   61.548294381352996,
   36.95444344388781,
   None],
  [datetime.datetime(2016, 3, 8, 23, 47, 16, 880554),
   233,
   244,
   27630,
   0.7439338175799398,
   2.0736340537675213,
   0.6912113512558404,
   1.4333193963147746,
   1,
   0,
   0,
   120,
   50,
   49.22192287980031,
   23.90526033283612,
   None],
 [datetime.datetime(2016, 3, 8, 23, 47, 16, 880554),
    218,
    244,
    27630,
    0.7439338175799398,
    2.0736340537675213,
    0.6912113512558404,
    1.4333193963147746,
    1,
    0,
    0,
    120,
    50,
    49.22192287980031,
    23.90526033283612,
    [0, 5]]],
 'pamguard': [datetime.datetime(2016, 3, 8, 23, 47, 16, 800000),"Dolphin"]}

In [14]:
target1 = Target(target_space=ts,
                 source="MSL_auto",
                 date=datetime.datetime(2016, 3, 8, 23, 47, 16, 880554),
                 indices={'nims': 10, 'adcp': 0, 'classifier_features':[], 'classifier_classifications':0})

In [19]:
def target_velocity(target):
    """
    Calculates "delta_v" for classification given a target.
    
    Delta_v is the norm of the difference between the current velocity
    and the target velocity. This function returns the maximum delta_v
    calculated for the target. Target velocity is calculated at intervals
    of M3_averaging_time
    
    i.e. if M3_averaging_time is 1 second, and a target was detected every
    ping at 10 Hz for 5 seconds, the velocity would be calculated 5 times.
    
    The most recent ADCP data at the time of target detection is used to 
    calculate delta_v.
    """
    # extract target data
    nims_indices = target.get_entry('nims')['aggregate_indices']
    adcp = target.get_entry('adcp')
    
    # sort nims data by timestamp
    sorted(nims_indices, 
           key = lambda x: target_space.get_entry_by_index('nims', x)['timestamp'])
    
    # extract all targets from nims data
    targets = extract_targets(target, nims_indices)
    
    points_to_avg = []
    index = 0
    # determine points between which to calculate velocity (must have at least
    # M3_averaging_time between the timestamps)
    while index < (len(targets)-1):
        start_time = targets[index]['timestamp']

        for i, target in enumerate(targets):
            # add to points_to_avg if the difference in time between
            # target sightings is greater than the M3_averaging_time
            diff = delta_t_in_seconds(target['timestamp'], start_time)
            
            if diff >= M3_avgeraging_time:
                points_to_avg.append(targets[i])
                index = i
                break
            
            if i >= (len(targets)-1):
                # if the target was less than the M3_averaging_time, use first
                # and last points
                index = i
                points_to_avg.append(targets[0])
                points_to_avg.append(targets[-1])
                break
    
    delta_v = calc_delta_v(points_to_avg, adcp)
    
    return max(delta_v)

    
def velocity_between_two_points(point1, point2):
    """
    Determines magnitude and direction of target trajectory (from point 1 to point 2)
    
    Inputs: 
    point 1, point 2 = points where target was detected, in list format [range, bearing in degrees]
    AMP_heading = heading of AMP, in radians from due north
    M3_swath = list containing minimum and maximum angle ( in degrees) for M3 target 
               detection. Default is 0 --> 120 degrees
    
    Outputs:
    vel = [velocity magnitude, velocity direction]
    """
    
    point1_cartesian = transform_NIMS_to_vector(point1)
    point2_cartesian = transform_NIMS_to_vector(point2)
    
    dt = delta_t_in_seconds(point1['timestamp'], point2['timestamp'])

    # subtract 2-1 to get velocity
    vel = [(point2_cartesian[0] - point1_cartesian[0])/dt,
           (point2_cartesian[1] - point1_cartesian[1])/dt]

    return(vel)


def transform_NIMS_to_vector(point):
    """
    Transform NIMS detection (in format [range, bearing in degrees]) to earth coordinates (East-North)
    
    Returns X-Y coordinates of point after transformation.
    """
    # convert target heading to radians, and shift such that zero degrees is center of swath
    point_heading = (point['last_pos_angle'] - (M3_swath[1] - M3_swath[0])/2) * pi/180

    # convert bearing to angle from due N by subtracting AMP angle
    point_heading = point_heading - AMP_heading

    # get vector components for point 1 and 2
    point_cartesian = [point['last_pos_range'] * math.cos(point_heading),
                       point['last_pos_range'] * math.sin(point_heading)]
    
    return(point_cartesian)


def delta_t_in_seconds(datetime1, datetime2):
    """
    calculate delta t in seconds between two datetime objects
    (returns absolute value, so order of dates is insignifigant)
    """
    delta_t = datetime1 - datetime2
    days_s = delta_t.days*(86400)
    microseconds_s = delta_t.microseconds/1000000
    delta_t_s = days_s + delta_t.seconds + microseconds_s
    return abs(delta_t_s)


def extract_targets(target, nims_indices):
    """
    Extract all targets from nims data
    """

    targets = []
    for index in nims_indices:
        targets.append(target.target_space.get_entry_by_index('nims', index))
    
    return targets

def calc_delta_v(points_to_avg, adcp):
    """
    returns delta v between all selected points and ADCP
    """
    # convert ADCP to cartesian coordinates
    velocity_adcp = [adcp['speed'] * math.cos(adcp['heading']),
                     adcp['speed'] * math.sin(adcp['heading'])]
    
    delta_v = []
    for i, target in enumerate(points_to_avg):

        # calculate delta_v between two consecutive points
        point1 = points_to_avg[i]
        
        try:
            point2 = points_to_avg[i+1]
        except:
            break
        
        # velocity of target between point 1 and point 2
        velocity_target = velocity_between_two_points(point1, point2)
        
        # difference between target and adcp velocity
        velocity_diff = [velocity_target[0]-velocity_adcp[0],
                         velocity_target[1]-velocity_adcp[1]]
            
        # "delta_v" is magnitude of velocity difference
        delta_v.append((velocity_diff[0]**2 + velocity_diff[1]**2)**0.5)
        
        return(delta_v)

In [20]:
target_velocity(target1)


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-20-32c245a4eabf> in <module>()
----> 1 target_velocity(target1)

<ipython-input-19-39aef874dfc8> in target_velocity(target)
     20     # sort nims data by timestamp
     21     sorted(nims_indices, 
---> 22            key = lambda x: target_space.get_entry_by_index('nims', x)['timestamp'])
     23 
     24     # extract all targets from nims data

<ipython-input-19-39aef874dfc8> in <lambda>(x)
     20     # sort nims data by timestamp
     21     sorted(nims_indices, 
---> 22            key = lambda x: target_space.get_entry_by_index('nims', x)['timestamp'])
     23 
     24     # extract all targets from nims data

NameError: name 'target_space' is not defined

In [ ]: