def process_azfp(site, data_directory, xml_file, output_directory, dates,
                 tilt_correction):
    """
    Use echopype to convert and process the ASL AZFP bio-acoustic sonar data
    (in *.01A files) to generate echograms for use by the community

    :param site:
    :param data_directory:
    :param xml_file:
    :param output_directory:
    :param dates:
    :param tilt_correction:
    :return data:
    """
    # generate a list of data files given the input dates
    file_list = azfp_file_list(data_directory, dates)

    # reset the file_list to a single index
    file_list = [file for sub in file_list for file in sub]
    if not file_list:
        # if there are no files to process, exit cleanly
        return None

    # make sure the data output directory exists
    output_directory = os.path.join(output_directory,
                                    dates[0] + '-' + dates[1])
    if not os.path.isdir(output_directory):
        os.mkdir(output_directory)

    # convert the list of .01A files using echopype and save the output as NetCDF files
    dc = Convert(file_list, xml_file)
    dc.platform_name = site  # OOI site name
    dc.platform_type = 'Mooring'  # ICES platform type
    dc.platform_code_ICES = '48'  # ICES code: tethered collection of instruments at a fixed location that may
    # include seafloor, mid-water or surface components
    dc.raw2nc(save_path=output_directory)

    # process the data, calculating the volume acoustic backscatter strength and the vertical range
    echo = []
    nc_files = glob.glob(output_directory + '/[12]???????.nc')
    for nc in nc_files:
        tmp_echo = Process(nc)
        tmp_echo.calibrate()  # calculate Sv
        data = tmp_echo.Sv  # extract the Sv dataset
        echo.append(data.sortby('ping_time'))  # append to the echogram list

    # concatenate the data into a single dataset
    data = xr.concat(echo, dim='ping_time', join='outer')
    data = data.sortby(['frequency', 'ping_time'])
    data['frequency'] = data['frequency'].astype(np.float32)
    data['range_bin'] = data['range_bin'].astype(np.int32)
    data['range'] = data['range'].sel(ping_time=data.ping_time[0], drop=True)
    data = data.set_coords('range')

    if tilt_correction:
        range_correction(
            data, tilt_correction)  # apply a tilt correction, if applicable

    # pass the Sv data back for further processing
    return data
Beispiel #2
0
def test_calibrate_ek80_cw():
    """Check noise estimation and noise removal using xarray and brute force using numpy.
    """
    ek80_raw_path = ek80_path.joinpath('D20190822-T161221.raw')
    # Unpack data and convert to .nc file
    tmp = Convert(ek80_raw_path, model="EK80")
    tmp.raw2nc()

    # Read .nc file into an Process object and calibrate
    e_data = Process(tmp.nc_path)
    e_data.calibrate(save=True)
    os.remove(e_data.Sv_path)
Beispiel #3
0
def test_process_AZFP_matlab():
    # Read in the dataset that will be used to confirm working conversions. Generated from MATLAB code.
    Sv_test = loadmat(
        str(azfp_path.joinpath('from_matlab/17082117_matlab_Output_Sv.mat')))
    TS_test = loadmat(
        str(azfp_path.joinpath('from_matlab/17082117_matlab_Output_TS.mat')))

    # Convert to .nc file
    tmp_convert = Convert(str(azfp_path.joinpath('17082117.01A')),
                          str(azfp_path.joinpath('17041823.XML')))
    tmp_convert.raw2nc()

    tmp_echo = Process(tmp_convert.nc_path,
                       salinity=27.9,
                       pressure=59,
                       temperature=None)
    tmp_echo.calibrate(save=True)
    tmp_echo.calibrate_TS(save=True)
    tmp_echo.remove_noise()
    tmp_echo.get_MVBS()

    # Tolerance lowered due to temperature not being averaged as is the case in the matlab code
    # Test Sv data
    def check_output(ds_base, ds_cmp, cal_type):
        for fidx in range(4):  # loop through all freq
            assert np.alltrue(
                ds_cmp.range.isel(frequency=fidx).values == ds_base['Output']
                [0]['Range'][fidx])
            assert np.allclose(ds_cmp[cal_type].isel(frequency=fidx).values,
                               ds_base['Output'][0][cal_type][fidx],
                               atol=1e-13,
                               rtol=0)

    # Check Sv
    check_output(ds_base=Sv_test, ds_cmp=tmp_echo.Sv, cal_type='Sv')

    # Check Sp
    check_output(ds_base=TS_test, ds_cmp=tmp_echo.TS, cal_type='TS')

    os.remove(tmp_echo.Sv_path)
    os.remove(tmp_echo.TS_path)
    del tmp_echo
    os.remove(tmp_convert.nc_path)
Beispiel #4
0
def test_calibration_ek60_echoview():
    ek60_raw_path = str(ek60_path.joinpath(
        'DY1801_EK60-D20180211-T164025.raw'))  # constant range_bin
    ek60_echoview_path = ek60_path.joinpath('from_echoview')

    tmp = Convert(ek60_raw_path)
    tmp.raw2nc(overwrite=True)

    # Read .nc file into an Process object and calibrate
    e_data = Process(tmp.nc_path)
    e_data.calibrate(save=True)

    # Compare with EchoView outputs
    channels = []
    for freq in [18, 38, 70, 120, 200]:
        fname = str(
            ek60_echoview_path.joinpath(
                'DY1801_EK60-D20180211-T164025-Sv%d.csv' % freq))
        channels.append(
            pd.read_csv(fname, header=None, skiprows=[0]).iloc[:, 13:])
    test_Sv = np.stack(channels)
    # Echoview data is missing 1 range. Also the first few ranges are handled differently
    assert np.allclose(test_Sv[:, :, 7:], e_data.Sv.Sv[:, :10, 8:], atol=1e-8)
def process_ek60(site, data_directory, output_directory, dates,
                 tilt_correction):
    """

    :param site:
    :param data_directory:
    :param output_directory:
    :param dates:
    :param tilt_correction:
    :return data:
    """
    # generate a list of data files given the input dates
    file_list = ek60_file_list(data_directory, dates)

    # reset the file_list to a single index
    file_list = [file for sub in file_list for file in sub]
    if not file_list:
        # if there are no files to process, exit cleanly
        return None

    # make sure the data output directory exists
    output_directory = os.path.join(output_directory,
                                    dates[0] + '-' + dates[1])
    if not os.path.isdir(output_directory):
        os.mkdir(output_directory)

    # convert the list of .raw files using echopype and save the output as NetCDF files
    dc = Convert(file_list)
    dc.platform_name = site  # OOI site name
    if site == 'CE02SHBP':
        dc.platform_type = 'Fixed Benthic Node'  # ICES platform type
        dc.platform_code_ICES = '11'  # ICES code
    else:
        dc.platform_type = 'Mooring'  # ICES platform type
        dc.platform_code_ICES = '48'  # ICES code: tethered collection of instruments at a fixed location that may
        # include seafloor, mid-water or surface components
    dc.raw2nc(save_path=output_directory)

    # process the data, calculating the volume acoustic backscatter strength and the vertical range
    echo = []
    sample_thickness = []
    tvg_correction_factor = []
    nc_files = glob.glob(output_directory + '/*OOI-D*.nc')
    for nc in nc_files:
        tmp_echo = Process(nc)
        tmp_echo.calibrate()  # calculate Sv
        data = tmp_echo.Sv  # extract the Sv dataset
        echo.append(data.sortby('ping_time'))  # append to the echogram list
        sample_thickness.append(tmp_echo.sample_thickness.values)
        tvg_correction_factor.append(tmp_echo.tvg_correction_factor)

    # concatenate the data into a single dataset
    data = xr.concat(echo, dim='ping_time', join='outer')
    data = data.sortby(['frequency', 'ping_time'])
    data['range_bin'] = data['range_bin'].astype(np.int32)
    data['range'] = data['range'].sel(ping_time=data.ping_time[0], drop=True)
    data = data.set_coords('range')

    # recalculate the range to deal with some discrepancies caused by the xarray concat
    thickness = np.max(np.array(sample_thickness), 0)
    correction_factor = np.max(tvg_correction_factor)
    range_meter = calc_range(data, thickness, correction_factor)
    data['range'] = data['range'].fillna(range_meter)

    if tilt_correction:
        range_correction(
            data, tilt_correction)  # apply a tilt correction, if applicable

    # pass the Sv data back for further processing
    return data
Beispiel #6
0
def EchoData(nc_path):
    warn("Echodata has been renamed to Process and will no longer be supported in the future.",
         DeprecationWarning, 2)
    return Process(nc_path)