Esempio n. 1
0
def calculate_bottle_oxygen(ssscc_list, ssscc_col, titr_vol, titr_temp,
                            flask_nums):
    """
    Wrapper function for collecting parameters and calculating oxygen values from
    Winkler titrations.

    Parameters
    ----------
    ssscc_list : list of str
        List of stations to process
    ssscc_col : array-like
        Station/cast for each sample taken
    titr_vol : array-like
        Titration volume [mL]
    titr_temp : array-like
        Temperature of titration [degC]
    flask_nums : array-like
        Oxygen flask used for each sample

    Returns
    -------
    oxy_mL_L : array-like
        Oxygen concentration [mL/L]

    Notes
    -----
    Titration equation comes from WHP Operations and Methods, Culberson (1991):
    https://cchdo.github.io/hdo-assets/documentation/manuals/pdf/91_1/culber2.pdf

    """
    params = pd.DataFrame()
    for ssscc in ssscc_list:
        df = gather_oxy_params(cfg.directory["oxy"] + ssscc)
        df["SSSCC"] = ssscc
        params = pd.concat([params, df])

    # get flask volumes and merge with titration parameters
    flask_df = load_flasks()  # TODO: volume correction from thermal expansion?
    volumes = pd.merge(flask_nums, flask_df, how="left")["FLASK_VOL"].values
    params = pd.merge(ssscc_col, params, how="left")

    # find 20degC equivalents
    rho_20C = gsw.rho_t_exact(0, 20, 0)
    rho_T_KIO3 = gsw.rho_t_exact(0, params["T_KIO3"], 0)
    N_KIO3_20C = params["N_KIO3"] * (rho_T_KIO3 / rho_20C)

    # TODO: does KIO3 volume get corrected? what is the recorded value?
    # V_KIO3_20C = correct_flask_vol(params["V_KIO3"], t=params["T_KIO3"])

    # calculate O2 concentration (in mL/L)
    E = 5598  # stoichiometric relationship between thio_n and DO
    DO_reg = 0.0017  # correction for oxygen added by reagents
    V_reg = 2.0  # volume of reagents (mL)

    oxy_mL_L = ((((titr_vol.values - params["V_blank"]) * params["V_KIO3"] *
                  N_KIO3_20C * E) / (params["V_std"] - params["V_blank"]) -
                 1000 * DO_reg)) / (volumes - V_reg)

    return oxy_mL_L.values
Esempio n. 2
0
def bfrq(T, S, z, lat, lon):
    """
    Calculate Bouyancy frequency from practical salinity and temperature.
    Converts to potential temperature and absolute salinity to calculate density
    """

    SA = gsw.conversions.SA_from_SP(S, z, lon, lat)
    g = gsw.grav(lat, z)
    pdens = gsw.rho_t_exact(SA, T, z)
    dpdens = np.gradient(gsw.rho_t_exact(SA, T, z), axis=0)
    dz = np.gradient(z, axis=0)
    N2 = (g / pdens) * (dpdens / dz)

    return N2
Esempio n. 3
0
    def read_dbds(self, fns, settings):
        if settings['buoyancy_engine']=='shallow':
            buoyancy_variable='m_ballast_pumped'
        elif settings['buoyancy_engine']=='deep':
            buoyancy_variable='m_de_oil_vol'
        else:
            raise ValueError('Unknown buoyancy engine. Accepted values: (shallow|deep)')
        dbd = dbdreader.MultiDBD(filenames=fns, include_paired=True)
        tmp = dbd.get_sync("sci_ctd41cp_timestamp",["sci_water_pressure",
                                                    "sci_water_cond",
                                                    "sci_water_temp",
                                                    "m_pitch",
                                                    "m_battpos",
                                                    buoyancy_variable])
        _, tctd, P, C, T, pitch, battpos, buoyancy_change = tmp.compress(tmp[3]>0.01, axis=1)
        SP = gsw.SP_from_C(C*10, T, P*10)
        SA = gsw.SA_from_SP(SP, P*10, settings['longitude'], settings['latitude'])
        density = gsw.rho_t_exact(SA, T, P*10)
        
        #density = fast_gsw.rho(C*10, T, P*10, settings['longitude'], settings['latitude'])

        data = dict(time=tctd, pressure=P, pitch=pitch,
                    buoyancy_change=buoyancy_change, battpos=battpos, density=density)
        self.model.input_data = data
        mask=np.zeros(tctd.shape,'int').astype(bool) # use all data by default
        self.model.set_mask(mask)
        self.model.OR(P*10<settings['minlimitdepth'])
        self.model.OR(P*10>settings['maxlimitdepth'])
Esempio n. 4
0
def compute_buoyancy(data, temperature_var='SST', salinity_var='SSS'):
    """
    Compute buoyancy from a dataset containing salinity and temperature 
    variables
    
    Parameters
    ----------
    data : xarray.Dataset
        A Dataset containing salinity and temperature variables
    temperature_var : str, optional
        The name of the temperature variable. Default is "SST".
    salinity_var : str, optional
        The name of the salinity variable Default is "SSS"
    
    Returns
    -------
    res : xarray.Dataset
        A Dataset similar to the input but with a new variable 
        "buoyancy"     
    """

    p = 0 * data['lon']
    SA = gsw.SA_from_SP(data[salinity_var], p, data['lon'], data['lat'])
    rho = gsw.rho_t_exact(SA, data[temperature_var], p)
    b = 9.81 * (1 - rho / 1025.)
    return data.assign(buoyancy=xr.DataArray(b, dims='time'))
Esempio n. 5
0
 def read_dbds(self, fns, settings):
     if settings['buoyancy_engine'] == 'shallow':
         buoyancy_variable = 'm_ballast_pumped'
     elif settings['buoyancy_engine'] == 'deep':
         buoyancy_variable = 'm_de_oil_vol'
     else:
         raise ValueError(
             'Unknown buoyancy engine. Accepted values: (shallow|deep)')
     dbd = dbdreader.MultiDBD(filenames=fns, complement_files=True)
     try:
         tmp = dbd.get_CTD_sync("m_pitch", "m_battpos", buoyancy_variable)
     except dbdreader.DbdError:
         tmp = dbd.get_sync("sci_water_cond", "sci_water_temp",
                            "sci_water_pressure", "m_pitch", "m_battpos",
                            buoyancy_variable)
     try:
         (_, lat), (_, lon) = dbd.get("m_gps_lat", "m_gps_lon")
     except dbdreader.DbdError:
         latitude = float(input("Provide decimal latitude:"))
         longitude = float(input("Provide decimal longitude:"))
     else:
         latitude = np.median(lat)
         longitude = np.median(lon)
     condition = np.logical_and(tmp[2] > 0.01,
                                np.isfinite(np.sum(tmp, axis=0)))
     tctd, C, T, P, pitch, battpos, buoyancy_change = np.compress(condition,
                                                                  tmp,
                                                                  axis=1)
     SP = gsw.SP_from_C(C * 10, T, P * 10)
     SA = gsw.SA_from_SP(SP, P * 10, longitude, latitude)
     density = gsw.rho_t_exact(SA, T, P * 10)
     #density = fast_gsw.rho(C*10, T, P*10, longitude, latitude)
     data = dict(time=tctd,
                 pressure=P,
                 pitch=pitch,
                 buoyancy_change=buoyancy_change,
                 battpos=battpos,
                 density=density)
     self.model.input_data = data
     mask = np.zeros(tctd.shape,
                     'int').astype(bool)  # use all data by default
     self.model.set_mask(mask)
     self.model.OR(P * 10 < settings['minlimitdepth'])
     self.model.OR(P * 10 > settings['maxlimitdepth'])