Example #1
0
def calculate_n2(T, p, C, lat, long):
    """Calculates the buoyancy frequency N^2
    All parameters and output are float or array-like.
    :param T: temperature (deg C)
    :param p: pressure (bar)
    :param C: conductivity (S/m)
    :param lat: latitude (decimal deg)
    :param long: longitude (decimal deg)
    :return: buoyancy (i.e. brunt-vaisala) frequency N^2 (s^-2)
    """
    # pressure in dbars = pressure * 10
    p_dbar = p * 10

    # conductivity in mS/cm = conductivity * 10
    C_mScm = C * 10

    print(T.count())
    print(p.count())
    print(C.count())
    print(lat.count())
    print(long.count())
    # calculate SP from conductivity (mS/cm), in-situ temperature (deg C), and gauge pressure (dbar)
    SP = gsw.SP_from_C(C_mScm, T, p_dbar)
    # calculate SA from SP (unitless), gauge pressure (dbar), longitude and latitude (decimal degrees)
    SA = gsw.SA_from_SP(SP, p_dbar, long, lat)
    # calculate CT from SA (g/kg), in-situ temperature (deg C), and gauge pressure (dbar)
    CT = gsw.CT_from_t(SA, T, p_dbar)
    # calculate N^2
    nsquared, p_mid = gsw.Nsquared(SA, CT, p_dbar, lat=lat)
    return nsquared
Example #2
0
def get_hydro(my_file):
    f = Dataset(my_file, mode='r')

    eps = f.variables['EPSILON'][:]
    eps = remove_bad_eps(eps)
    lat = f.variables['LATITUDE'][:]
    lon = f.variables['LONGITUDE'][:]
    p = f.variables['PRESSURE'][:]
    SP = f.variables['PSAL'][:]
    T = f.variables['TEMPERATURE'][:]

    z = gsw.z_from_p(p, lat)  # m
    SA = gsw.SA_from_SP(SP, p, lon, lat)  #  g/kg, absolute salinity
    CT = gsw.CT_from_t(SA, T, p)  # C, conservative temperature

    SA = remove_bad_SA(SA)
    CT = remove_bad_CT(CT)

    [N2_mid, p_mid] = gsw.Nsquared(SA, CT, p, lat)
    z_mid = gsw.z_from_p(p_mid, lat)

    N2 = interp_to_edges(N2_mid, z, z_mid, 4)
    N2 = np.append(np.append(N2, [np.nan]), [np.nan])
    N2 = remove_bad_N2(N2)

    return N2, SA, CT, eps, z
    def interpolate(self):
        self.ipres = range(int(min(self.pres)),int(max(self.pres)))
        if len(self.pres)>4:

            self.isals = np.interp(self.ipres,self.pres,self.sals)
            self.itemps = np.interp(self.ipres,self.pres,self.temps)
            if hasattr(self,"knownu"):
                self.iknownu = np.interp(self.ipres,self.pres,self.knownu)
                self.iknownv = np.interp(self.ipres,self.pres,self.knownv)
            if hasattr(self,"knownpsi"):
                self.iknownpsi = np.interp(self.ipres,self.pres,self.knownpsi)

            if hasattr(self,"kapredi"):
                self.ikapredi = np.interp(self.ipres,self.pres,self.kapredi)
                self.idiffkr = np.interp(self.ipres,self.pres,self.diffkr)
                self.ikapgm = np.interp(self.ipres,self.pres,self.kapgm)
            #plt.plot(self.temps,self.pres)
            #plt.plot(self.itemps,self.ipres)
            #plt.show()
            self.ialpha = gsw.alpha(self.isals,self.itemps,self.ipres)
            self.ibeta = gsw.beta(self.isals,self.itemps,self.ipres)
            self.idalphadtheta = gsw.cabbeling(self.isals,self.itemps,self.ipres)
            self.idalphadp = gsw.thermobaric(self.isals,self.itemps,self.ipres)

            ###using gsw
            self.n2 = gsw.Nsquared(self.isals,self.itemps,self.ipres,self.maplat)[0]
def common_thermodynamics(depth, lon, lat, SP, t):
    """Wrapper for various thermodynamic calculations.

    Assumes input data is 1D with size N or M, or 2D with size N*M,
    where M denotes profiles and N depths.

    Parameters
    ----------
        depth : numpy array
            Depth (m), size N.
        lon : numpy array
            Longitude, size M.
        lat : numpy array
            Latitude, size M.
        SP : numpy array
            Practical salinity, size N*M.
        t : numpy array
            Temperature, size N*M.

    """

    p = gsw.p_from_z(-depth, np.mean(lat))
    SA = gsw.SA_from_SP(SP, p[:, np.newaxis], lon[np.newaxis, :],
                        lat[np.newaxis, :])
    CT = gsw.CT_from_t(SA, t, p[:, np.newaxis])
    sig0 = gsw.pot_rho_t_exact(SA, t, p[:, np.newaxis], 0)
    N2, p_mid = gsw.Nsquared(SA, CT, p[:, np.newaxis], lat[np.newaxis, :])

    return p, SA, CT, sig0, p_mid, N2
Example #5
0
def derive_variables(dbase, which_ones='all'):
    """
    Also include density, potential temp and density; and uncertainties!!
    """
    SA_dat = [
        gsw.SA_from_SP(dbase['sal'][n], dbase['pres'][n], dbase['lon'][n],
                       dbase['lat'][n]) for n in range(0, len(dbase))
    ]
    CT_dat = [
        gsw.CT_from_t(SA_dat[n], dbase['temp'][n], dbase['pres'][n])
        for n in range(0, len(dbase))
    ]
    N2_dat = [
        gsw.Nsquared(
            SA_dat[n],
            CT_dat[n],
            dbase['pres'][n],
            dbase['lat'][n],
            alphabeta=True,
        ) for n in range(0, len(dbase))
    ]
    if which_ones == 'all':
        return SA_dat, CT_dat, N2_dat
    elif which_ones == 'N2':
        return N2_dat
Example #6
0
def brunt_vaisala(SP,
                  t,
                  p,
                  lon=-45.401666,
                  lat=-23.817233,
                  interpolate=True,
                  result='frequency'):
    """
    Returns Brunt-Väisäla (or buoyancy) frequency/period from practical
    salinity, in situ temperature and pressure (depth).
    
    Parameters
    ----------
    SP : array like
        Salinity (PSS-78) [1e-3]
    t : array like
        Temperature (ITS-90) [degC]
    p : array like
        Pressure [dbar]
    lon : array like, float, optional
        Longitude, decimal degrees east
    lat : array like, float, optional
        Latitude, decimal degrees north
    interpolate : boolean, optional
        If True, interpolates calculated frequency to original pressure
        (depth) levels. If False, returns results at mid pressure 
        between pressugre grid.
    result : {'freuency', 'period'}, optional
        Sets whether to return `frequency` [in 
    
    Returns
    -------
    N : array like
        Brunt-Väisälä frequency [s-1] or period [s].
    p : array like
        Pressure levels [dbar].
    
    
    """
    # Calculates Absolute Salinity from Practical Salinity
    SA = gsw.SA_from_SP(SP, p, lon, lat)
    # Calcualtes Conservative Temperature from in situ temperature
    CT = gsw.CT_from_t(SA, t, p)
    #
    N2, p_mid = gsw.Nsquared(SA, CT, p, lat=lat)
    N2[N2 < 0] = 0
    #
    if interpolate:
        N2 = interp(p, p_mid, N2)
    #
    if result == 'frequency':
        return N2**0.5, p_mid
    elif result == 'period':
        return 1. / N2**0.5, p_mid
    else:
        raise ValueError('Invalid result type {}.'.format(result))
Example #7
0
 def _update_eos(self):
     # derive absolute salinity and conservative temperature
     self.SA = gsw.SA_from_SP(self.s, self.p, self.lon, self.lat)
     self.CT = gsw.CT_from_t(self.SA, self.temp, self.p)
     # derive N2
     self.N2, self.p_mid = gsw.Nsquared(self.SA,
                                        self.CT,
                                        self.p,
                                        lat=self.lat)
     self.z_mid = gsw.z_from_p(self.p_mid, self.lat)
Example #8
0
def Nsquared(S, T, p, lat=None, lon=None, dim='p'):
    ones = xr.ones_like(S)
    p = ones * S[dim]
    if lat is None:
        lat = ones * S['lat']
    if lon is None:
        lon = ones * S['lon']
    SA = gsw.SA_from_SP(S, p, lon, lat)
    CT = gsw.CT_from_t(SA, T, p)
    N2, pmid = gsw.Nsquared(SA, CT, p, axis=S.get_axis_num(dim))
    return N2, pmid
    def test(self):
        sal = np.array([0.1, 0.1])  #
        temp = np.array([4., 21.])  # Celsius
        pres = np.array([10., 20.])
        rho = gsw.rho(sal, temp, pres)
        print("density", rho)

        lat = [43.2, 43.2]
        CT = gsw.CT_from_t(sal, temp, pres)
        N2, p_mid = gsw.Nsquared(sal, CT, pres, lat=lat)
        print("N2", N2)
        print("p_mid", p_mid)
 def Burger(self, data, H, L):
     '''
     Bu = NH/fL   in which
            N is the buoyancy frequency,
            f is the Coriolis parameter
            H characteristic vertical length scale
            L characteristic horizontal length scale
     '''
     sal, CT, pres, lat = data
     N2 = gsw.Nsquared(sal, CT, pres, lat=lat)
     f = gsw.f(lat)
     Bu = (np.sqrt(N2) * H) / (f * L)
     return Bu
Example #11
0
def add_nsquared(mp):
    if "SA" not in mp:
        mp = add_gsw_variables(mp)
    N2, pmid = gsw.Nsquared(mp.SA, mp.CT, mp.P)
    fint = sp.interpolate.interp1d(x=pmid[:, 0],
                                   y=N2,
                                   axis=0,
                                   bounds_error=False)
    N2i = fint(mp.p)
    mp["N2"] = (("z", "time"), N2i)
    mp.N2.attrs["long_name"] = r"N$^2$"
    mp.N2.attrs["units"] = r"s$^{-2}$"
    return mp
Example #12
0
    def interpolate(self):
        self.ipres = range(int(min(self.pres)), int(max(self.pres)))
        if len(self.pres) > 4:

            self.isals = np.interp(self.ipres, self.pres, self.sals)
            self.itemps = np.interp(self.ipres, self.pres, self.temps)
            self.igamma = np.interp(self.ipres, self.pres, self.gamma)
            self.ialpha = gsw.alpha(self.isals, self.itemps, self.ipres)
            self.ibeta = gsw.beta(self.isals, self.itemps, self.ipres)
            self.idalphadtheta = gsw.cabbeling(self.isals, self.itemps,
                                               self.ipres)
            self.idalphadp = gsw.thermobaric(self.isals, self.itemps,
                                             self.ipres)

            ###using gsw
            self.n2 = gsw.Nsquared(self.isals, self.itemps, self.ipres,
                                   self.lat)[0]
Example #13
0
def calc_n2(SA, CT, rho, depth, alpha, g=9.8, po=1027, gsw=True):
    """
    gsw implementation of n2, 
    decomposed into temp and salt components
    """
    if gsw == True:
        # From gsw package
        import gsw
        n2 = gsw.Nsquared(SA, CT, depth, axis=0)
        n2_t = (-g * alpha * np.diff(CT, axis=0))  # Temperature component
        n2_s = n2 - n2_t  # Salt component
    else:
        # From buoyancy
        by = g * (1 - rho / po)  # Buoyancy

        n2 = np.diff(by * -1, axis=0)
        n2_t = (-g * alpha[:-1, :] * np.diff(CT, axis=0)
                )  # Temperature component
        n2_s = n2 - n2_t  # Salt component

    return n2, n2_t, n2_s
Example #14
0
def BV2(S,T,depth,lon,lat):
    p1=gsw.p_from_z(depth,np.array(lat))
    sa=gsw.SA_from_SP(S,p1,lon,lat)
    ct=gsw.CT_from_pt(sa,T)
    N2,pOut=gsw.Nsquared(sa,ct,p1,lat)
    return N2,pOut
Example #15
0
for var in list(dsSX.var()):
    if var != 'profile_index':
        exec('sx_' + var + '[ppitch<0] = sx_' + var + '[ppitch<0].fillna(method="ffill", limit=5, axis=1)')
        exec('sx_' + var + '[ppitch>0] = sx_' + var + '[ppitch>0].fillna(method="bfill", limit=5, axis=1)')
print('  Done!')
                    
# TEOS-10 conversion SeaExplorer
P = sx_pressure.values
lon0, lat0 = dsSX['longitude'].values.mean(), dsSX['latitude'].values.mean()
SA = gsw.SA_from_SP(sx_salinity.values, P, lon0, lat0)
CT = gsw.CT_from_t(SA, sx_temperature.values, P)
sigma0 = gsw.sigma0(SA, CT)
SA_sort = np.array(list(map(lambda x, y: y[x], np.argsort(sigma0, axis=1), SA)))
CT_sort = np.array(list(map(lambda x, y: y[x], np.argsort(sigma0, axis=1), CT)))
P_sort = np.array(list(map(lambda x, y: y[x], np.argsort(sigma0, axis=1), P)))
N2, p_mid = gsw.Nsquared(SA_sort, CT_sort, P_sort, lat=lat0, axis=1)

# Oxygen conversion
Ofreq = sx_oxygen_frequency.values
Soc = float(dpl['calibration.SBE43F.soc'])
Foffset = float(dpl['calibration.SBE43F.foffset'])
A = float(dpl['calibration.SBE43F.a'])
B = float(dpl['calibration.SBE43F.b'])
C = float(dpl['calibration.SBE43F.c'])
E = float(dpl['calibration.SBE43F.e'])

K = CT + 273.15 # Temp in Kelvin
O2sol = gsw.O2sol(SA, CT, P, lon0, lat0); #umol/Kg
O2 =  Soc*(Ofreq+Foffset)*(1.0+A*CT + B*CT**2 + C*CT**3)*O2sol*np.exp(E*P/K); 

# MiniFluo calib (# Assume new version)
    Np = len(MP['id'])
    if np.ndim(MP['lon']) != 0:
        MP['lon'] = MP.pop('lon')[0]
        MP['lat'] = MP.pop('lat')[0]
    MP['P'] = np.tile(MP['p'][:, np.newaxis].astype(float), (1, Np))
    MP['T'] = MP.pop('t')
    MP['S'] = MP.pop('s')
    MP['z'] = gsw.z_from_p(MP['P'], MP['lat'])
    MP['HAB'] = MP['z'] - np.nanmin(MP['z']) + 20.
    MP['SA'] = gsw.SA_from_SP(MP['S'], MP['P'], MP['lon'], MP['lat'])
    MP['CT'] = gsw.CT_from_t(MP['SA'], MP['T'], MP['P'])
    MP['sig4'] = gsw.pot_rho_t_exact(MP['SA'], MP['T'], MP['P'], 4000)
    MP['g'] = gsw.grav(MP['lat'], MP['P'])
    MP['sig4m'] = np.nanmean(MP['sig4'])
    MP['sig4_sorted'] = utils.nansort(MP['sig4'], axis=0)
    MP['N2'], MP['P_mid'] = gsw.Nsquared(MP['SA'], MP['CT'], MP['P'],
                                         MP['lat'])
    MP['z_mid'] = gsw.z_from_p(MP['P_mid'], MP['lat'])
    MP['ual'], MP['uac'] = rotate_overflow(MP['u'], MP['v'], MP['sig4'],
                                           sig4max)

    print('- Calculating the overflow integrated velocity')
    ual_ = MP['ual'].copy()
    uac_ = MP['uac'].copy()
    mask = MP['sig4'] < sig4max
    ual_[mask] = np.nan
    uac_[mask] = np.nan
    MP['uoal'] = utils.nantrapz(ual_, x=MP['z'], axis=0, xave=True)
    MP['uoac'] = utils.nantrapz(uac_, x=MP['z'], axis=0, xave=True)

    print('- Calculating neutral density')
    MP['PT0'] = seawater.ptmp(MP['S'], MP['T'], MP['P'])
Example #17
0
# N^2 = -\frac{g}{\rho} \frac{d \rho}{dz}
# $$
# $$
# \rho = \alpha_T \theta
# $$
# $$
# T_{z0} = \frac{N^2}{g \alpha_T}
# $$

# %%
zshift = 50  # shift peak by how many metres

tmp = sec9.where(sec9.station == 12, drop=True)
SA = gsw.SA_from_SP(tmp.s.squeeze(), tmp.p.squeeze(), tmp.lon, tmp.lat)
CT = gsw.CT_from_t(SA, tmp.t.squeeze(), tmp.p.squeeze())
N2, pmid = gsw.Nsquared(SA, CT, tmp.p.squeeze(), tmp.lat)
zmid = utils.mid(tmp.z.data)
good = np.isfinite(N2)
N2smooth = utils.convolve_smooth(N2[good], 100)
zs = zmid[good]

imax, _ = sp.signal.find_peaks(N2smooth, height=(3e-6, 5e-6), prominence=2e-6)
hw = 220
ispeak = (zs > zs[imax - hw]) & (zs < zs[imax + hw])
N2filled = np.interp(zs, zs[~ispeak], N2smooth[~ispeak])
N2peak = (N2smooth - N2filled)
fpeak = sp.interpolate.interp1d(zs,
                                N2peak,
                                bounds_error=False,
                                fill_value=(0, 0))
N2shifted = N2filled + fpeak(zs + zshift)
Example #18
0
    def derive(self,property):
        """

        Derives seawater properties as salinity, buoyancy frequency squared etc.
        Args:
            ST:
            N2:
        """

        try:
            gsw
        except:
            logger.warning('GSW toolbox missing, derive will not work, doing nothing')
            return
        
        if(property == 'ST'):
            # Poor mans check if the variables exist
            sensor_pair0 = False
            sensor_pair1 = False
            try:
                tmp1 = self.data['cond0']
                tmp1 = self.data['temp0']
                tmp1 = self.data['p']
                sensor_pair0 = True
            except:
                sensor_pair0 = False

            try:
                tmp1 = self.data['cond1']
                tmp1 = self.data['temp1']
                tmp1 = self.data['p']
                sensor_pair1 = True
            except:
                sensor_pair1 = False                
                
                
            if(sensor_pair0):
                logger.debug('Calculating PSU0/SA11/CT11/rho11')
                SP = gsw.SP_from_C(self.data['cond0'],self.data['temp0'],self.data['p'])
                self.derived['SP00'] = SP
                SA = gsw.SA_from_SP(SP,self.data['p'],self.header['lon'],self.header['lat'])
                self.derived['SA00'] = SA
                CT = gsw.CT_from_t(SA,self.data['temp0'],self.data['p'])
                self.derived['CT00'] = CT
                rho = gsw.rho_CT_exact(SA,CT,self.data['p'])
                self.derived['rho00'] = rho
            if(sensor_pair1):
                logger.debug('Calculating PSU1/SA11/CT11/rho11') 
                SP = gsw.SP_from_C(self.data['cond1'],self.data['temp1'],self.data['p'])
                self.derived['SP11'] = SP
                SA = gsw.SA_from_SP(SP,self.data['p'],self.header['lon'],self.header['lat'])
                self.derived['SA11'] = SA
                CT = gsw.CT_from_t(SA,self.data['temp1'],self.data['p'])
                self.derived['CT11'] = CT
                rho = gsw.rho_CT_exact(SA,CT,self.data['p'])
                self.derived['rho11'] = rho                
                
                
        if(property == 'N2'):
            # Poor mans check if the variables exist
            sensor_pair0 = False
            sensor_pair1 = False
            try:
                tmp1 = self.derived['SA00']
                tmp1 = self.derived['CT00']                
                tmp1 = self.data['p']
                sensor_pair0 = True
            except:
                logger.info('Did not find absolute salinities and temperature, do first a .derive("ST")')
                sensor_pair0 = False

            try:
                tmp1 = self.derived['SA11']
                tmp1 = self.derived['CT11']                
                tmp1 = self.data['p']
                sensor_pair1 = True
            except:
                logger.info('Did not find absolute salinities and temperature, do first a .derive("ST")')
                sensor_pair1 = False

            if(sensor_pair0):
                logger.debug('Calculating Nsquared00')
                [N2,p_mid] = gsw.Nsquared(self.derived['SA00'],self.derived['CT00'],self.data['p'])
                self.derived['Nsquared00'] = interp(self.data['p'],p_mid,N2)
            if(sensor_pair1):
                logger.debug('Calculating Nsquared11')                
                [N2,p_mid] = gsw.Nsquared(self.derived['SA11'],self.derived['CT11'],self.data['p'])
                self.derived['Nsquared11'] = interp(self.data['p'],p_mid,N2)
                
                
        if(property == 'alphabeta'):
            # Poor mans check if the variables exist
            sensor_pair0 = False
            sensor_pair1 = False
            try:
                tmp1 = self.derived['SA00']
                tmp1 = self.derived['CT00']                
                tmp1 = self.data['p']
                sensor_pair0 = True
            except:
                logger.info('Did not find absolute salinities and temperature, do first a .derive("ST")')
                sensor_pair0 = False

            try:
                tmp1 = self.derived['SA11']
                tmp1 = self.derived['CT11']                
                tmp1 = self.data['p']
                sensor_pair1 = True
            except:
                logger.info('Did not find absolute salinities and temperature, do first a .derive("ST")')
                sensor_pair1 = False
                

            if(sensor_pair0):
                logger.debug('Calculating Nsquared00')
                alpha = gsw.alpha(self.derived['SA00'],self.derived['CT00'],self.data['p'])
                beta = gsw.beta(self.derived['SA00'],self.derived['CT00'],self.data['p'])
                self.derived['alpha00'] = alpha
                self.derived['beta00'] = beta
            if(sensor_pair1):
                logger.debug('Calculating Nsquared11')                
                alpha = gsw.alpha(self.derived['SA11'],self.derived['CT11'],self.data['p'])
                beta = gsw.beta(self.derived['SA11'],self.derived['CT11'],self.data['p'])
                self.derived['alpha11'] = alpha
                self.derived['beta11'] = beta
Example #19
0
print('Fill NaNs in matrices  - SeaExplorer')
for var in list(dsSX.var()):
    if var != 'profile_index':
        exec('sx_' + var + '[ppitch<0] = sx_' + var +
             '[ppitch<0].fillna(method="ffill", limit=5, axis=1)')
        exec('sx_' + var + '[ppitch>0] = sx_' + var +
             '[ppitch>0].fillna(method="bfill", limit=5, axis=1)')
print('  Done!')

# TEOS-10 conversion SeaExplorer
P = sx_pressure.values
lon0, lat0 = dsSX['longitude'].values.mean(), dsSX['latitude'].values.mean()
SA = gsw.SA_from_SP(sx_salinity.values, P, lon0, lat0)
CT = gsw.CT_from_t(SA, sx_temperature.values, P)
sigma0 = gsw.sigma0(SA, CT)
N2, p_mid = gsw.Nsquared(SA, CT, P, lat=lat0)

# Oxygen conversion
Ofreq = sx_oxygen_frequency.values
Soc = float(dpl['calibration.SBE43F.soc'])
Foffset = float(dpl['calibration.SBE43F.foffset'])
A = float(dpl['calibration.SBE43F.a'])
B = float(dpl['calibration.SBE43F.b'])
C = float(dpl['calibration.SBE43F.c'])
E = float(dpl['calibration.SBE43F.e'])

K = CT + 273.15  # Temp in Kelvin
O2sol = gsw.O2sol(SA, CT, P, lon0, lat0)
#umol/Kg
O2 = Soc * (Ofreq + Foffset) * (1.0 + A * CT + B * CT**2 +
                                C * CT**3) * O2sol * np.exp(E * P / K)
                                              right=np.nan)
    test_eps_grid[i] = eps[i].flatten()
    eps_grid[i] = np.interp(interp_coarse_pressure,
                            eps_pressure[i].flatten(),
                            eps[i].flatten(),
                            left=np.nan,
                            right=np.nan)

density_grid = gsw.rho(salinity_grid, consv_temperature_grid, pressure_grid)
#density_grid_check = (1 - alpha_grid * (consv_temperature_grid) + beta_grid * (salinity_grid))*rho_0
#difference = density_grid-density_grid_check

#calculate N^2 with the gsw toolbox
BV_freq_squared_grid_gsw, midpoint_pressure_grid = gsw.Nsquared(
    salinity_grid,
    consv_temperature_grid,
    pressure_grid,
    lat=np.mean(lat),
    axis=1)

test_N_gsw, test_eps_pressure_grid = gsw.Nsquared(test_salinity_grid,
                                                  test_consv_temperature_grid,
                                                  test_pressure_grid,
                                                  lat=np.mean(lat),
                                                  axis=1)
eps_mid_point_pressure = np.mean(test_eps_pressure_grid, axis=0)

print("\n", eps_pressure[0].flatten(), np.shape(eps_pressure[0].flatten()))
print("\n", test_pressure, np.shape(test_pressure))
print("\n", eps_mid_point_pressure, np.shape(eps_mid_point_pressure))
assert (np.all(eps_mid_point_pressure == eps_pressure[0].flatten()))
Example #21
0
lat = 55
lon = 16
Pbin = np.arange(0.5, 85, 1)
MSS_S1_1_dict = loadmat('./data/MSS_DATA/S1_1.mat',
                        squeeze_me=True,
                        struct_as_record=False)
Zmss = MSS_S1_1_dict['CTD'][2].P
Tmss = MSS_S1_1_dict['CTD'][2].T
Smss = MSS_S1_1_dict['CTD'][2].S
digitized = np.digitize(Zmss, Pbin)  #<- this is awesome!
TTbin = np.array([Tmss[digitized == i].mean() for i in range(0, len(Pbin))])
SSbin = np.array([Smss[digitized == i].mean() for i in range(0, len(Pbin))])
SA_MSS_01 = gsw.SA_from_SP_Baltic(SSbin, lon, lat)
CT_MSS_01 = gsw.CT_from_t(SA_MSS_01, TTbin, Pbin)
SIG0_MSS_01 = gsw.sigma0(SA_MSS_01, CT_MSS_01)
N2_MSS_01 = gsw.Nsquared(SA_MSS_01, CT_MSS_01, Pbin, lat)
import SW_extras as swe
N2_01 = N2_MSS_01[0]
zN2_01 = N2_MSS_01[1]
N2_period_01 = 60.0 / swe.cph(N2_01)

MSS_S1_2_dict = loadmat('./data/MSS_DATA/S1_2.mat',
                        squeeze_me=True,
                        struct_as_record=False)
Zmss = MSS_S1_2_dict['CTD'][2].P
Tmss = MSS_S1_2_dict['CTD'][2].T
Smss = MSS_S1_2_dict['CTD'][2].S
digitized = np.digitize(Zmss, Pbin)  #<- this is awesome!
TTbin = np.array([Tmss[digitized == i].mean() for i in range(0, len(Pbin))])
SSbin = np.array([Smss[digitized == i].mean() for i in range(0, len(Pbin))])
SA_MSS_02 = gsw.SA_from_SP_Baltic(SSbin, lon, lat)
Example #22
0
def compute_thermodynamics(prof):
	"""
	Perform a pre-processing on the glider data

	"""
	# 1) Make a nice time record for the profile
	max_depth = prof['P'].max(dim='NT')
	bottom = prof['P'].argmax(dim='NT')
	record = prof['time_since_start_of_dive']
	deltat_bottom = record.data[bottom].astype('f8')
	deltat_total = record.data[-1].astype('f8')
	alpha = deltat_bottom / deltat_total
	t_start = prof.GPS_time[0].data
	t_stop = prof.GPS_time[1].data
	t_bottom = t_start + pd.to_timedelta(
		alpha * (t_stop - t_start).astype('f8'))
	time_profile = t_bottom + pd.to_timedelta(
		prof['time_since_start_of_dive'] - deltat_bottom, unit='s')
	prof = prof.rename({'NT': 'time'}).assign_coords(
		time=('time', time_profile))

	# 2) Get the coordinates of the profile
	lat_start = prof.GPS_latitude[0].data
	lat_stop = prof.GPS_latitude[1].data
	lat_bottom = lat_start + alpha * (lat_stop - lat_start)
	lon_start = prof.GPS_longitude[0].data
	lon_stop = prof.GPS_longitude[1].data
	lon_bottom = lon_start + alpha * (lon_stop - lon_start)
	distance_start_to_bottom = 1e-3 * gsw.distance([lon_start, lon_bottom],
												  [lat_start, lat_bottom],
												  p=[0, max_depth]).squeeze()
	distance_bottom_to_stop = 1e-3 * gsw.distance([lon_bottom, lon_stop],
												  [lat_bottom, lat_stop],
												  p=[max_depth, 0]).squeeze()
	# 3) Clean up unvalid data
	niceT = prof['T']
	niceS = prof['S']
	# Do not forget to correct the offset due to surface pressure
	niceP = (prof['P'] - prof['Psurf'])
	niceDive = prof['dive']

	# 4) Compute thermodynamic quantities from GSW toolbox
	# - Absolute Salinity
	SA = gsw.SA_from_SP(niceS, niceP, lat_start, lon_start)
	# - Conservative Temperature
	CT = gsw.CT_from_t(SA, niceT, niceP)
	# - In situ density
	rho = gsw.rho(SA, CT, niceP)
	# - Potential density referenced to surface pressure
	sigma0 = gsw.sigma0(SA, CT)
	# - Buoyancy
	b = 9.81 * (1 - rho / 1025)
	N2 = xr.DataArray(gsw.Nsquared(SA, CT, niceP)[0], name='Buoyancy frequency',
					  dims='time',
					  coords = {'time': ('time',
										 prof['time'].isel(time=slice(1, None)))
								}
					  )
	# - Depth
	depth = - gsw.z_from_p(niceP, lat_start)

	# 5) Split the dive into one descending and one ascending path
	bottom = niceP.argmax(dim='time')
	ones = xr.ones_like(niceP)
	newdive = xr.concat([2 * niceDive[:bottom] - 1, 2 * niceDive[bottom:]],
						dim='time')
	lat = xr.concat([0.5 * (lat_start + lat_bottom) * ones[:bottom],
					 0.5 * (lat_stop + lat_bottom) * ones[bottom:]], dim='time')
	lon = xr.concat([0.5 * (lon_start + lon_bottom) * ones[:bottom],
					 0.5 * (lon_stop + lon_bottom) * ones[bottom:]], dim='time')
	Pmax = xr.concat([max_depth * ones[:bottom],
					  max_depth * ones[bottom:]], dim='time')

	distance = xr.concat([distance_start_to_bottom * ones[:bottom],
						  distance_bottom_to_stop * ones[bottom:]], dim='time')
	distance.name = 'distance between profiles in km'

	return xr.Dataset({'Temperature': niceT,
					   'Salinity': niceS,
					   'Pressure': niceP,
					   'Rho': ('time', rho),
					   'CT': ('time', CT),
					   'SA': ('time', SA),
					   'Sigma0': ('time', sigma0),
					   'b': ('time', b),
					   'Pmax': ('time', Pmax),
					   'N2': N2},
					  coords={'profile': ('time', newdive.data),
							  'depth': ('time', depth),
							  'lat': ('time', lat), 'lon': ('time', lon),
							  'distance': distance})
Example #23
0
        for t, year in enumerate(index_unique):  #time loop
            T = df_Ttmp[df_Ttmp.index.year == year].values.squeeze()
            S = df_Stmp[df_Stmp.index.year == year].values.squeeze()

            if T.size < 1:  # no data for this year
                pass
            else:
                Z = df_Ttmp.columns.values
                T[(~np.isnan(T)) & (~np.isnan(S))]
                TT = T[(~np.isnan(T)) & (~np.isnan(S))]
                SS = S[(~np.isnan(T)) & (~np.isnan(S))]
                ZZ = Z[(~np.isnan(T)) & (~np.isnan(S))]

                SA = gsw.SA_from_SP(SS, ZZ, xx, yy)
                CT = gsw.CT_from_t(SA, TT, ZZ)
                N2, pmid = gsw.Nsquared(SA, CT, ZZ, yy)

                yearVec.append(year)
                TVec.append(np.nanmean(TT))
                SVec.append(np.nanmean(SS))
                NVec.append(np.sqrt(np.nanmean(N2)))

            # compute trends if serie long enough
            x = np.array(yearVec)
            y = np.array(TVec)
            idx = np.where(~np.isnan(y))
            if np.size(idx) > 5:
                m, b, r_value, p_value, std_err = stats.linregress(
                    x[idx], y[idx])
                Tmap[j, i] = m
            y = np.array(SVec)
Example #24
0
    def post_process(self, verbose=True):

        print("\nPost processing")
        print("---------------\n")

        # Very basic
        self.ascent = self.hpid % 2 == 0
        self.ascent_ctd = self.ascent * np.ones_like(self.UTC, dtype=int)
        self.ascent_ef = self.ascent * np.ones_like(self.UTCef, dtype=int)

        # Estimate number of observations.
        self.nobs_ctd = np.sum(~np.isnan(self.UTC), axis=0)
        self.nobs_ef = np.sum(~np.isnan(self.UTCef), axis=0)

        # Figure out some useful times.
        self.UTC_start = self.UTC[0, :]
        self.UTC_end = np.nanmax(self.UTC, axis=0)

        if verbose:
            print("Creating time variable dUTC with units of seconds.")
        self.dUTC = (self.UTC - self.UTC_start) * 86400
        self.dUTCef = (self.UTCef - self.UTC_start) * 86400

        if verbose:
            print("Interpolated GPS positions to starts and ends of profiles.")
        # GPS interpolation to the start and end time of each half profile.
        idxs = ~np.isnan(self.lon_gps) & ~np.isnan(self.lat_gps)
        self.lon_start = np.interp(self.UTC_start, self.utc_gps[idxs],
                                   self.lon_gps[idxs])
        self.lat_start = np.interp(self.UTC_start, self.utc_gps[idxs],
                                   self.lat_gps[idxs])
        self.lon_end = np.interp(self.UTC_end, self.utc_gps[idxs],
                                 self.lon_gps[idxs])
        self.lat_end = np.interp(self.UTC_end, self.utc_gps[idxs],
                                 self.lat_gps[idxs])

        if verbose:
            print("Calculating heights.")
        # Depth.
        self.z = gsw.z_from_p(self.P, self.lat_start)
        #        self.z_ca = gsw.z_from_p(self.P_ca, self.lat_start)
        self.zef = gsw.z_from_p(self.Pef, self.lat_start)

        if verbose:
            print("Calculating distance along trajectory.")
        # Distance along track from first half profile.
        self.__ddist = utils.lldist(self.lon_start, self.lat_start)
        self.dist = np.hstack((0., np.cumsum(self.__ddist)))

        if verbose:
            print("Interpolating distance to measurements.")
        # Distances, velocities and speeds of each half profile.
        self.profile_ddist = np.zeros_like(self.lon_start)
        self.profile_dt = np.zeros_like(self.lon_start)
        self.profile_bearing = np.zeros_like(self.lon_start)
        lons = np.zeros((len(self.lon_start), 2))
        lats = lons.copy()
        times = lons.copy()

        lons[:, 0], lons[:, 1] = self.lon_start, self.lon_end
        lats[:, 0], lats[:, 1] = self.lat_start, self.lat_end
        times[:, 0], times[:, 1] = self.UTC_start, self.UTC_end

        self.dist_ctd = self.UTC.copy()
        nans = np.isnan(self.dist_ctd)
        for i, (lon, lat, time) in enumerate(zip(lons, lats, times)):
            self.profile_ddist[i] = utils.lldist(lon, lat)
            # Convert time from days to seconds.
            self.profile_dt[i] = np.diff(time) * 86400.

            d = np.array([self.dist[i], self.dist[i] + self.profile_ddist[i]])
            idxs = ~nans[:, i]
            self.dist_ctd[idxs, i] = np.interp(self.UTC[idxs, i], time, d)

        self.dist_ef = self.__regrid('ctd', 'ef', self.dist_ctd)

        if verbose:
            print("Estimating bearings.")
        # Pythagorian approximation (?) of bearing.
        self.profile_bearing = np.arctan2(self.lon_end - self.lon_start,
                                          self.lat_end - self.lat_start)

        if verbose:
            print("Calculating sub-surface velocity.")
        # Convert to m s-1 calculate meridional and zonal velocities.
        self.sub_surf_speed = self.profile_ddist * 1000. / self.profile_dt
        self.sub_surf_u = self.sub_surf_speed * np.sin(self.profile_bearing)
        self.sub_surf_v = self.sub_surf_speed * np.cos(self.profile_bearing)

        if verbose:
            print("Interpolating missing velocity values.")
        # Fill missing U, V values using linear interpolation otherwise we
        # run into difficulties using cumtrapz next.
        self.U = self.__fill_missing(self.U)
        self.V = self.__fill_missing(self.V)

        # Absolute velocity
        self.calculate_absolute_velocity(verbose=verbose)

        if verbose:
            print("Calculating thermodynamic variables.")
        # Derive some important thermodynamics variables.

        # Absolute salinity.
        self.SA = gsw.SA_from_SP(self.S, self.P, self.lon_start,
                                 self.lat_start)
        # Conservative temperature.
        self.CT = gsw.CT_from_t(self.SA, self.T, self.P)

        # Potential temperature with respect to 0 dbar.
        self.PT = gsw.pt_from_CT(self.SA, self.CT)

        # In-situ density.
        self.rho = gsw.rho(self.SA, self.CT, self.P)

        # Potential density with respect to 1000 dbar.
        self.rho_1 = gsw.pot_rho_t_exact(self.SA, self.T, self.P, p_ref=1000.)

        # Buoyancy frequency regridded onto ctd grid.
        N2_ca, __ = gsw.Nsquared(self.SA, self.CT, self.P, self.lat_start)
        self.N2 = self.__regrid('ctd_ca', 'ctd', N2_ca)

        if verbose:
            print("Calculating float vertical velocity.")
        # Vertical velocity regridded onto ctd grid.
        dt = 86400. * np.diff(self.UTC, axis=0)  # [s]
        Wz_ca = np.diff(self.z, axis=0) / dt
        self.Wz = self.__regrid('ctd_ca', 'ctd', Wz_ca)

        if verbose:
            print("Renaming Wp to Wpef.")
        # Vertical water velocity.
        self.Wpef = self.Wp.copy()
        del self.Wp

        if verbose:
            print("Calculating shear.")
        # Shear calculations.
        dUdz_ca = np.diff(self.U, axis=0) / np.diff(self.zef, axis=0)
        dVdz_ca = np.diff(self.V, axis=0) / np.diff(self.zef, axis=0)
        self.dUdz = self.__regrid('ef_ca', 'ef', dUdz_ca)
        self.dVdz = self.__regrid('ef_ca', 'ef', dVdz_ca)

        if verbose:
            print("Calculating Richardson number.")
        N2ef = self.__regrid('ctd', 'ef', self.N2)
        self.Ri = N2ef / (self.dUdz**2 + self.dVdz**2)

        if verbose:
            print("Regridding piston position to ctd.\n")
        # Regrid piston position.
        self.ppos = self.__regrid('ctd_ca', 'ctd', self.ppos_ca)

        self.update_profiles()
Example #25
0
    print("- Renaming variables and calculating new ones")
    TY["T"] = TY.pop("t1")
    TY["P"] = TY.pop("p")
    TY["S"] = TY.pop("s1")
    TY["spd"] = np.sqrt(TY["u"]**2 + TY["v"]**2)
    TY["z"] = -np.tile(TY["z"][:, np.newaxis].astype(float), (1, Np))
    TY["depth"] = -TY["z"]
    TY["SA"] = gsw.SA_from_SP(TY["S"], TY["P"], TY["lon"], TY["lat"])
    TY["CT"] = gsw.CT_from_t(TY["SA"], TY["T"], TY["P"])
    TY["sig4"] = gsw.pot_rho_t_exact(TY["SA"], TY["T"], TY["P"], 4000)
    TY["g"] = gsw.grav(TY["lat"], TY["P"])
    TY["b"] = -TY["g"] * (TY["sig4"] - sig4b) / sig4b
    TY["sig4m"] = np.nanmean(TY["sig4"])
    TY["sig4_sorted"] = utils.nansort(TY["sig4"], axis=0)
    TY["b_sorted"] = -TY["g"] * (TY["sig4_sorted"] - sig4b) / sig4b
    TY["N2"], TY["P_mid"] = gsw.Nsquared(TY["SA"], TY["CT"], TY["P"],
                                         np.nanmean(TY["lat"], axis=0))
    TY["z_mid"] = gsw.z_from_p(TY["P_mid"], TY["mlat"])
    ddist = utils.lldist(TY["mlon"], TY["mlat"])
    TY["dist"] = np.hstack((0, np.cumsum(ddist)))
    TY["dist_r"] = -(TY["dist"] - TY["dist"].max())

    print("- Estimating distances")
    lon = TY["lon"].flatten()
    lat = TY["lat"].flatten()
    time = TY["datenum"].flatten()
    use = np.isfinite(lon) & np.isfinite(lat) & np.isfinite(time)
    idxs = np.argsort(time[use])
    time_ = time[use][idxs]
    lon_ = lon[use][idxs]
    lat_ = lat[use][idxs]
    d = utils.lldist(lon_[::dc], lat_[::dc])
Example #26
0
def load_clean_interpolate_and_shift_data(datafile_path, shift_value):
    """
    loads a a .mat file of mss measurements
    a few files are cleaned through a hardcoded routine (emb217/TR1-8.mat, emb169/TS118, emb169/TRR109)
    
    
    
    datafile_path: absolute path of the mss measurements saved as a .mat file


    return values:
        number_of_profiles              number of profiles/casts in the transect
        lat                             latitude in degrees (as a float) of the casts
        lon                             longitude in degrees (as a float) of the casts
        distance                        distance in km from the starting point of the transect
        
        interp_pressure                 equidistant pressure array between the highest and the lowest measured pressure value
        pressure_grid
        oxygen_grid                     
        oxygen_sat_grid                 oxygen saturation in percent as a grid (number_of_profiles x len(interp_pressure))
        salinity_grid                   salinity in g/kg as a grid (number_of_profiles x len(interp_pressure)) 
        consv_temperature_grid          conservative temperature in degrees Celsius as a grid (number_of_profiles x len(interp_pressure))
        density_grid                    density in kg/m^3 as a grid (number_of_profiles x len(interp_pressure))
        
        eps_pressure                    1D array of pressure values to the dissipation rate values (the pressure distance between points is bigger than in interp_pressure) 
        eps_pressure_grid               
        eps_grid                        measured dissipation rate values (number_of_profiles x len(eps_pressure))
        eps_salinity_grid               salinity in g/kg as a grid (number_of_profiles x len(eps_pressure)) 
        eps_consv_temperature_grid      conservative temperature as a grid (number_of_profiles x len(eps_pressure))
        eps_oxygen_grid                 
        eps_oxygen_sat_grid             oxygen saturation as a grid (number_of_profiles x len(eps_pressure))
        eps_N_squared_grid              N^2, the Brunt-Vaisala frequency in 1/s^2 as a grid (number_of_profiles x len(eps_pressure))
        eps_density_grid                density in kg/m^3 as a grid (number_of_profiles x len(eps_pressure))
        
        0                               error code, returned if distance is not monotonically increasing (ergo a loop in the data)

    """
    import scipy.io as sio
    import geopy.distance as geo
    import numpy as np
    import gsw

    splitted_path = datafile_path.split("/")
    cruisename = splitted_path[4][0:6]
    DATAFILENAME = splitted_path[-1]

    transect_name = DATAFILENAME[:-4]

    print(cruisename + "_" + transect_name)
    #print("Filename:",sio.whosmat(FILENAME))

    data = sio.loadmat(datafile_path)

    STA_substructure = data["STA"]
    DATA_substructure = data["DATA"]
    MIX_substructure = data["MIX"]
    CTD_substructure = data["CTD"]

    #print(STA_substructure.dtype)
    #print(DATA_substructure.dtype)
    #print(CTD_substructure.dtype)
    #print(MIX_substructure.dtype)

    lat = STA_substructure["LAT"][0]
    lon = STA_substructure["LON"][0]

    pressure = CTD_substructure["P"][0]
    absolute_salinity = CTD_substructure["SA"][0]  #is this unit sufficient
    consv_temperature = CTD_substructure["CT"][
        0]  #TODO better use conservative temperature?
    alpha = CTD_substructure["ALPHA"][0]
    beta = CTD_substructure["BETA"][0]

    if cruisename == "emb217":
        oxygen_sat = CTD_substructure["O2"][0]

    elif cruisename == "emb177":
        try:
            oxygen_data = sio.loadmat(
                "/home/ole/windows/all_data/emb177/deployments/ship/mss/mss38/TODL/TODL_merged_oxy/"
                + transect_name + "_TODL_merged_oxy.mat")
        except OSError:
            print("##########################################")
            print(cruisename, transect_name, "is skipped!")
            print("No oxygen data for this file")
            print("##########################################")
            return 0

        #the following code block is written by Peter Holtermann and Copy pasted here

        emb177_oxygen = []
        emb177_oxygen_pressure = []
        for icast in range(len(lon)):
            oxy_p_temp = oxygen_data['TODL_MSS']['P'][0, :][icast][0, :]
            #mT  = oxygen_data['TODL_MSS']['mT'][0,:][icast][0,:]
            #C   = oxygen_data['TODL_MSS']['C'][0,:][icast][0,:]
            oxy = oxygen_data['TODL_MSS']['oxy'][0, :][icast][:, 4]
            emb177_oxygen.append(oxy)
            emb177_oxygen_pressure.append(oxy_p_temp)

    elif cruisename == "emb169":
        try:
            oxygen_data = sio.loadmat(
                "/home/ole/windows/all_data/emb169/deployments/ship/mss/TODL/merged/"
                + transect_name + "_TODL_merged_oxy.mat")
        except OSError:
            print("##########################################")
            print(cruisename, transect_name, "is skipped!")
            print("No oxygen data for this file")
            print("##########################################")
            return 0

        #the following code block is written by Peter Holtermann and Copy pasted here

        emb169_oxygen = []
        emb169_oxygen_pressure = []
        for icast in range(len(lon)):
            oxy_p_temp = oxygen_data['TODL_MSS']['P'][0, :][icast][0, :]
            #mT  = oxygen_data['TODL_MSS']['mT'][0,:][icast][0,:]
            #C   = oxygen_data['TODL_MSS']['C'][0,:][icast][0,:]
            oxy = oxygen_data['TODL_MSS']['oxy'][0, :][icast][:, 4]
            emb169_oxygen.append(oxy)
            emb169_oxygen_pressure.append(oxy_p_temp)
    else:
        raise AssertionError

    eps = MIX_substructure["eps"][0]
    eps_pressure = MIX_substructure["P"][0]

    number_of_profiles = np.shape(pressure)[-1]

    latitude = []
    longitude = []

    #calculates the distance in km of the position from every profile to the position of the starting profile.
    distance = np.zeros(number_of_profiles)
    origin = (float(lat[0][0][0]), float(lon[0][0][0])
              )  #lots of brackets to get a number, not an array (workaround)
    for i in range(number_of_profiles):
        current_point = (float(lat[i][0][0]), float(lon[i][0][0]))
        latitude.append(float(lat[i][0][0]))
        longitude.append(float(lon[i][0][0]))
        distance[i] = geo.geodesic(
            origin,
            current_point).km  #Distance in km, change to nautical miles?

    lat = np.asarray(latitude)
    lon = np.asarray(longitude)

    #Data Cleaning
    #-----------------------------------------------------------------------------------------------------------------

    #remove data from a file, with overlapping positional points
    if cruisename == "emb217" and transect_name == "TR1-8":
        lat = np.delete(lat, np.s_[33:47])
        lon = np.delete(lon, np.s_[33:47])
        distance = np.delete(distance, np.s_[33:47])

        pressure = np.delete(pressure, np.s_[33:47], axis=0)
        oxygen_sat = np.delete(oxygen_sat, np.s_[33:47], axis=0)
        absolute_salinity = np.delete(absolute_salinity, np.s_[33:47], axis=0)
        consv_temperature = np.delete(consv_temperature, np.s_[33:47], axis=0)
        alpha = np.delete(alpha, np.s_[33:47], axis=0)
        beta = np.delete(beta, np.s_[33:47], axis=0)

        eps = np.delete(eps, np.s_[33:47], axis=0)
        eps_pressure = np.delete(eps_pressure, np.s_[33:47], axis=0)

        number_of_profiles = np.shape(pressure)[-1]

    if cruisename == "emb169" and DATAFILENAME[:-4] == "TS118":
        lat = lat[:21]
        lon = lon[:21]
        distance = distance[:21]

        pressure = pressure[:21]
        oxygen_sat = oxygen_sat[:21]
        absolute_salinity = absolute_salinity[:21]
        consv_temperature = consv_temperature[:21]
        alpha = alpha[:21]
        beta = beta[:21]

        eps = eps[:21]
        eps_pressure = eps_pressure[:21]
        number_of_profiles = np.shape(pressure)[-1]

    #removes the last data point, that dont seem to belong to the transect
    if cruisename == "emb169" and DATAFILENAME[:-4] == "TRR109":
        lat = lat[:-1]
        lon = lon[:-1]
        distance = distance[:-1]

        pressure = pressure[:-1]
        oxygen_sat = oxygen_sat[:-1]
        absolute_salinity = absolute_salinity[:-1]
        consv_temperature = consv_temperature[:-1]
        alpha = alpha[:-1]
        beta = beta[:-1]

        eps = eps[:-1]
        eps_pressure = eps_pressure[:-1]
        number_of_profiles = np.shape(pressure)[-1]
    #-----------------------------------------------------------------------------------------------------------------

    #test if distance is monotonically increasing
    try:
        assert (np.all(np.diff(distance) > 0))
    except AssertionError:
        print("##########################################")
        print(cruisename, DATAFILENAME[:-4], "is skipped!")
        print(
            "Distance is not monotonically increasing. Mabye due to a loop in the transect?"
        )
        print("##########################################")
        return 0
        #continue #jump to the next datafile

    #TODO point density?

    #initial values
    min_pressure = 10
    max_pressure = 60
    max_size = 1000
    min_size = 3000

    #select the min and max values for the equidistant pressure array (later used for the grid)
    for i in range(number_of_profiles):
        if np.nanmin(pressure[i]) < min_pressure:
            min_pressure = np.nanmin(pressure[i])
        if np.nanmax(pressure[i]) > max_pressure:
            max_pressure = np.nanmax(pressure[i])
        if pressure[i].size > max_size:
            max_size = pressure[i].size
        if pressure[i].size < min_size:
            min_size = pressure[i].size

    #print("High resolution",min_pressure,max_pressure,min_size,max_size)

    #check if that worked correctly
    assert (max_size >= min_size)

    #creates a pressure axis between the maximum and minimum pressure
    interp_pressure = np.linspace(min_pressure, max_pressure, min_size)

    #creates pressure grid, where every column is equal to interp_pressure
    pressure_grid = np.reshape(interp_pressure, (1, -1)) * np.ones(
        (np.shape(pressure)[-1], min_size))

    #create grids that changes in distance on x and in depth on y-axis

    salinity_grid = np.zeros((np.shape(pressure)[-1], min_size))
    consv_temperature_grid = np.copy(salinity_grid)
    alpha_grid = np.copy(salinity_grid)
    beta_grid = np.copy(salinity_grid)

    if cruisename == "emb217":
        oxygen_sat_grid = np.copy(salinity_grid)
    elif cruisename == "emb177" or cruisename == "emb169":
        oxygen_grid = np.copy(salinity_grid)

    #check if the pressure points for every eps profile are the same
    for i in range(number_of_profiles):
        assert np.all(eps_pressure[i].flatten() == eps_pressure[0].flatten())
    #if yes the pressure can be coverted to a 1D array instead of a 2D array
    eps_pressure = eps_pressure[0].flatten()

    #print(eps[i].flatten().size,eps_pressure.size, np.arange(1,160.5,0.5).size, np.arange(1,160.5,0.5).size - eps_pressure.size)
    #print(np.shape(eps),np.shape(eps[0]))

    desired_pressure_array = np.arange(
        1, 160.5, 0.5
    )  #stems from the orginal matlab script that process the raw MSS data
    last_element = eps_pressure[-1]
    old_size = eps_pressure.size
    if last_element < 160:
        for index, element in enumerate(eps):
            eps[index] = np.pad(
                eps[index],
                ((0, desired_pressure_array.size - eps_pressure.size), (0, 0)),
                'constant',
                constant_values=np.nan)
        eps_pressure = np.append(eps_pressure,
                                 np.arange(last_element + 0.5, 160.5, 0.5))
    assert (eps[0].flatten().size == eps_pressure.size)

    #averaged of approx 5 depth bins (???)
    eps_grid = np.zeros((number_of_profiles, eps_pressure.size))

    #needed for the interpolation of S and T to the same grid as the eps
    eps_salinity_grid = np.ones((np.shape(eps_grid)))
    eps_consv_temperature_grid = np.ones(np.shape(eps_grid))

    if cruisename == "emb217":
        eps_oxygen_sat_grid = np.copy(eps_salinity_grid)
    elif cruisename == "emb177" or cruisename == "emb169":
        eps_oxygen_grid = np.copy(eps_salinity_grid)

    #vector times matrix multiplication to get a 2D array, where every column is equal to eps_pressure
    eps_pressure_grid = np.reshape(eps_pressure,
                                   (1, -1)) * np.ones(np.shape(eps_grid))

    #create a pressure axis where every point is shifted by half the distance to the next one
    shifted_pressure = eps_pressure + np.mean(np.diff(eps_pressure)) / 2

    #prepend a point at the beginning to be a point longer than the pressure axis we want from the Nsquared function
    shifted_pressure = np.append(
        eps_pressure[0] - np.mean(np.diff(eps_pressure)) / 2, shifted_pressure)

    #from that create a grid, where we have just n-times the pressure axis with n the number of profiles
    shifted_pressure_grid = np.reshape(shifted_pressure, (1, -1)) * np.ones(
        (number_of_profiles, shifted_pressure.size))
    shifted_salinity_grid = np.ones((np.shape(shifted_pressure_grid)))
    shifted_consv_temperature_grid = np.ones((np.shape(shifted_pressure_grid)))

    #Grid interpolation (loops over all profiles)
    for i in range(number_of_profiles):

        #interpolation to a common fine grid
        salinity_grid[i] = np.interp(interp_pressure,
                                     pressure[i].flatten(),
                                     absolute_salinity[i].flatten(),
                                     left=np.nan,
                                     right=np.nan)
        consv_temperature_grid[i] = np.interp(interp_pressure,
                                              pressure[i].flatten(),
                                              consv_temperature[i].flatten(),
                                              left=np.nan,
                                              right=np.nan)
        alpha_grid[i] = np.interp(interp_pressure,
                                  pressure[i].flatten(),
                                  alpha[i].flatten(),
                                  left=np.nan,
                                  right=np.nan)
        beta_grid[i] = np.interp(interp_pressure,
                                 pressure[i].flatten(),
                                 beta[i].flatten(),
                                 left=np.nan,
                                 right=np.nan)

        #interpolation to a shifted grid for the Nsquared function
        shifted_salinity_grid[i] = np.interp(shifted_pressure,
                                             pressure[i].flatten(),
                                             absolute_salinity[i].flatten(),
                                             left=np.nan,
                                             right=np.nan)
        shifted_consv_temperature_grid[i] = np.interp(
            shifted_pressure,
            pressure[i].flatten(),
            consv_temperature[i].flatten(),
            left=np.nan,
            right=np.nan)

        #just changes the format of eps slightly
        assert (eps[i].flatten().size == eps_pressure.size)
        eps_grid[i] = eps[i].flatten()

        #interpolate S and T to the same grid as eps
        eps_salinity_grid[i] = np.interp(eps_pressure,
                                         pressure[i].flatten(),
                                         absolute_salinity[i].flatten(),
                                         left=np.nan,
                                         right=np.nan)
        eps_consv_temperature_grid[i] = np.interp(
            eps_pressure,
            pressure[i].flatten(),
            consv_temperature[i].flatten(),
            left=np.nan,
            right=np.nan)

        #interpolation of the oxygen depends on which source it is
        if cruisename == "emb217":
            oxygen_sat_grid[i] = np.interp(interp_pressure,
                                           pressure[i].flatten() + shift_value,
                                           oxygen_sat[i].flatten(),
                                           left=np.nan,
                                           right=np.nan)
            eps_oxygen_sat_grid[i] = np.interp(eps_pressure,
                                               pressure[i].flatten() +
                                               shift_value,
                                               oxygen_sat[i].flatten(),
                                               left=np.nan,
                                               right=np.nan)
        elif cruisename == "emb177":
            oxygen_grid[i] = np.interp(interp_pressure,
                                       emb177_oxygen_pressure[i] + shift_value,
                                       emb177_oxygen[i],
                                       left=np.nan,
                                       right=np.nan)
            eps_oxygen_grid[i] = np.interp(eps_pressure,
                                           emb177_oxygen_pressure[i] +
                                           shift_value,
                                           emb177_oxygen[i].flatten(),
                                           left=np.nan,
                                           right=np.nan)
        elif cruisename == "emb169":
            oxygen_grid[i] = np.interp(interp_pressure,
                                       emb169_oxygen_pressure[i] + shift_value,
                                       emb169_oxygen[i],
                                       left=np.nan,
                                       right=np.nan)
            eps_oxygen_grid[i] = np.interp(eps_pressure,
                                           emb169_oxygen_pressure[i] +
                                           shift_value,
                                           emb169_oxygen[i].flatten(),
                                           left=np.nan,
                                           right=np.nan)

    if cruisename == "emb217":
        assert (np.shape(oxygen_sat_grid) == np.shape(salinity_grid))
        assert (np.shape(eps_oxygen_sat_grid) == np.shape(eps_salinity_grid))

    if cruisename == "emb177" or cruisename == "emb169":
        assert (np.shape(oxygen_grid) == np.shape(salinity_grid))
        assert (np.shape(eps_oxygen_grid) == np.shape(eps_salinity_grid))

    #fine density grid
    density_grid = gsw.rho(salinity_grid, consv_temperature_grid,
                           pressure_grid)
    pot_density_grid = 1000 + gsw.density.sigma0(salinity_grid,
                                                 consv_temperature_grid)

    #density grid on the same points as the eps grid
    eps_density_grid = gsw.rho(eps_salinity_grid, eps_consv_temperature_grid,
                               eps_pressure_grid)
    eps_pot_density_grid = 1000 + gsw.density.sigma0(
        eps_salinity_grid, eps_consv_temperature_grid)

    #TODO compare with density_grid?
    #density_grid_check = (1 - alpha_grid * (consv_temperature_grid) + beta_grid * (salinity_grid))*rho_0
    #difference = density_grid-density_grid_check

    #calculate N^2 with the gsw toolbox, by using the shifted grid we should get a N^2 grid that is defined at the same points as eps_grid
    eps_N_squared_grid, crosscheck_pressure_grid = gsw.Nsquared(
        shifted_salinity_grid,
        shifted_consv_temperature_grid,
        shifted_pressure_grid,
        lat=np.mean(lat),
        axis=1)
    crosscheck_pressure = np.mean(crosscheck_pressure_grid, axis=0)

    #test if we really calculated N^2 for the same points as pressure points from the dissipation measurement
    assert (np.all(crosscheck_pressure == eps_pressure))

    #create grids that have the latitude/longitude values for every depth (size: number_of_profiles x len(interp_pressure))
    lat_grid = np.reshape(lat, (-1, 1)) * np.ones(
        (number_of_profiles, max_size))
    lon_grid = np.reshape(lon, (-1, 1)) * np.ones(
        (number_of_profiles, max_size))

    #check if lon grid was correctly created
    assert (np.all(lon_grid[:, 0] == lon))

    #create grids that have the latitude/longitude values for every depth (size: number_of_profiles x len(eps_pressure))
    eps_lat_grid = np.reshape(lat, (-1, 1)) * np.ones(
        (number_of_profiles, eps_pressure.size))
    eps_lon_grid = np.reshape(lat, (-1, 1)) * np.ones(
        (number_of_profiles, eps_pressure.size))

    if cruisename == "emb217":
        #convert oxygen saturation to oxygen concentration (functions are selfwritten but use the gsw toolbox, for more informations see the function (also in this file))
        oxygen_grid = thesis.oxygen_saturation_to_concentration(
            oxygen_sat_grid, salinity_grid, consv_temperature_grid,
            pressure_grid, lat_grid, lon_grid)
        eps_oxygen_grid = thesis.oxygen_saturation_to_concentration(
            eps_oxygen_sat_grid, eps_salinity_grid, eps_consv_temperature_grid,
            eps_pressure_grid, eps_lat_grid, eps_lon_grid)

    elif cruisename == "emb177":
        #scale the oxygen to be at 100% at the surface
        maximum_concentration_grid = gsw.O2sol(salinity_grid,
                                               consv_temperature_grid,
                                               pressure_grid, lat_grid,
                                               lon_grid)

        correction_factor = np.ones((number_of_profiles, 1))

        for profile in range(number_of_profiles):
            for i in range(100):
                if np.isnan(oxygen_grid[profile, i]) or np.isnan(
                        maximum_concentration_grid[profile, i]):
                    continue
                else:
                    correction_factor[profile] = maximum_concentration_grid[
                        profile, i] / oxygen_grid[profile, i]
                    break

        oxygen_grid = oxygen_grid * correction_factor
        eps_oxygen_grid = eps_oxygen_grid * correction_factor

        #convert oxygen concentration to oxygen saturation (functions are selfwritten but use the gsw toolbox, for more informations see the function (also in this file))
        oxygen_sat_grid = thesis.oxygen_concentration_to_saturation(
            oxygen_grid, salinity_grid, consv_temperature_grid, pressure_grid,
            lat_grid, lon_grid)
        eps_oxygen_sat_grid = thesis.oxygen_concentration_to_saturation(
            eps_oxygen_grid, eps_salinity_grid, eps_consv_temperature_grid,
            eps_pressure_grid, eps_lat_grid, eps_lon_grid)

    elif cruisename == "emb169":
        #convert oxygen concentration to oxygen saturation (functions are selfwritten but use the gsw toolbox, for more informations see the function (also in this file))
        oxygen_sat_grid = thesis.oxygen_concentration_to_saturation(
            oxygen_grid, salinity_grid, consv_temperature_grid, pressure_grid,
            lat_grid, lon_grid)
        eps_oxygen_sat_grid = thesis.oxygen_concentration_to_saturation(
            eps_oxygen_grid, eps_salinity_grid, eps_consv_temperature_grid,
            eps_pressure_grid, eps_lat_grid, eps_lon_grid)

    else:
        raise AssertionError

    return [[number_of_profiles, lat, lon, distance],
            [
                interp_pressure, oxygen_sat_grid, oxygen_grid, salinity_grid,
                consv_temperature_grid, density_grid, pot_density_grid
            ],
            [
                eps_pressure, eps_oxygen_sat_grid, eps_oxygen_grid, eps_grid,
                eps_salinity_grid, eps_consv_temperature_grid,
                eps_N_squared_grid, eps_density_grid, eps_pot_density_grid
            ]]
Example #27
0
        exec('sx_' + var + '[ppitch<0] = sx_' + var + '[ppitch<0].fillna(method="ffill", limit=10, axis=1)')
        exec('sx_' + var + '[ppitch>0] = sx_' + var + '[ppitch>0].fillna(method="bfill", limit=10, axis=1)')
        exec('sx_' + var + ' = sx_' + var + '[~pd.isna(sx_' + var + '.iloc[:,0:50].mean(axis=1))]') # correction specific for this deployment
print('  Done!')

         
# TEOS-10 conversion SeaExplorer
P = sx_pressure.values
lon0, lat0 = ds['longitude'].values.mean(), ds['latitude'].values.mean()
SA = gsw.SA_from_SP(sx_salinity.values, P, lon0, lat0)
CT = gsw.CT_from_t(SA, sx_temperature.values, P)
sigma0 = gsw.sigma0(SA, CT)
SA_sort = np.array(list(map(lambda x, y: y[x], np.argsort(sigma0, axis=1), SA)))
CT_sort = np.array(list(map(lambda x, y: y[x], np.argsort(sigma0, axis=1), CT)))
P_sort = np.array(list(map(lambda x, y: y[x], np.argsort(sigma0, axis=1), P)))
N2, p_mid = gsw.Nsquared(SA_sort, CT_sort, P_sort, lat=lat0, axis=1)

# Oxygen conversion
Ofreq = sx_oxygen_frequency.values
Soc = float(dpl['calibration.SBE43F.soc'])
Foffset = float(dpl['calibration.SBE43F.foffset'])
A = float(dpl['calibration.SBE43F.a'])
B = float(dpl['calibration.SBE43F.b'])
C = float(dpl['calibration.SBE43F.c'])
E = float(dpl['calibration.SBE43F.e'])

K = CT + 273.15 # Temp in Kelvin
O2sol = gsw.O2sol(SA, CT, P, lon0, lat0); #umol/Kg
O2 =  Soc*(Ofreq+Foffset)*(1.0+A*CT + B*CT**2 + C*CT**3)*O2sol*np.exp(E*P/K); 

# MiniFluo calib (# Assume new version)
Example #28
0
    end_index = c_time.index(a_time[-1])
    data = pd.DataFrame({'time': c_time[start_index - 1:end_index + 1]})
    data['c_pres'] = pd.Series(c_data["c_pres"][start_index - 1:end_index + 1])
    data['c_temp'] = pd.Series(c_data["c_temp"][start_index - 1:end_index + 1])
    data['c_sal'] = pd.Series(c_data["c_sal"][start_index - 1:end_index + 1])

    data_start = data.index[data["c_pres"] > 10][0]
    data_end = data.index[data["c_pres"] > 100][0]
    data = data[data_start:data_end]
    #a_data = a_data.iloc[data_start:data_end].reset_index()
    #print(a_data)

    #Generate the bouyancy frequency plot
    CT = gsw.CT_from_t(data['c_sal'], data['c_temp'], data['c_pres'])
    SA = gsw.SA_from_SP(data['c_sal'], data['c_pres'], 174, -43)
    [N2, p_mid, dp] = gsw.Nsquared(SA, CT, data['c_pres'])
    Ri_calcs = pd.DataFrame({'pres': p_mid})
    Ri_calcs['dp'] = pd.Series(dp, index=Ri_calcs.index)
    Ri_calcs['N2'] = pd.Series(N2, index=Ri_calcs.index)
    Ri_calcs['N2'] = Ri_calcs['N2'].mask(
        ((Ri_calcs['N2'] - Ri_calcs['N2'].mean()).abs() >
         2 * Ri_calcs['N2'].std()))
    Ri_calcs['N2'] = Ri_calcs['N2'].interpolate()

    #Generate the east, north and up
    [east, north,
     up] = beam2ENU([
         a_data["a_beam1"][0], a_data["a_beam2"][0], a_data["a_beam3"][0],
         a_data["a_beam4"][0]
     ], a_data['a_heading'].values, a_data['a_pitch'].values,
                    a_data['a_roll'].values, a_data['a_vel1'].values,
Example #29
0
def strain_adiabatic_leveling(depth, t, SP, lon, lat, bin_width, depth_bin,
                              window_size):
    """
    Calculate strain with a smooth :math:`N^2` profile based on the adiabatic leveling method.

    Parameters
    ----------
    depth : array-like
        CTD depth [m]
    t : array-like
        CTD in-situ temperature [ITS-90, degrees C]
    SP : array-like
        CTD practical salinity [psu]
    lon : array-like or float
        Longitude
    lat : array-like or float
        Latitude
    depth_bin : array-like
        Window centers
    window_size : float
        Window size

    Returns
    -------
    list
        List with results in a dict for each depth segment. The dict has the following entries:
        ``"segz"``
            Segment depth vector (`array-like`).
        ``"depth_bin"``
            Segment center depth (`float`).
        ``"N2"``
            Segment buoyancy frequency squared (`array-like`).
        ``"N2smooth"``
            Segment polynomial fit to buoyancy frequency squared (`array-like`).
        ``"N2mean"``
            Segment mean buoyancy frequency squared (`float`).
        ``"strain"``
            Segment strain (`array-like`).
    """
    dz = np.absolute(np.median(np.diff(depth)))
    # Prepare output list. It will hold a dictionary with data for each window.
    out = []
    # Calculate pressure
    pr = gsw.p_from_z(-1 * depth, lat)
    # Calculate smooth background N^2
    N2ref = nsq.adiabatic_leveling(
        pr,
        SP,
        t,
        lon,
        lat,
        bin_width=bin_width,
        order=2,
        return_diagnostics=False,
        cap="both",
    )
    # Calculate in-situ N^2
    SA = gsw.SA_from_SP(SP, pr, lon, lat)
    CT = gsw.CT_from_t(SA, t, pr)
    N2, Pbar = gsw.Nsquared(SA, CT, pr, lat=lat)
    depth_mid = -1 * gsw.z_from_p(Pbar, lat)
    # Interpolate smooth N^2 to in-situ N^2
    N2ref = interp1d(pr, N2ref)(Pbar)
    # Calculate strain
    strain = (N2 - N2ref) / N2ref
    isN = np.isfinite(N2) & np.isfinite(N2ref)
    # Sort into depth windows
    for iwin, zw in enumerate(depth_bin):
        # Find data points within the depth window. As we are operating on the
        # mid-points here, we extend the search for datapoints by delta z on
        # each side of the window.
        ij = (depth_mid >=
              (zw - window_size / 2 - dz)) & (depth_mid <
                                              (zw + window_size / 2 + dz))
        ij = ij * isN
        seg = {"depth_bin": zw, "segz": depth_mid[ij], "N2": N2[ij]}
        seg["N2smooth"] = N2ref[ij]
        seg["N2mean"] = np.mean(seg["N2smooth"])
        seg["strain"] = strain[ij]
        out.append(seg)
    return out
Example #30
0
def strain_polynomial_fits(depth, t, SP, lon, lat, depth_bin, window_size):
    """
    Calculate strain with a smooth :math:`N^2` profile from polynomial fits to windowed data.

    This version outputs polyfit and strain for the whole window as opposed to
    just half the window centered.

    Parameters
    ----------
    depth : array-like
        CTD depth [m]
    t : array-like
        CTD in-situ temperature [ITS-90, degrees C]
    SP : array-like
        CTD practical salinity [psu]
    lon : array-like or float
        Longitude
    lat : array-like or float
        Latitude
    depth_bin : float
        Window centers
    window_size : float
        Window size

    Returns
    -------
    list
        List with results in a dict for each depth segment. The dict has the following entries:
        ``"segz"``
            Segment depth vector (`array-like`).
        ``"depth_bin"``
            Segment center depth (`float`).
        ``"N2"``
            Segment buoyancy frequency squared (`array-like`).
        ``"N2smooth"``
            Segment polynomial fit to buoyancy frequency squared (`array-like`).
        ``"N2mean"``
            Segment mean buoyancy frequency squared (`float`).
        ``"strain"``
            Segment strain (`array-like`).
    """
    # Prepare output list. It will hold a dictionary with data for each window.
    out = []
    dz = np.absolute(np.median(np.diff(depth)))
    # Calculate buoyancy frequency.
    pr = gsw.p_from_z(-1 * depth, lat)
    SA = gsw.SA_from_SP(SP, pr, lon, lat)
    CT = gsw.CT_from_t(SA, t, pr)
    N2, pr_mid = gsw.Nsquared(SA, CT, pr, lat=lat)
    depth_mid = -1 * gsw.z_from_p(pr_mid, lat)
    isN = np.isfinite(N2)
    # Second order polynomial fit for each depth window.
    for iwin, zw in enumerate(depth_bin):
        # Find data points within the depth window. As we are operating on the
        # mid-points here, we extend the search for datapoints by delta z on
        # each side of the window.
        ij = (depth_mid >=
              (zw - window_size / 2 - dz)) & (depth_mid <
                                              (zw + window_size / 2 + dz))
        ij = ij * isN
        seg = {"depth_bin": zw, "segz": depth_mid[ij], "N2": N2[ij]}
        p = np.polyfit(depth_mid[ij], N2[ij], deg=2)
        seg["N2smooth"] = np.polyval(p, depth_mid[ij])
        seg["N2mean"] = np.mean(seg["N2smooth"])
        # Calculate strain
        seg["strain"] = (seg["N2"] - seg["N2smooth"]) / seg["N2mean"]
        out.append(seg)
    return out