def process_report(path):
    'Processes data from vessel movement report. Adds data from wind buoys,\n    performs meeting and passing analysis. Creates other relevant columns.\n\n    Args:\n        path: Relative path to raw vessel movement report (CSV).\n\n    Returns:\n        Two pairs of two DataFrames cooresponding to the movement report.\n        The first pair of DataFrames contains all vessel movements belonging to\n        Charleston and Savannah, respectively. The second pair of DataFrames\n        stores the vessel movement entries at which each vessel achieved\n        its maximum speed. Again, the first DataFrame in the pair belongs to\n        Charleston and the second DataFrame belongs to Savannah.\n    '
    blacklist = [int(mmsi) for mmsi in open('../cache/blacklist.txt', 'r').readlines()]
    df = pd.read_csv(path)
    df = _wrangle_vmr(df, {'DATETIME (UTC)': 'Date/Time UTC', 'NAME': 'Name', 'LATITUDE': 'Latitude', 'LONGITUDE': 'Longitude', 'SPEED': 'VSPD kn', 'COURSE': 'Course', 'HEADING': 'Heading', 'AIS TYPE': 'AIS Type'})
    ch_course_ranges = ((100, 140), (280, 320))
    sv_course_ranges = ((100, 160), (280, 340))
    channel_midpoint = ((- 79.74169), (- 80.78522))
    course_ranges = (ch_course_ranges, sv_course_ranges)
    ports = [None, None]
    buoys = [{'41004': None}, {'41008': None}]
    alt_buoys = [{'41008': None}, {'41004': None}]
    for i in range(len(ports)):
        ch_df = (df.loc[:, 'Latitude'] >= 32.033)
        sv_df = (df.loc[:, 'Latitude'] < 32.033)
        ports[i] = (df[ch_df] if (i == 0) else df[sv_df])
        if (not len(ports[i])):
            empty = pd.DataFrame({'Date/Time UTC': [], 'Name': [], 'MMSI': [], 'Max Speed kn': [], 'Mean Speed kn': [], 'LOA ft': [], 'Beam ft': [], 'Class': [], 'AIS Type': [], 'Course': [], 'Heading': [], 'Course Behavior': [], 'Yaw deg': [], 'Effective Beam ft': [], 'WDIR degT': [], 'WSPD mph': [], 'GST mph': [], 'Buoy Source': [], 'Location': [], 'Latitude': [], 'Longitude': [], 'Transit': [], '% Channel Occupied': []})
            ports[i] = [empty, empty]
            continue
        ports[i].loc[:, 'Location'] = 'Nearshore'
        off_row = (ports[i].loc[:, 'Longitude'] > channel_midpoint[i])
        off_loc = ports[i].loc[off_row, :].index
        offshore_indices = ports[i].index.isin(off_loc)
        ports[i].loc[(offshore_indices, 'Location')] = 'Offshore'
        ports[i] = add_wind(ports, i, buoys, alt_buoys)
        ports[i] = _course_behavior(ports[i], course_ranges[i])
        ports[i] = _add_vessel_class(ports[i])
        ports[i].loc[:, 'Yaw deg'] = abs((ports[i].loc[:, 'Course'] - ports[i].loc[:, 'Heading']))
        eff_beam = []
        loa = ports[i].loc[:, 'LOA ft'].values
        beam = ports[i].loc[:, 'Beam ft'].values
        yaw = ports[i].loc[:, 'Yaw deg'].values
        for l in range(ports[i].shape[0]):
            eff_beam.append(round(((math.cos(math.radians((90 - yaw[l]))) * loa[l]) + (math.cos(math.radians(yaw[l])) * beam[l]))))
        ports[i].loc[:, 'Effective Beam ft'] = eff_beam
        ports[i].loc[:, 'Effective Beam ft'] = ports[i].loc[:, 'Effective Beam ft'].round(0)
        ports[i] = _filter_blacklisters(ports[i], blacklist)
        stamps = len(ports[i].loc[:, 'Date/Time UTC'])
        round_times = [ports[i].loc[:, 'Date/Time UTC'].iloc[ii].floor('Min') for ii in range(stamps)]
        ports[i].loc[:, 'rounded date'] = round_times
        mp = meetpass(ports[i])
        two_way = twoway(ports[i], mp)
        ports[i].loc[:, 'Transit'] = 'One-way Transit'
        if (not isinstance(two_way, type(None))):
            two_way_indices = ports[i].index.isin(two_way.index)
            ports[i].loc[(two_way_indices, 'Transit')] = 'Two-way Transit'
        ports[i] = ports[i].reset_index()
        ports[i] = _add_channel_occ(ports, i)
        all_res = ports[i]
        if (i % 2):
            all_res = all_res[(((all_res.loc[:, 'Latitude'] <= 32.02838) & (all_res.loc[:, 'Latitude'] >= 31.9985)) | (all_res.loc[:, 'Latitude'] <= 31.99183))]
        else:
            all_res = all_res[(all_res.loc[:, 'Latitude'] >= 32.667473)]
        fold_res = _fold_vmr(ports, i)
        fold_res = fold_res.loc[:, ('Date/Time UTC', 'Name', 'MMSI', 'Max Speed kn', 'Mean Speed kn', 'LOA ft', 'Beam ft', 'Class', 'AIS Type', 'Course', 'Heading', 'Course Behavior', 'Yaw deg', 'Effective Beam ft', 'WDIR degT', 'WSPD mph', 'GST mph', 'Buoy Source', 'Location', 'Latitude', 'Longitude', 'Transit', '% Channel Occupied')]
        all_res = all_res.loc[:, ('Name', 'MMSI', 'VSPD kn', 'WSPD mph', 'Transit', '% Channel Occupied', 'Yaw deg', 'Effective Beam ft', 'LOA ft', 'Beam ft', 'Class', 'AIS Type', 'Course', 'Heading', 'Course Behavior', 'WDIR degT', 'GST mph', 'Buoy Source', 'Location', 'Latitude', 'Longitude', 'Date/Time UTC')]
        ports[i] = [fold_res, all_res]
    return (ports[0], ports[1])
Processes data from vessel movement report. Adds data from wind buoys,
performs meeting and passing analysis. Creates other relevant columns.

Args:
    path: Relative path to raw vessel movement report (CSV).

Returns:
    Two pairs of two DataFrames cooresponding to the movement report.
    The first pair of DataFrames contains all vessel movements belonging to
    Charleston and Savannah, respectively. The second pair of DataFrames
    stores the vessel movement entries at which each vessel achieved
    its maximum speed. Again, the first DataFrame in the pair belongs to
    Charleston and the second DataFrame belongs to Savannah.
def process_report(path):
    'Processes data from vessel movement report. Adds data from wind buoys,\n    performs meeting and passing analysis. Creates other relevant columns.\n\n    Args:\n        path: Relative path to raw vessel movement report (CSV).\n\n    Returns:\n        Two pairs of two DataFrames cooresponding to the movement report.\n        The first pair of DataFrames contains all vessel movements belonging to\n        Charleston and Savannah, respectively. The second pair of DataFrames\n        stores the vessel movement entries at which each vessel achieved\n        its maximum speed. Again, the first DataFrame in the pair belongs to\n        Charleston and the second DataFrame belongs to Savannah.\n    '
    blacklist = [int(mmsi) for mmsi in open('../cache/blacklist.txt', 'r').readlines()]
    df = pd.read_csv(path)
    df = _wrangle_vmr(df, {'DATETIME (UTC)': 'Date/Time UTC', 'NAME': 'Name', 'LATITUDE': 'Latitude', 'LONGITUDE': 'Longitude', 'SPEED': 'VSPD kn', 'COURSE': 'Course', 'HEADING': 'Heading', 'AIS TYPE': 'AIS Type'})
    ch_course_ranges = ((100, 140), (280, 320))
    sv_course_ranges = ((100, 160), (280, 340))
    channel_midpoint = ((- 79.74169), (- 80.78522))
    course_ranges = (ch_course_ranges, sv_course_ranges)
    ports = [None, None]
    buoys = [{'41004': None}, {'41008': None}]
    alt_buoys = [{'41008': None}, {'41004': None}]
    for i in range(len(ports)):
        ch_df = (df.loc[:, 'Latitude'] >= 32.033)
        sv_df = (df.loc[:, 'Latitude'] < 32.033)
        ports[i] = (df[ch_df] if (i == 0) else df[sv_df])
        if (not len(ports[i])):
            empty = pd.DataFrame({'Date/Time UTC': [], 'Name': [], 'MMSI': [], 'Max Speed kn': [], 'Mean Speed kn': [], 'LOA ft': [], 'Beam ft': [], 'Class': [], 'AIS Type': [], 'Course': [], 'Heading': [], 'Course Behavior': [], 'Yaw deg': [], 'Effective Beam ft': [], 'WDIR degT': [], 'WSPD mph': [], 'GST mph': [], 'Buoy Source': [], 'Location': [], 'Latitude': [], 'Longitude': [], 'Transit': [], '% Channel Occupied': []})
            ports[i] = [empty, empty]
            continue
        ports[i].loc[:, 'Location'] = 'Nearshore'
        off_row = (ports[i].loc[:, 'Longitude'] > channel_midpoint[i])
        off_loc = ports[i].loc[off_row, :].index
        offshore_indices = ports[i].index.isin(off_loc)
        ports[i].loc[(offshore_indices, 'Location')] = 'Offshore'
        ports[i] = add_wind(ports, i, buoys, alt_buoys)
        ports[i] = _course_behavior(ports[i], course_ranges[i])
        ports[i] = _add_vessel_class(ports[i])
        ports[i].loc[:, 'Yaw deg'] = abs((ports[i].loc[:, 'Course'] - ports[i].loc[:, 'Heading']))
        eff_beam = []
        loa = ports[i].loc[:, 'LOA ft'].values
        beam = ports[i].loc[:, 'Beam ft'].values
        yaw = ports[i].loc[:, 'Yaw deg'].values
        for l in range(ports[i].shape[0]):
            eff_beam.append(round(((math.cos(math.radians((90 - yaw[l]))) * loa[l]) + (math.cos(math.radians(yaw[l])) * beam[l]))))
        ports[i].loc[:, 'Effective Beam ft'] = eff_beam
        ports[i].loc[:, 'Effective Beam ft'] = ports[i].loc[:, 'Effective Beam ft'].round(0)
        ports[i] = _filter_blacklisters(ports[i], blacklist)
        stamps = len(ports[i].loc[:, 'Date/Time UTC'])
        round_times = [ports[i].loc[:, 'Date/Time UTC'].iloc[ii].floor('Min') for ii in range(stamps)]
        ports[i].loc[:, 'rounded date'] = round_times
        mp = meetpass(ports[i])
        two_way = twoway(ports[i], mp)
        ports[i].loc[:, 'Transit'] = 'One-way Transit'
        if (not isinstance(two_way, type(None))):
            two_way_indices = ports[i].index.isin(two_way.index)
            ports[i].loc[(two_way_indices, 'Transit')] = 'Two-way Transit'
        ports[i] = ports[i].reset_index()
        ports[i] = _add_channel_occ(ports, i)
        all_res = ports[i]
        if (i % 2):
            all_res = all_res[(((all_res.loc[:, 'Latitude'] <= 32.02838) & (all_res.loc[:, 'Latitude'] >= 31.9985)) | (all_res.loc[:, 'Latitude'] <= 31.99183))]
        else:
            all_res = all_res[(all_res.loc[:, 'Latitude'] >= 32.667473)]
        fold_res = _fold_vmr(ports, i)
        fold_res = fold_res.loc[:, ('Date/Time UTC', 'Name', 'MMSI', 'Max Speed kn', 'Mean Speed kn', 'LOA ft', 'Beam ft', 'Class', 'AIS Type', 'Course', 'Heading', 'Course Behavior', 'Yaw deg', 'Effective Beam ft', 'WDIR degT', 'WSPD mph', 'GST mph', 'Buoy Source', 'Location', 'Latitude', 'Longitude', 'Transit', '% Channel Occupied')]
        all_res = all_res.loc[:, ('Name', 'MMSI', 'VSPD kn', 'WSPD mph', 'Transit', '% Channel Occupied', 'Yaw deg', 'Effective Beam ft', 'LOA ft', 'Beam ft', 'Class', 'AIS Type', 'Course', 'Heading', 'Course Behavior', 'WDIR degT', 'GST mph', 'Buoy Source', 'Location', 'Latitude', 'Longitude', 'Date/Time UTC')]
        ports[i] = [fold_res, all_res]
    return (ports[0], ports[1])