def mds_track_check(invoyage):

    '''
    Perform one pass of the track check
    
    :param invoyage: A list of :class:`.Voyage` that you want track checked
    :type invoyage: :class:`.Voyage`
    :return: list of QC flags 0 for pass and 1 for fail
    :rtype: integer
    
    This is an implementation of the MDS track check code 
    which was originally written in the 1990s. I don't know why this piece of 
    historic trivia so exercises my mind, but it does: the 1990s! I wish my code 
    would last so long.
    '''
    
    km_to_nm = 0.539957
    nobs = len(invoyage)

#no obs in, no qc outcomes out
    if nobs == 0:
        return []

#Generic ids get a free pass on the track check
    if qc.id_is_generic(invoyage.getvar(0, 'ID'), invoyage.getvar(0, 'YR')):
        qcs = []
        nobs = len(invoyage)
        for i in range(0, nobs):
            invoyage.set_qc(i, 'POS', 'bad_track', 0)
            qcs.append(0)
        return qcs

#fewer than three obs - set the fewsome flag
#deck 720 gets a pass prior to 1891 see Carella, Kent, Berry 2015 Appendix A3
    if nobs < 3 and not(invoyage.getvar(0, 'DCK') == 720 and invoyage.getvar(0 ,'YR') < 1891):
        qcs = []
        nobs = len(invoyage)
        for i in range(0, nobs):
            invoyage.set_qc(i, 'POS', 'fewsome_check', 1)
            qcs.append(0)
        return qcs

#work out speeds and distances between alternating points
    invoyage.calc_alternate_speeds()

#what are the mean and mode speeds?
    mean_speed = invoyage.meansp()
    modal_speed = modesp(invoyage.get_speed())
#set speed limits based on modal speed
    amax, amaxx, amin = set_speed_limits(modal_speed)

#compare reported speeds and positions if we have them
    forward_diff_from_estimated  = distr1(invoyage)
    reverse_diff_from_estimated  = distr2(invoyage)
    midpoint_diff_from_estimated =  midpt(invoyage)

#do QC
    qcs = [0]
    all_alwdis = [0]
    invoyage.set_qc(0, 'POS', 'bad_track', 0)
    invoyage.set_qc(0, 'POS', 'fewsome_check', 0)

    for i in range(1, nobs-1):
        
        thisqc_a = 0
        thisqc_b = 0

#together these cover the speeds calculate from point i        
        if   (invoyage.getvar(i, 'speed')       > amax and 
              invoyage.getvar(i-1 ,'alt_speed') > amax):
            thisqc_a += 1.00
        elif (invoyage.getvar(i+1, 'speed')     > amax and 
              invoyage.getvar(i+1, 'alt_speed') > amax):
            thisqc_a += 2.00
        elif (invoyage.getvar(i, 'speed')       > amax and 
              invoyage.getvar(i+1, 'speed')     > amax):
            thisqc_a += 3.00 

# Quality-control by examining the distance 
#between the calculated and reported second position.
        thisqc_b += check_distance_from_estimate(invoyage.getvar(i ,  'vsi'), 
                                                 invoyage.getvar(i-1, 'vsi'), 
                                                 invoyage.getvar(i,   'time_diff'), 
                                                 forward_diff_from_estimated[i],
                                                 reverse_diff_from_estimated[i])
#Check for continuity of direction                              
        thisqc_b += direction_continuity(invoyage.getvar(i,   'dsi'), 
                                         invoyage.getvar(i-1, 'dsi'), 
                                         invoyage.getvar(i,   'course'))
#Check for continuity of speed.                                 
        thisqc_b += speed_continuity(invoyage.getvar(i,   'vsi'), 
                                     invoyage.getvar(i-1, 'vsi'), 
                                     invoyage.getvar(i,   'speed'))

#check for speeds in excess of 40.00 knots
        if invoyage.getvar(i, 'speed') > 40.00/km_to_nm:
            thisqc_b += 10.0

#make the final decision
        if (midpoint_diff_from_estimated[i] > 150.0/km_to_nm and 
            thisqc_a > 0 and 
            thisqc_b > 0):
            qcs.append(1)
            invoyage.set_qc(i, 'POS', 'bad_track', 1)
            invoyage.set_qc(i, 'POS', 'fewsome_check', 0)
        else:
            qcs.append(0)
            invoyage.set_qc(i, 'POS', 'bad_track', 0)
            invoyage.set_qc(i, 'POS', 'fewsome_check', 0)

    qcs.append(0)
    invoyage.set_qc(nobs-1, 'POS', 'bad_track', 0)
    invoyage.set_qc(nobs-1, 'POS', 'fewsome_check', 0)

    return qcs
Exemplo n.º 2
0
def mds_track_check(invoyage):
    """
    Perform one pass of the track check
    
    :param invoyage: A list of :class:`.Voyage` that you want track checked
    :type invoyage: :class:`.Voyage`
    :return: list of QC flags 0 for pass and 1 for fail
    :rtype: integer
    
    This is an implementation of the MDS track check code 
    which was originally written in the 1990s. I don't know why this piece of 
    historic trivia so exercises my mind, but it does: the 1990s! I wish my code 
    would last so long.
    """

    km_to_nm = 0.539957
    nobs = len(invoyage)

    # no obs in, no qc outcomes out
    if nobs == 0:
        return []

    # Generic ids get a free pass on the track check
    if qc.id_is_generic(invoyage.getvar(0, 'ID'), invoyage.getvar(0, 'YR')):
        qcs = []
        nobs = len(invoyage)
        for i in range(0, nobs):
            invoyage.set_qc(i, 'POS', 'bad_track', 0)
            qcs.append(0)
        return qcs

    # fewer than three obs - set the fewsome flag
    # deck 720 gets a pass prior to 1891 see Carella, Kent, Berry 2015 Appendix A3
    if nobs < 3 and not (invoyage.getvar(0, 'DCK') == 720
                         and invoyage.getvar(0, 'YR') < 1891):
        qcs = []
        nobs = len(invoyage)
        for i in range(0, nobs):
            invoyage.set_qc(i, 'POS', 'fewsome_check', 1)
            qcs.append(0)
        return qcs

    # work out speeds and distances between alternating points
    invoyage.calc_alternate_speeds()

    # what are the mean and mode speeds?
    mean_speed = invoyage.meansp()
    modal_speed = modesp(invoyage.get_speed())
    # set speed limits based on modal speed
    amax, amaxx, amin = set_speed_limits(modal_speed)

    # compare reported speeds and positions if we have them
    forward_diff_from_estimated = distr1(invoyage)
    reverse_diff_from_estimated = distr2(invoyage)
    midpoint_diff_from_estimated = midpt(invoyage)

    # do QC
    qcs = [0]
    all_alwdis = [0]
    invoyage.set_qc(0, 'POS', 'bad_track', 0)
    invoyage.set_qc(0, 'POS', 'fewsome_check', 0)

    for i in range(1, nobs - 1):

        thisqc_a = 0
        thisqc_b = 0

        # together these cover the speeds calculate from point i
        if (invoyage.getvar(i, 'speed') > amax
                and invoyage.getvar(i - 1, 'alt_speed') > amax):
            thisqc_a += 1.00
        elif (invoyage.getvar(i + 1, 'speed') > amax
              and invoyage.getvar(i + 1, 'alt_speed') > amax):
            thisqc_a += 2.00
        elif (invoyage.getvar(i, 'speed') > amax
              and invoyage.getvar(i + 1, 'speed') > amax):
            thisqc_a += 3.00

        # Quality-control by examining the distance
        # between the calculated and reported second position.
        thisqc_b += check_distance_from_estimate(
            invoyage.getvar(i, 'vsi'), invoyage.getvar(i - 1, 'vsi'),
            invoyage.getvar(i, 'time_diff'), forward_diff_from_estimated[i],
            reverse_diff_from_estimated[i])
        # Check for continuity of direction
        thisqc_b += direction_continuity(invoyage.getvar(i, 'dsi'),
                                         invoyage.getvar(i - 1, 'dsi'),
                                         invoyage.getvar(i, 'course'))
        # Check for continuity of speed.
        thisqc_b += speed_continuity(invoyage.getvar(i, 'vsi'),
                                     invoyage.getvar(i - 1, 'vsi'),
                                     invoyage.getvar(i, 'speed'))

        # check for speeds in excess of 40.00 knots
        if invoyage.getvar(i, 'speed') > 40.00 / km_to_nm:
            thisqc_b += 10.0

        # make the final decision
        if (midpoint_diff_from_estimated[i] > 150.0 / km_to_nm and thisqc_a > 0
                and thisqc_b > 0):
            qcs.append(1)
            invoyage.set_qc(i, 'POS', 'bad_track', 1)
            invoyage.set_qc(i, 'POS', 'fewsome_check', 0)
        else:
            qcs.append(0)
            invoyage.set_qc(i, 'POS', 'bad_track', 0)
            invoyage.set_qc(i, 'POS', 'fewsome_check', 0)

    qcs.append(0)
    invoyage.set_qc(nobs - 1, 'POS', 'bad_track', 0)
    invoyage.set_qc(nobs - 1, 'POS', 'fewsome_check', 0)

    return qcs
def mds_track_check(inreps):

    '''
    Perform one pass of the track check
    
    :param inreps: A list of :class:`.MarineReport` that you want track checked
    :type inreps: :class:`.MarineReport`
    :return: list of QC flags 0 for pass and 1 for fail
    :rtype: integer
    
    This is an implementation of the MDS track check code 
    which was originally written in the 1990s. I don't know why this piece of 
    historic trivia so exercises my mind, but it does: the 1990s! I wish my code 
    would last so long.
    '''

    nobs = len(inreps)

#no obs in, no qc outcomes out
    if nobs == 0:
        return []

#Generic ids get a free pass on the track check
    if qc.id_is_generic(inreps[0].id, inreps[0].year) or nobs < 3:
        qcs = []
        nobs = len(inreps)
        for i in range(0, nobs):
            inreps[i].bad_track = 0
            qcs.append(0)
        return qcs
    
#work out speeds and distances between consecutive 
#points and alternating points
    time_diffs, speeds, distances, ship_directions = calc_1step_speeds(inreps)
    alt_time_diffs, alt_speeds, alt_distances, alt_ship_directions = \
    calc_alternate_step_speeds(inreps)

#what are the mean and mode speeds?
    mean_speed = meansp(speeds)
    modal_speed = modesp(speeds)
#set speed limits based on modal speed
    amax, amaxx, amin = set_speed_limits(modal_speed)

#compare reported speeds and positions if we have them
    forward_diff_from_estimated  = distr1(inreps, time_diffs)
    reverse_diff_from_estimated  = distr2(inreps, time_diffs)
    midpoint_diff_from_estimated =  midpt(inreps, time_diffs)

#do QC
    qcs = [0]
    all_alwdis = [0]
    for i in range(1, nobs-1):
        
        thisqc_a = 0
        thisqc_b = 0

#together these cover the speeds calculate from point i        
        if   speeds[i]   > amax and alt_speeds[i-1] > amax:
            thisqc_a += 1.00
        elif speeds[i+1] > amax and alt_speeds[i+1] > amax:
            thisqc_a += 2.00
        elif speeds[i]   > amax and speeds[i+1]     > amax:
            thisqc_a += 3.00 

# Quality-control by examining the distance 
#between the calculated and reported second position.
        thisqc_b += check_distance_from_estimate(inreps[i].vsi, 
                                                 inreps[i-1].vsi, 
                                                 time_diffs[i], 
                                                 forward_diff_from_estimated[i],
                                                 reverse_diff_from_estimated[i])
#Check for continuity of direction                              
        thisqc_b += direction_continuity(inreps[i].dsi, 
                                         inreps[i-1].dsi, 
                                         ship_directions[i])
#Check for continuity of speed.                                 
        thisqc_b += speed_continuity(inreps[i].vsi, 
                                     inreps[i-1].vsi, 
                                     speeds[i])

#check for speeds in excess of 40.00 knots
        if speeds[i] > 40.00:
            thisqc_b += 10.0

#make the final decision
        if (midpoint_diff_from_estimated[i] > 150.0 and 
            thisqc_a > 0 and 
            thisqc_b > 0):
            qcs.append(1)
            inreps[i].bad_track = 1
        else:
            qcs.append(0)
            inreps[i].bad_track = 0
    
    qcs.append(0)
            
    return qcs