def test_xarray_with_coords(): pytest.importorskip('dask') SA_chunk = SA.chunk(chunks={'y': 1, 't': 1}) CT_chunk = CT.chunk(chunks={'y': 1, 't': 1}) lat_chunk = lat.chunk(chunks={'y': 1}) # Dimensions and cordinates match: expected = gsw.sigma0(SA_vals, CT_vals) xarray = gsw.sigma0(SA, CT) chunked = gsw.sigma0(SA_chunk, CT_chunk) assert_allclose(xarray, expected) assert_allclose(chunked, expected) # Broadcasting along dimension required (dimensions known) expected = gsw.alpha(SA_vals, CT_vals, p_vals[np.newaxis, :, np.newaxis]) xarray = gsw.alpha(SA, CT, p) chunked = gsw.alpha(SA_chunk, CT_chunk, p) assert_allclose(xarray, expected) assert_allclose(chunked, expected) # Broadcasting along dimension required (dimensions unknown/exclusive) expected = gsw.z_from_p(p_vals[:, np.newaxis], lat_vals[np.newaxis, :]) xarray = gsw.z_from_p(p, lat) chunked = gsw.z_from_p(p, lat_chunk) assert_allclose(xarray, expected) assert_allclose(chunked, expected)
def plot_TS(K, T, S, labels, tit, plotdir): col = ['r', 'c', 'pink', 'g', 'b'] ss = np.linspace(32.5, 35.5, 16) tt = np.linspace(-3, 3, 15) ss2, tt2 = np.meshgrid(ss, tt) s0 = gsw.sigma0(ss2, tt2) vd = np.arange(23, 30, 0.3) plt.figure(figsize=(15, 10)) for ii in range(5): ax = plt.subplot(2, 3, ii + 1) idx = np.where(labels == ii)[0][:] ax.scatter(S[idx, :], T[idx, :], color=col[ii], alpha=0.5, s=10) ax.set_xlim(32.5, 35.5) ax.set_ylim(-2.2, 2) cs = ax.contour(ss, tt, s0, vd, colors='k', linestyles='dashed', linewidths=0.5, alpha=0.8) plt.clabel(cs, inline=0, fontsize=10) ax.set_xlabel('SA') ax.set_ylabel('CT') outfile = os.path.join(plotdir, 'gmm_TS_K%i_%s.png' % (K, tit)) plt.savefig(outfile, bbox_inches='tight', dpi=200) plt.show()
def gambar_TS(self, ax, S, T, cores, labels, jumlah_garis_TS, posisi_judul): # T-S Diagram. s = ma.masked_invalid(S).mean(axis=1) t = ma.masked_invalid(T).mean(axis=1) Te = np.linspace(t.min(), t.max(), jumlah_garis_TS) Se = np.linspace(s.min(), s.max(), jumlah_garis_TS) Tg, Sg = np.meshgrid(Te, Se) sigma_theta = gsw.sigma0(Sg, Tg) cnt = np.linspace(sigma_theta.min(), sigma_theta.max(), jumlah_garis_TS) divider = make_axes_locatable(ax) axTS = divider.append_axes("right", 2, pad=1) #axTS.set(xlim=(33.2,35), ylim=(6,33)) cs = axTS.contour(Sg, Tg, sigma_theta, colors='grey', levels=cnt, zorder=1) kw = dict(color='r', fontsize=14, fontweight='black') for i in range(cores.shape[1]): axTS.text(cores[1, i], cores[0, i], labels[i], **kw) axTS.plot(s, t, 'k') axTS.yaxis.set_label_position(posisi_judul) axTS.yaxis.set_ticks_position(posisi_judul) axTS.set_xlabel("Salinity [g kg$^{-1}$]") axTS.set_ylabel("Temperature [$^\circ$C]", rotation=-90, labelpad=20) axTS.set_title("T-S Diagram") axTS.xaxis.set_major_locator(MaxNLocator(nbins=4))
def o2pl2pkg(p_col, t_col, sal_col, dopl_col, dopkg_col, lat_col, lon_col, inMat): """o2pl2pkg convert ml/l dissolved oxygen to umol/kg Input: - t_col, temperature column header deg c. - sal_col, salinity column header psu. - dopl_col, dissolved column header ml/l. - dopkg_col, dissolved column header umol/kg - lat_col, latitude for entire cast deg. - lon_col, longitude for entire cast deg. - inMat, dtype ndarray processed ctd time data. Output: - Converted Oxygen column umol/kg Example: >>> # linear interpolation of NaNs >>> outArray = o2pl2kg(inArr) """ pkg = np.ndarray(shape=len(inMat), dtype=[(dopkg_col, np.float)]) # Absolute sailinity from Practical salinity. SA = gsw.SA_from_SP(inMat[sal_col], inMat[p_col], inMat[lat_col], inMat[lon_col]) # Conservative temperature from insitu temperature. CT = gsw.CT_from_t(SA, inMat[t_col], inMat[p_col]) s0 = gsw.sigma0( SA, CT ) # Potential density from Absolute Salinity g/Kg Conservative temperature deg C. # Convert DO ml/l to umol/kg for i in range(0, len(inMat[dopl_col])): pkg[i] = inMat[dopl_col][i] * 44660 / (s0[i] + 1000) return pkg
def convert_ctddata(ctd_dir): ''' Reads raw CTD profile data and converts it to xarray ''' from epsilontools.tools import load_matfile dat = load_matfile(ctd_dir) time = pd.to_datetime(dat['UXT'], unit='s') dat = xr.Dataset( { 'T': ('time', dat['T']), 'S': ('time', dat['S']), 'p': ('time', dat['P']) }, coords={ 'time': time, }) # TODO: need to check units when integrating! dat['sigma'] = ('time', gsw.sigma0(dat['S'], dat['T']) + 1000) dat['z'] = -dat.p dat['w'] = dat.z.differentiate('time', datetime_unit='s') temp = dat.swap_dims({'time': 'z'}) temp['N2'] = -9.81 * temp.sigma.differentiate('z') / 1025 temp['dTdz'] = temp.T.differentiate('z') return temp.swap_dims({'z': 'time'})
def calc_mld(SA, CT, P, crit=.125, sd=5.): psi = find_nearest(P, sd)[1] rho = gsw.sigma0(SA, CT) rho_surf = rho[:psi + 1].mean() idx = np.where(rho >= rho_surf + crit)[0][0] mld = P[idx] return mld
def aaoptode_sternvolmer(foil_coef, optode_phase, tempc, salin, press): # %%%%%%%%%%%%%%%%%%%%%%%%%%%% # %% AAOPTODE_STERNVOLMER: For Aanderaa optode 4XXX series, to interpret # % calphase measurements based on the Stern Volmer equation. To be used in # % combination with aaoptode_salpresscorr, which handles salinity and # % pressure corrections. # # %% INPUTS # % foil_coef: Struct of calibration coefficients # % optode_phase: vector of optode phase measurements (calphase or dphase) # % tempc: temperature in deg C # % salin: Salinity # % press: pressure (db) for pressure correction # # %% OUTPUTS # % optode_uM: Oxygen concentration in uM # % optode_umolkg: Oxygen concentration in umol/kg # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% # % H. Palevsky, 8/6/2019, based on sg_aaoptode.m # % Uchida et al. 2008 Stern-Volmer based calbration mode C = foil_coef; Ksv = C[0] + C[1]*tempc+C[2]*tempc**2; P0 = C[3] + C[4]*tempc; PC = C[5] + C[6]*optode_phase; optode_uM = ((P0/PC)-1)/Ksv; # % note - this uses SR, reference salinity SA = 35.16504/35*salin; CT = gsw.CT_from_t(SA,tempc,press); optode_umolkg = 1000*optode_uM/(1000+ gsw.sigma0(SA,CT)); return optode_uM, optode_umolkg
def add_ctd_params(df_in: MutableMapping[str, Sequence], cfg: Mapping[str, Any], lon=16.7, lat=55.2): """ Calculate all parameters from 'sigma0', 'depth', 'soundV', 'SA' that is specified in cfg['out']['data_columns'] :param df_in: DataFrame with columns: 'Pres', 'Temp90' or 'Temp', and may be others: 'Lat', 'Lon': to use instead cfg['in']['lat'] and lat and -//- lon :param cfg: dict with fields: ['out']['data_columns'] - list of columns in output dataframe ['in'].['b_temp_on_its90'] - optional :param lon: # 54.8707 # least priority values :param lon: # 19.3212 :return: DataFrame with only columns specified in cfg['out']['data_columns'] """ ctd = df_in params_to_calc = set(cfg['out']['data_columns']).difference(ctd.columns) params_coord_needed_for = params_to_calc.intersection( ('depth', 'sigma0', 'SA', 'soundV')) # need for all cols? if any(params_coord_needed_for): # todo: load from nav: if np.any(ctd.get('Lat')): lat = ctd['Lat'] lon = ctd['Lon'] else: if 'lat' in cfg['in']: lat = cfg['in']['lat'] lon = cfg['in']['lon'] else: print( 'Calc', '/'.join(params_coord_needed_for), f'using MANUAL INPUTTED coordinates: lat={lat}, lon={lon}') if 'Temp90' not in ctd.columns: if cfg['in'].get('b_temp_on_its90'): ctd['Temp90'] = ctd['Temp'] else: ctd['Temp90'] = gsw.conversions.t90_from_t68(df_in['Temp']) ctd['SA'] = gsw.SA_from_SP( ctd['Sal'], ctd['Pres'], lat=lat, lon=lon) # or Sstar_from_SP() for Baltic where SA=S* # Val['Sal'] = gsw.SP_from_C(Val['Cond'], Val['Temp'], Val['P']) if 'soundV' in params_to_calc: ctd['soundV'] = gsw.sound_speed_t_exact(ctd['SA'], ctd['Temp90'], ctd['Pres']) if 'depth' in params_to_calc: ctd['depth'] = np.abs(gsw.z_from_p(np.abs(ctd['Pres']), lat)) if 'sigma0' in params_to_calc: CT = gsw.CT_from_t(ctd['SA'], ctd['Temp90'], ctd['Pres']) ctd['sigma0'] = gsw.sigma0(ctd['SA'], CT) # ctd = pd.DataFrame(ctd, columns=cfg['out']['data_columns'], index=df_in.index) if 'Lat' in params_to_calc and not 'Lat' in ctd.columns: ctd['Lat'] = lat ctd['Lon'] = lon return ctd[cfg['out']['data_columns']]
def derive_csv(data): density = gsw.z_from_p(cast[6].values,lat) absolute_sal=gsw.SA_from_SP(cast[10].values,density,lon,lat) reference_sal=gsw.SR_from_SP(absolute_sal) conservative_temp=gsw.CT_from_t(absolute_sal,cast[8],density) potential_density=gsw.sigma0(absolute_sal,conservative_temp) return density,absolute_sal,reference_sal,conservative_temp,potential_density
def barrier_layer_thickness(SA, CT): """ Compute the thickness of water separating the mixed surface layer from the thermocline. A more precise definition would be the difference between mixed layer depth (MLD) calculated from temperature minus the mixed layer depth calculated using density. """ import gsw sigma_theta = gsw.sigma0(SA, CT) mask = mixed_layer_depth(CT) mld = np.where(mask)[0][-1] sig_surface = sigma_theta[0] sig_bottom_mld = gsw.sigma0(SA[0], CT[mld]) d_sig_t = sig_surface - sig_bottom_mld d_sig = sigma_theta - sig_bottom_mld mask = d_sig < d_sig_t # Barrier layer. return Series(mask, index=SA.index, name='BLT')
def barrier_layer_thickness(SA, CT): """ Compute the thickness of water separating the mixed surface layer from the thermocline. A more precise definition would be the difference between mixed layer depth (MLD) calculated from temperature minus the mixed layer depth calculated using density. """ import gsw sigma_theta = gsw.sigma0(SA, CT) mask = mixed_layer_depth(CT) mld = np.where(mask)[0][-1] sig_surface = sigma_theta[0] sig_bottom_mld = gsw.sigma0(SA[0], CT[mld]) d_sig_t = sig_surface - sig_bottom_mld d_sig = sigma_theta - sig_bottom_mld mask = d_sig < d_sig_t # Barrier layer. return Series(mask, index=SA.index, name="BLT")
def dens0(S, T, P): # ctd file contain in situ temperature and practical salinity # CT= conservative temperature # SA= absolute salinity # p is sea pressure (dbar) SA = gsw.SA_from_SP(S, P, 6., 42.) CT = gsw.CT_from_t(SA, T, P) # sound speed #C = gsw.sound_speed(SA, CT, P) return gsw.sigma0(SA, CT) + 1000.
def sigma0(S, T, p, lat=None, lon=None): ones = xr.ones_like(S) p = ones * S['p'] 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) rho = gsw.sigma0(SA, CT) return rho
def oxy_to_umolkg(df_sal, df_pressure, df_lat, df_lon, df_temp, df_oxy): '''Rewritten from Courtney's method to use array-likes (aka use dataframes and ndarrays). ''' # Absolute salinity from Practical salinity. SA = gsw.SA_from_SP(df_sal, df_pressure, df_lat, df_lon) # Conservative temperature from insitu temperature. CT = gsw.CT_from_t(SA, df_temp, df_pressure) s0 = gsw.sigma0( SA, CT ) # Potential density from Absolute Salinity g/Kg Conservative temperature deg C. series = df_oxy * 44660 / (s0 + 1000) return series
def derive_cnv(self): """Compute SP, SA, CT, z, and GP from a cnv pre-processed cast.""" import gsw cast = self.copy() p = cast.index.values.astype(float) cast['SP'] = gsw.SP_from_C(cast['c0S/m'].values * 10., cast['t090C'].values, p) cast['SA'] = gsw.SA_from_SP(cast['SP'].values, p, self.lon, self.lat) cast['SR'] = gsw.SR_from_SP(cast['SP'].values) cast['CT'] = gsw.CT_from_t(cast['SA'].values, cast['t090C'].values, p) cast['z'] = -gsw.z_from_p(p, self.lat) cast['sigma0_CT'] = gsw.sigma0(cast['SA'].values, cast['CT'].values) return cast
def sbe43(volts, p, t, c, coefs, lat=0.0, lon=0.0): # NOTE: lat/lon = 0 is not "acceptable" for GSW, come up with something else? """ SBE equation for converting SBE43 engineering units to oxygen (ml/l). SensorID: 38 Parameters ---------- volts : array-like Raw voltage p : array-like Converted pressure (dbar) t : array-like Converted temperature (Celsius) c : array-like Converted conductivity (mS/cm) coefs : dict Dictionary of calibration coefficients (Soc, Voffset, Tau20, A, B, C, E) lat : array-like, optional Latitude (decimal degrees north) lon : array-like, optional Longitude (decimal degrees) Returns ------- oxy_ml_l : array-like Converted oxygen (mL/L) """ # TODO: is there any reason for this to output mL/L? if oxygen eq uses o2sol # in umol/kg, result is in umol/kg... which is what we use at the end anyway? t_Kelvin = t + 273.15 SP = gsw.SP_from_C(c, t, p) SA = gsw.SA_from_SP(SP, p, lon, lat) CT = gsw.CT_from_t(SA, t, p) sigma0 = gsw.sigma0(SA, CT) o2sol = gsw.O2sol(SA, CT, p, lon, lat) # umol/kg o2sol_ml_l = oxy_umolkg_to_ml(o2sol, sigma0) # equation expects mL/L (see TODO) # NOTE: lat/lon always required to get o2sol (and need SA/CT for sigma0 anyway) # the above is equivalent to: # pt = gsw.pt0_from_t(SA, t, p) # o2sol = gsw.O2sol_SP_pt(s, pt) oxy_ml_l = (coefs["Soc"] * (volts + coefs["offset"]) * (1.0 + coefs["A"] * t + coefs["B"] * np.power(t, 2) + coefs["C"] * np.power(t, 3)) * o2sol_ml_l * np.exp(coefs["E"] * p / t_Kelvin)) return np.around(oxy_ml_l, 4)
def sigma_from_CTD(sal, temp, press, lon, lat, ref=0): """ Calculates potential density from CTD parameters at various reference pressures Parameters ---------- sal :array-like Salinity in PSU (PSS-78) temp :array_like In-situ temperature in deg C press :array_like Pressure in dbar lon :array_like longitude in decimal degrees lat :array_like latitute in decimal degrees ref :int reference pressure point for caluclateing sigma0 (in ref * 1000 dBar ref[0-4]) Returns ------- simga :array-like Potential density calculated at a reference pressure of ref * 1000 dBar """ CT = gsw.CT_from_t(sal, temp, press) SA = gsw.SA_from_SP(sal, press, lon, lat) # Reference pressure in ref*1000 dBars if ref == 0: sigma = gsw.sigma0(SA, CT) elif ref == 1: sigma = gsw.sigma1(SA, CT) elif ref == 2: sigma = gsw.sigma2(SA, CT) elif ref == 3: sigma = gsw.sigma3(SA, CT) elif ref == 4: sigma = gsw.sigma4(SA, CT) return sigma
def calc_teos10_columns(self, lat, lng): # Practical Salinity SP = gsw.SP_from_C(self.data['Cond'], self.data['Temp'], self.data['Pres']) # Absolute Salinity SA = gsw.SA_from_SP_Baltic(SP, lng, lat) # Conservative Temperature CT = gsw.CT_from_t(SA, self.data['Temp'], self.data['Pres']) # Sigma(density) with reference pressure of 0 dbar sigma = gsw.sigma0(SA, CT) # Depth depth = list(map(abs, gsw.z_from_p(self.data['Pres'], lat))) return {'PracticalSalinity' : SP, 'AbsoluteSalinity' : SA, 'ConservativeTemperature' : CT, 'Sigma(density)' : sigma, 'Depth' : depth}
def add_SA_CT_PT(xray): if 'PRES' in list(xray.data_vars): PRES_out = xray['PRES'] else: PRES_out = -gsw.p_from_z(xray['DEPTH']) SA_out = gsw.SA_from_SP(xray['PSAL'], PRES_out, xray.LONGITUDE, xray.LATITUDE) if 'PTMP' in list(xray.data_vars): PT_out = xray['PTMP'] else: PT_out = gsw.pt0_from_t(SA_out, xray['TEMP'], PRES_out) CT_out = gsw.CT_from_pt(SA_out, PT_out) PD_out = gsw.sigma0(SA_out, CT_out) xray['ASAL'] = (('TIME', 'DEPTH'), SA_out) xray['PTMP'] = (('TIME', 'DEPTH'), PT_out) xray['CTMP'] = (('TIME', 'DEPTH'), CT_out) xray['PDEN'] = (('TIME', 'DEPTH'), PD_out)
def __Density(self): temp = ArgoData(Type='Temperature', Month=self.Month) temp.AllData() sal = ArgoData(Type='Salinity', Month=self.Month) sal.AllData() self.lons = temp.lons self.lats = temp.lats self.press = temp.press self.press_units = temp.press_units self.t_units = 'kg/m^3' self.t_title = temp.t_title press = np.zeros(temp.t_all.shape) for i in range(len(self.press)): press[i].fill(self.press[i]) self.t_all = gsw.sigma0( sal.t_all, temp.t_all) #potential density (rho for density)
def TSdiagram(df, salt='sal00', temp='t090C', figsize=(10,10)): """Plot a TS diagram with parametric isopycnals based on the limits given in the df Parameters ---------- df : pandas.DataFrame dataframe containing the T/S pair to plot salt : str, optional salt variable column name, by default 'sal00' temp : str, optional temp variable column name, by default 't090C' """ # create parametric isopycnals T = np.linspace(df[temp].min() - 1, df[temp].max() + 1, 100) S = np.linspace(df[salt].min() - 0.1, df[salt].max() + 0.1, 100) T,S = np.meshgrid(T,S) # compute density rho = gsw.sigma0(S,T) ##-- dataviz --## fig,ax = plt.subplots(figsize=figsize) # plot isopycnals as background cr_bground = ax.contour(S, T, rho, colors='grey', zorder=1, linewidths=(0.5), linestyles=('dashed')) # identification of some isopycnals cl_bground = ax.clabel(cr_bground, fontsize=10, inline=True, fmt="%0.1f") # adding TS pairs ts_cr = ax.scatter(df[salt], df[temp], s=10, alpha=1, color='k') ax.set_xlabel('Salinity [psu]', fontsize=14) ax.set_ylabel(r'Temperature [$^o$C]', fontsize=14) return fig,ax
def loadArgoRunsFromFile(partialUrl): pressuresOut = [] densitiesOut = [] tempsOut = [] if downloadRun(partialUrl) != -1: runId = runIdFromPartial(partialUrl) dataset = Dataset("runs/" + runId + ".nc") pressures = dataset.variables["pres_adjusted"][:][0] salts = dataset.variables["psal"][:][0] temps = dataset.variables["temp"][:][0] for index in range(len(pressures)): if pressures[index] != "_": pres = pressures[index] psal = salts[index] temp = temps[index] temp = gsw.conversions.CT_from_t(psal, temp, pres) tempsOut.append(temp) pressuresOut.append(float(pres)) densitiesOut.append(float(gsw.sigma0(psal, temp))) return pressuresOut, densitiesOut, tempsOut
def buoyancy_freq(data): #Get buoyancy frequency dp = np.diff(data['c_pres'].values, axis=0) data['dp'] = np.append(dp, dp[-1]) data['dp'] = data['dp'].mask( ((data['dp'] - data['dp'].mean()).abs() > data['dp'].std())) data['dp'] = data['dp'].interpolate().rolling(5).mean() 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) pdens = gsw.sigma0(SA, CT) data['pdens'] = pdens dpdens = np.diff(data['pdens'].values, axis=0) data['dpdens'] = np.append(dpdens, dpdens[-1]) data['dpdens'] = data['dpdens'].mask( ((data['dpdens'] - data['dpdens'].mean()).abs() > data['dpdens'].std())) data['dpdens'] = data['dpdens'].interpolate().rolling(5).mean() data['N2'] = (9.7963 * data['dpdens']) / (data['pdens'] * data['dp']) #filter buoyancy frequency by removing outliers #data['N2'] = data['N2'].mask(data['N2']< 0.000005) data['N2'] = data["N2"].replace([np.inf, -np.inf], np.nan) data['N2'] = data['N2'].mask( ((data['N2'] - data['N2'].mean()).abs() > data['N2'].std())) data['N2'] = data['N2'].interpolate().rolling(10).mean() #data['N2'] = data['N2'].mask(((data['N2']-data['N2'].mean()).abs() > 3*data['N2'].std())) #data['N2'] = data['N2'].interpolate() #Sorted data['pdens_sort'] = np.sort(pdens) dpdens_sort = np.diff(data['pdens_sort'].values, axis=0) data['dpdens_sort'] = np.append(dpdens_sort, dpdens_sort[-1]) data['dpdens_sort'] = data['dpdens_sort'].mask( ((data['dpdens_sort'] - data['dpdens_sort'].mean()).abs() > data['dpdens_sort'].std())) data['dpdens_sort'] = data['dpdens_sort'].interpolate().rolling(5).mean() data['N2_sort'] = (9.7963 * data['dpdens_sort']) / (data['pdens_sort'] * data['dp']) return data
def density_contours4TS(ax): """This function puts lines of constant density into a given T-S-asxis""" Tl = ax.get_ylim() Sl = ax.get_xlim() DS = (Sl[1] - Sl[0]) / 10 DT = (Tl[1] - Tl[0]) / 10 s = np.arange(Sl[0], Sl[1] + DS, DS) t = np.arange(Tl[0], Tl[1] + DT, DT) S, T = np.meshgrid(s, t) R = gsw.sigma0(S, T) minR = np.min(R) maxR = np.max(R) DR = maxR - minR Rlevels = np.arange(minR, maxR, DR / 7) conts = ax.contour(S, T, R, levels=Rlevels, colors='.7', Linewidth=1)
def gambar_utama(self, S, T, depth, latitude, hasil_mixing): s = ma.masked_invalid(self.S).mean(axis=1) t = ma.masked_invalid(self.T).mean(axis=1) Te = np.linspace(t.min(), t.max(), 10) Se = np.linspace(s.min(), s.max(), 10) Tg, Sg = np.meshgrid(Te, Se) sigma_theta = gsw.sigma0(Sg, Tg) cnt = np.linspace(sigma_theta.min(), sigma_theta.max(), 15) Reds = brewer2mpl.get_map('Reds', 'Sequential', 9).mpl_colormap Blues = brewer2mpl.get_map('Blues', 'Sequential', 9).mpl_colormap Greens = brewer2mpl.get_map('Greens', 'Sequential', 9).mpl_colormap warna = [Reds, Blues, Greens] # Grid for contouring. zg, xg = np.meshgrid(self.depth, self.latitude) self.fig, self.ax = plt.subplots(nrows=1, ncols=1, figsize=(14, 6), facecolor='w') self.ax.invert_yaxis() kl = [] percent = [50, 60, 70, 80, 90, 100] # m = np.zeros(hasil_mixing.shape) for i in range(hasil_mixing.shape[2]): k = self.ax.contourf(xg, zg, hasil_mixing[0:, 0:, i].transpose(), percent, cmap=warna[i], zorder=3) k.set_clim(percent[0], percent[-1]) kl.append(k) return self.fig, kl, self.ax
def calc_preind_co2_AOU_method(arrowdate, obs_year, target_year, scen): import numpy as np import netCDF4 as nc import gsw test_LO = hm.load_nc(arrowdate) tdate = arrowdate yy = tdate.format('YYYY') mm = tdate.format('MM') dd = tdate.format('DD') ymd = f'y{yy}m{mm}d{dd}' #open dataset & retrieve relevant variables, calculate potential density zlevels = (test_LO['deptht'][:]) sal = test_LO['vosaline'][0, :, 0, :] temp = test_LO['votemper'][0, :, 0, :] sigma0 = gsw.sigma0(sal, temp) DIC = test_LO['DIC'][0, :, 0, :] TA = test_LO['TA'][0, :, 0, :] O2 = test_LO['OXY'][0, :, 0, :] depth_this = np.zeros_like(TA) zeros = np.zeros_like(TA) #depth_this - array of depths of same shape as DIC for i in range(0, 950): depth_this[:, i] = zlevels ### GET AGE AND WATERMASS WITNESSED CO2 #calculate pycnal's last surfacing, according to exp function #found using cfc ages params0 = 0.1301889490932413 params1 = 3.8509914822057825 params2 = 8.301166081413104 #change to 2015 since model year is 2015 water_age = (params0 * np.exp(-params1 * (25.15 - sigma0)) + params2) # year_watermass_at_surface = int(targetyear - age) # watermass_witnessed_co2_obs = int(hm.co2_from_year(scen,year_watermass_at_surface)) #get witnessed co2 both of the present day water parcel and the target year water parcel obs_year_ar = np.zeros_like(water_age) obs_year_ar[:] = obs_year target_year_ar = np.zeros_like(water_age) target_year_ar[:] = target_year year_watermass_at_surface = (obs_year_ar - water_age).astype(int) watermass_witnessed_co2_obs = hm.co2_from_year(scen, year_watermass_at_surface) print(np.min(watermass_witnessed_co2_obs)) print(np.shape(watermass_witnessed_co2_obs)) if target_year < 1905: watermass_witnessed_co2_target = 284 else: watermass_witnessed_co2_target = \ hm.co2_from_year(scen,year_watermass_at_surface+(target_year_ar-obs_year_ar)) ###GET AOU #(1) estimate AOU on 26 (assoc with water parcel with DIC_{w,2019,26,jdf}) # = f(O2_{w,2019,26,jdf},S_{w,2019,26,jdf},T_{w,2019,26,jdf}, P_{w,2019,26,jdf}) #(P is there to determine T when last at surface - I'll call it preT next) AOU_stoich = hm.get_AOU_stoich(sal, temp, O2, sigma0, water_age) ### GET PREFORMED DIC obs_preformed_dic = DIC - AOU_stoich #### get preformed pco2 and target year preformed pco2 pHr, OmAr, pco2r = hm.oned_moxy(sal, temp, obs_preformed_dic, TA, 1, np.zeros_like(sal)) obsyear_pref_pco2 = pco2r diseqPCO2 = obsyear_pref_pco2 - watermass_witnessed_co2_obs targetyear_pref_pco2 = watermass_witnessed_co2_target + diseqPCO2 print('calculating target year preformed DIC') target_preformed_dic = np.zeros_like(DIC) target_preformed_dic_r = np.ravel(target_preformed_dic) targetyear_pref_pco2_r = np.ravel(targetyear_pref_pco2) depth_r = np.ravel(depth_this) sal_r = np.ravel(sal) temp_r = np.ravel(temp) TA_r = np.ravel(TA) zeros_r = np.zeros_like(TA_r) sigma0_r = np.ravel(sigma0) start = time.time() for i in range(0, len(TA_r)): if i % (950 * 5) == 0: print(f'level: {i/(950*5)}') ### the surface needs better handling if sigma0_r[i] < 25.0: target_preformed_dic_r[i] = 9999 #### the bottom can be actually taken from the cell right above it, no need to do this painful calculation if depth_r[i] > 330: target_preformed_dic_r[i] = 6666 else: t_dic = hm.find_DIC_corresp_to_pco2(sal_r[i], temp_r[i], targetyear_pref_pco2_r[i], TA_r[i], 1, 0) target_preformed_dic_r[i] = t_dic print('seconds taken at the hard part') print(time.time() - start) # deltaDIC = obs_preformed_dic - target_preformed_dic # print('max deltaDIC: '+str(np.max(deltaDIC)) + ', min deltaDIC: '+ str(np.min(deltaDIC))) # final_target_DIC = DIC - deltaDIC ## the top and bottom can be dealt with differently DIC_r = np.ravel(DIC) obs_preformed_dic_r = np.ravel(obs_preformed_dic) deltaDIC_r = obs_preformed_dic_r - target_preformed_dic_r final_target_DIC_r = DIC_r - deltaDIC_r for i in range(0, len(TA_r)): if sigma0_r[i] < 25.0: deltaDIC_r[i] = 9999 obs_preformed_dic_r[i] = 9999 target_preformed_dic_r[i] = 9999 final_target_DIC_r[i] = 9999 if depth_r[i] > 330: deltaDIC_r[i] = 6666 obs_preformed_dic_r[i] = 6666 target_preformed_dic_r[i] = 6666 final_target_DIC_r[i] = 6666 deltaDIC = deltaDIC_r.reshape(40, 950) obs_preformed_dic = obs_preformed_dic_r.reshape(40, 950) target_preformed_dic = target_preformed_dic_r.reshape(40, 950) final_target_DIC = final_target_DIC_r.reshape(40, 950) #target_preformed_dic = target_preformed_dic_r.reshape(40,950) # target_year_ar = np.zeros_like(final_target_DIC) # target_year_ar[:] = target_year f = nc.Dataset( f'./JdF_future_DIC/LO_TY_{target_year}_scen_{scen}_{ymd}_DIC_nosurfnodeep.nc', 'w', format='NETCDF4') #'w' stands for write g = f.createGroup('preindustrial_DIC') g.createDimension('xval', 950) g.createDimension('depth', 40) g.createDimension('single', 1) ts = g.createVariable('sigma0', 'f4', ('depth', 'xval')) ts[:] = sigma0 ts2 = g.createVariable('water_age', 'f4', ('depth', 'xval')) ts2[:] = water_age ts2a = g.createVariable('target_year', 'f4', ('single')) ts2a[:] = target_year # ts3 = g.createVariable('watermass_witnessed_co2_obs','f4',('depth','xval')) # ts3[:] = watermass_witnessed_co2_obs # ts3a = g.createVariable('watermass_witnessed_co2_target','f4',('depth','xval')) # ts3a[:] = watermass_witnessed_co2_target ts4 = g.createVariable('AOU_stoich', 'f4', ('depth', 'xval')) ts4[:] = AOU_stoich ts5 = g.createVariable('obsyear_pref_pco2', 'f4', ('depth', 'xval')) ts5[:] = obsyear_pref_pco2 ts5a = g.createVariable('targetyear_pref_pco2', 'f4', ('depth', 'xval')) ts5a[:] = targetyear_pref_pco2 ts5b = g.createVariable('obsyear_pref_dic', 'f4', ('depth', 'xval')) ts5b[:] = obs_preformed_dic ts5c = g.createVariable('targetyear_pref_dic', 'f4', ('depth', 'xval')) ts5c[:] = target_preformed_dic ts6 = g.createVariable('final_target_DIC', 'f4', ('depth', 'xval')) ts6[:] = final_target_DIC f.close()
def save_as_xr(input, output): '''Read float files, compose xarray dataset, convert variables, and save as netcdf last updated: june 11, 2019 ''' a = load_matfile(str(input)) output = str(output) # u = 0.5 * (a['A']['u1'].flatten()[0] + a['A']['u2'].flatten()[0]) # v = 0.5 * (a['A']['v1'].flatten()[0] + a['A']['v2'].flatten()[0]) # dudz = 0.5 * (a['A']['du1dz'].flatten()[0] + a['A']['du2dz'].flatten()[0]) # dvdz = 0.5 * (a['A']['dv1dz'].flatten()[0] + a['A']['dv2dz'].flatten()[0]) # eps = np.nanmedian(np.dstack((a['A']['eps1'].flatten()[0], # a['A']['eps2'].flatten()[0])), axis=2) # chi = np.nanmedian(np.dstack((a['A']['chi1'].flatten()[0], # a['A']['chi2'].flatten()[0])), axis=2) # compose dataset object ds = xr.Dataset( { # define wanted variables here! 'sigma': (['z', 'time'], a['A']['Sigma'].flatten()[0]), 'u1': (['z', 'time'], a['A']['u1'].flatten()[0]), 'u2': (['z', 'time'], a['A']['u2'].flatten()[0]), 'v1': (['z', 'time'], a['A']['v1'].flatten()[0]), 'v2': (['z', 'time'], a['A']['v2'].flatten()[0]), 'du1dz': (['z', 'time'], a['A']['du1dz'].flatten()[0]), 'du2dz': (['z', 'time'], a['A']['du2dz'].flatten()[0]), 'dv1dz': (['z', 'time'], a['A']['dv1dz'].flatten()[0]), 'dv2dz': (['z', 'time'], a['A']['dv2dz'].flatten()[0]), 'eps1': (['z', 'time'], a['A']['eps1'].flatten()[0]), 'eps2': (['z', 'time'], a['A']['eps2'].flatten()[0]), 'chi1': (['z', 'time'], a['A']['chi1'].flatten()[0]), 'chi2': (['z', 'time'], a['A']['chi2'].flatten()[0]), # variables needed for QC 'RotP': (['z', 'time'], a['A']['RotP'].flatten()[0]), 'W': (['z', 'time'], a['A']['W'].flatten()[0]), 'verr1': (['z', 'time'], a['A']['verr1'].flatten()[0]), 'verr2': (['z', 'time'], a['A']['verr2'].flatten()[0]), 'kT1': (['z', 'time'], a['A']['kT1'].flatten()[0]), 'kT2': (['z', 'time'], a['A']['kT2'].flatten()[0]), 'T': (['z', 'time'], a['A']['T'].flatten()[0]), 'S': (['z', 'time'], a['A']['S'].flatten()[0]), 'n2': (['z', 'time'], a['A']['N2'].flatten()[0]) }, coords={ 'pressure': (['z'], a['A']['Pr'].flatten()[0].astype(float)), 'z': a['A']['Pr'].flatten()[0].astype(float), 'lat': (['time'], a['A']['lat'].flatten()[0]), 'lon': (['time'], a['A']['lon'].flatten()[0]), 'time': a['A']['Jday_gmt'].flatten()[0].astype(float) }, attrs={'floatid': output.split('_')[1].split('.')[0]}) # remove nans ds = ds.dropna(dim='time', how='all') # convert to datetime ds = ds.assign_coords(time=(dn2dt_vec(ds.time))) # comvert pressure to depth ds = ds.assign_coords(z=(gsw.z_from_p(ds.z, ds.lat.mean()).astype(float))) # ds = ds.assign_coords(z=-ds.z) _, index = np.unique(ds.time, return_index=True) ds = ds.isel(time=index) # convert variables p, lon, lat = xr.broadcast(ds.pressure, ds.lon, ds.lat) ds['S'] = xr.DataArray(gsw.SA_from_SP(ds.S, p, lon, lat), dims=['z', 'time']) ds['T'] = xr.DataArray(gsw.CT_from_t(ds.S, ds.T, p), dims=['z', 'time']) ds['rho0'] = xr.DataArray(gsw.sigma0(ds.S, ds.T) + 1000, dims=['z', 'time']) # save as netcdf ds.to_netcdf(str(output))
CT = gsw.CT_from_t(SA, temp_s, depth_s) #CT_5mean=np.mean(CT) #SA_5mean=np.mean(SA) # plot T/S diagram - altered from example from https://medium.com@hafezahmad/making-#temperature-salinity-diagrams-called-the-t-s-diagram-with-python-and-r-#programming-5deec6378a29 mint = np.min(CT) maxt = np.max(CT) mins = np.min(SA) maxs = np.max(SA) tempL = np.linspace(mint - 1, maxt + 1, len(SA)) salL = np.linspace(mins - 1, maxs + 1, len(SA)) Tg, Sg = np.meshgrid(tempL, salL) sigma_theta = gsw.sigma0(Sg, Tg) cnt = np.linspace(sigma_theta.min(), sigma_theta.max(), len(SA)) fig, ax = plt.subplots(figsize=(10, 10)) cs = ax.contour(Sg, Tg, sigma_theta, colors='grey', zorder=1) cl = plt.clabel(cs, fontsize=10) #sc=plt.scatter(SA_5_day_mean,CT_5_day_mean,c=cnt) sc = plt.scatter(SA, CT, c=cnt) cb = plt.colorbar(sc) cb.set_label('Density') plt.xlabel('Salinity A') plt.ylabel('Conservative Temperature') plt.title('T-S at BATS at T= ' + str(year) + ' - ' + str(month) + ' - ' + str(day) + '') cb.set_label('Density') plt.show()
for l in np.arange(len(new_dates_num)): P_PD[:, l] = depth_range SA = gsw.SA_from_SP(S_PD, P_PD, lon_array_pd, lat_array_pd) CT = gsw.CT_from_t(SA, T_PD, P_PD) oxy_eq = gsw.O2sol(SA, CT, P_PD, lon_array_pd, lat_array_pd) OS_PD = O_PD / oxy_eq * 100 D_PD = np.zeros(T_PD.shape) D_PD[:] = np.NaN for r in np.arange(D_PD.shape[0]): for c in np.arange(D_PD.shape[1]): if np.isnan(SA[r, c]) == False and np.isnan( CT[r, c]) == False: D_PD[r, c] = gsw.sigma0(SA[r, c], CT[r, c]) plt.figure(figsize=(figx, figy)) plt.pcolormesh(X, Y, OS_PD, vmin=minOsat, vmax=maxOsat, cmap=cmo.haline) plt.gca().invert_yaxis() plt.colorbar() plt.xticks(rotation=45) plt.title('Oxygen Saturation Float: ' + str(WMO)) plt.savefig(SectionFigDir + 'Pres_' + str(interp_pres) + '_' + str(WMO) + '_Interp_OxygenSaturation.jpg') plt.clf()
from ocean_tools import TKED import gsw directory = '../../Data/deployment_raw/' outdir = '../../plots/ctd/LT_Lo_R/' deployment_name = 'deploy1_' measurement_type = 'ctd_' file_type = 'raw_' for i in range(58): c_file = 'C' + ("%07d" % (i, )) c_data = pd.read_pickle(directory + deployment_name + file_type + c_file) CT = gsw.CT_from_t(c_data['c_sal'], c_data['c_temp'], c_data['c_pres']) SA = gsw.SA_from_SP(c_data['c_sal'], c_data['c_pres'], 174, -43) pdens = gsw.sigma0(SA, CT) c_data["pdens"] = pdens [LT, Td, Nsqu, Lo, R, x_sorted, idxs] = TKED.thorpe_scales1(c_data["c_depth"].values * -1, c_data['pdens'].values, full_output=True) #plt.show() fig2, (ax2, ax3, ax4) = plt.subplots(1, 3, sharey=True) # Temperature ax2.plot(LT, c_data["c_depth"].values, c='k') ax2.set_ylabel('Depth (m)') #ax2.set_ylim(ax2.get_ylim()[::-1]) #this reverses the yaxis (i.e. deep at the bottom) ax2.set_xlabel('LT (m)') ax2.xaxis.set_label_position('top') # this moves the label to the top ax2.xaxis.set_ticks_position('top') # this moves the ticks to the top
ppitch = sx_pitch.mean(axis=1) # <0: downcast | >0: upcast print('Fill NaNs in matrices - SeaExplorer') for var in list(ds.var()): if var != 'profile_index': 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