def compute_potdens(ds, saltname='SALT', tempname='THETA'): import gsw """ compute the potential density """ # compute the Conservative Temperature from the model's potential temperature temp = ds[tempname].transpose(*('time', 'k', 'face', 'j', 'i')) salt = ds[tempname].transpose(*('time', 'k', 'face', 'j', 'i')) CT = gsw.CT_from_pt(salt, temp) z, lat = xr.broadcast(ds['Z'], ds['YC']) z = z.transpose(*('k', 'face', 'j', 'i')) lat = lat.transpose(*('k', 'face', 'j', 'i')) # compute pressure from depth p = gsw.p_from_z(z, lat) # compute in-situ temperature T = gsw.t_from_CT(salt, CT, p) # compute potential density rho = gsw.pot_rho_t_exact(salt, T, p, 0.) # create new dataarray darho = xr.full_like(temp, 0.) darho = darho.load().chunk({'time': 1, 'face': 1}) darho.name = 'RHO' darho.attrs['long_name'] = 'Potential Density ref at 0m' darho.attrs['standard_name'] = 'RHO' darho.attrs['units'] = 'kg/m3' darho.values = rho # filter special value darho = darho.where(darho > 1000) darho = darho.assign_coords(XC=ds['XC'], YC=ds['YC'], Z=ds['Z']) return darho
def _convert_TS_to_TEOS10(var_meta, sal, temp): """Convert Practical Salinity and potential temperature to Reference Salinity and Conservative Temperature using gsw functions. :arg var_meta: dictionary of metadata for salinity and temperature. Must have keys vosaline and votemper, each with a sub dictionary with keys long_name and units :type var_meta: dictionary of dictionaries :arg sal: salinity data :type sal: numpy array :arg temp: temperature daya :type temp: numpy array :returns: updated meta data, salinity and temperature""" # modify metadata new_meta = var_meta.copy() new_meta['vosaline']['long_name'] = 'Reference Salinity' new_meta['vosaline']['units'] = 'g/kg' new_meta['votemper']['long_name'] = 'Conservative Temperature' # Convert salinity from practical to reference salinity sal_ref = gsw.SR_from_SP(sal[:]) # Convert temperature from potential to conservative temp_cons = gsw.CT_from_pt(sal_ref[:], temp[:]) return new_meta, sal_ref, temp_cons
def tsdiagram( salt, temp, color=None, size=None, lon=None, lat=None, pressure=None, convert_teos10=True, ts_kwargs={}, ax=None, fig=None, draw_density_contours=True, draw_cbar=True, add_labels=True, **kwargs, ): if ax is None: ax = plt.gca() if fig is None: fig = plt.gcf() if convert_teos10: temp_label = "Conservative Temperature [$^{\circ}C$]" salt_label = "Absolute Salinity [$g/kg$]" if any([a is None for a in [lon, lat, pressure]]): raise ValueError( "when converting to teos10 variables, \ input for lon, lat and pressure is needed" ) else: salt = gsw.SA_from_SP(salt, pressure, lon, lat) temp = gsw.CT_from_pt(salt, temp) else: temp_label = "Potential Temperature [$^{\circ}C$]" salt_label = "Practical Salinity [$g/kg$]" if add_labels: ax.set_xlabel(salt_label) ax.set_ylabel(temp_label) scatter_kw_defaults = dict(s=size, c=color) scatter_kw_defaults.update(kwargs) s = ax.scatter(salt, temp, **scatter_kw_defaults) if draw_density_contours: draw_dens_contours_teos10(ax=ax, **ts_kwargs) if draw_cbar and color is not None: if isinstance(color, str) or isinstance(color, tuple): pass elif ( isinstance(color, list) or isinstance(color, np.ndarray) or isinstance(color, xr.DataArray) ): fig.colorbar(s, ax=ax) else: raise RuntimeError("`color` not recognized. %s" % type(color)) return s
def potential_to_in_situ_temperature(dsPotTemp, dsSalin): z = dsPotTemp.z.values lat = numpy.maximum(dsPotTemp.lat.values, -80.) lon = dsPotTemp.lon.values if len(lat.shape) == 1: lon, lat = numpy.meshgrid(lon, lat) nz = len(z) ny, nx = lat.shape if 'time' in dsPotTemp.dims: nt = dsPotTemp.sizes['time'] T = numpy.nan * numpy.ones((nt, nz, ny, nx)) for zIndex in range(nz): pressure = gsw.p_from_z(z[zIndex], lat) for tIndex in range(nt): pt = dsPotTemp.temperature[tIndex, zIndex, :, :].values salin = dsSalin.salinity[tIndex, zIndex, :, :].values mask = numpy.logical_and(numpy.isfinite(pt), numpy.isfinite(salin)) SA = gsw.SA_from_SP(salin[mask], pressure[mask], lon[mask], lat[mask]) TSlice = T[tIndex, zIndex, :, :] CT = gsw.CT_from_pt(SA, pt[mask]) TSlice[mask] = gsw.t_from_CT(SA, CT, pressure[mask]) T[tIndex, zIndex, :, :] = TSlice else: T = numpy.nan * numpy.ones((nz, ny, nx)) for zIndex in range(nz): pressure = gsw.p_from_z(z[zIndex], lat) pt = dsPotTemp.temperature[zIndex, :, :].values salin = dsSalin.salinity[zIndex, :, :].values mask = numpy.logical_and(numpy.isfinite(pt), numpy.isfinite(salin)) SA = gsw.SA_from_SP(salin[mask], pressure[mask], lon[mask], lat[mask]) TSlice = T[zIndex, :, :] CT = gsw.CT_from_pt(SA, pt[mask]) TSlice[mask] = gsw.t_from_CT(SA, CT, pressure[mask]) T[zIndex, :, :] = TSlice dsTemp = dsPotTemp.drop('temperature') dsTemp['temperature'] = (dsPotTemp.temperature.dims, T) dsTemp['temperature'].attrs = dsPotTemp.temperature.attrs return dsTemp
def compute_pot_density(prefix, inGridName, inDir): config = MpasAnalysisConfigParser() config.read('mpas_analysis/config.default') outDescriptor = get_comparison_descriptor(config, 'antarctic') outGridName = outDescriptor.meshName description = 'Monthly potential density climatologies from ' \ '2005-2010 average of the Southern Ocean State ' \ 'Estimate (SOSE)' botDescription = 'Monthly potential density climatologies at sea ' \ 'floor from 2005-2010 average from SOSE' for gridName in [inGridName, outGridName]: outFileName = '{}_pot_den_{}.nc'.format(prefix, gridName) TFileName = '{}_pot_temp_{}.nc'.format(prefix, gridName) SFileName = '{}_salinity_{}.nc'.format(prefix, gridName) if not os.path.exists(outFileName): with xarray.open_dataset(TFileName) as dsT: with xarray.open_dataset(SFileName) as dsS: dsPotDensity = dsT.drop(['theta', 'botTheta']) lat, lon, z = xarray.broadcast(dsS.lat, dsS.lon, dsS.z) pressure = gsw.p_from_z(z.values, lat.values) SA = gsw.SA_from_SP(dsS.salinity.values, pressure, lon.values, lat.values) CT = gsw.CT_from_pt(SA, dsT.theta.values) dsPotDensity['potentialDensity'] = (dsS.salinity.dims, gsw.rho(SA, CT, 0.)) dsPotDensity.potentialDensity.attrs['units'] = \ 'kg m$^{-3}$' dsPotDensity.potentialDensity.attrs['description'] = \ description lat, lon, z = xarray.broadcast(dsS.lat, dsS.lon, dsS.zBot) pressure = gsw.p_from_z(z.values, lat.values) SA = gsw.SA_from_SP(dsS.botSalinity.values, pressure, lon.values, lat.values) CT = gsw.CT_from_pt(SA, dsT.botTheta.values) dsPotDensity['botPotentialDensity'] = \ (dsS.botSalinity.dims, gsw.rho(SA, CT, 0.)) dsPotDensity.botPotentialDensity.attrs['units'] = \ 'kg m$^{-3}$' dsPotDensity.botPotentialDensity.attrs['description'] = \ botDescription write_netcdf(dsPotDensity, outFileName)
def get_soundc(t, s, z, lon, lat): ''' compute sound velocity ''' import gsw p = gsw.p_from_z(z, lat.mean()) SA = gsw.SA_from_SP(s, p, lon, lat) CT = gsw.CT_from_pt(SA, t) c = gsw.sound_speed(s, t, p) # inputs are: SA (absolute salinity) and CT (conservative temperature) return c
def _main(args): """Run the command line program.""" temperature_cube, temperature_history = gio.combine_files(args.temperature_file, args.temperature_var, checks=True) salinity_cube, salinity_history = gio.combine_files(args.salinity_file, 'sea_water_salinity', checks=True) assert 'c' in str(temperature_cube.units).lower(), "Input temperature units must be in celsius" # if not 'C' in str(bigthetao_cube.units): # bigthetao_cube.data = bigthetao_cube.data - 273.15 # data_median = np.ma.median(bigthetao_cube.data) # assert data_median < 100 # assert data_median > -10 # bigthetao_cube.units = 'C' target_shape = temperature_cube.shape[1:] depth = temperature_cube.coord('depth').points * -1 broadcast_depth = uconv.broadcast_array(depth, 0, target_shape) broadcast_longitude = uconv.broadcast_array(temperature_cube.coord('longitude').points, [1, 2], target_shape) broadcast_latitude = uconv.broadcast_array(temperature_cube.coord('latitude').points, [1, 2], target_shape) pressure = gsw.p_from_z(broadcast_depth, broadcast_latitude) absolute_salinity = gsw.SA_from_SP(salinity_cube.data, pressure, broadcast_longitude, broadcast_latitude) if args.temperature_var == 'sea_water_conservative_temperature': conservative_temperature = temperature_cube.data elif args.temperature_var == 'sea_water_potential_temperature': conservative_temperature = gsw.CT_from_pt(absolute_salinity, temperature_cube.data) else: raise ValueError('Invalid temperature variable') if args.coefficient == 'alpha': coefficient_data = gsw.alpha(absolute_salinity, conservative_temperature, pressure) var_name = 'alpha' standard_name = 'thermal_expansion_coefficient' long_name = 'thermal expansion coefficient' units = '1/K' elif args.coefficient == 'beta': coefficient_data = gsw.beta(absolute_salinity, conservative_temperature, pressure) var_name = 'beta' standard_name = 'saline_contraction_coefficient' long_name = 'saline contraction coefficient' units = 'kg/g' else: raise ValueError('Coefficient must be alpha or beta') iris.std_names.STD_NAMES[standard_name] = {'canonical_units': units} coefficient_cube = temperature_cube.copy() coefficient_cube.data = coefficient_data coefficient_cube.standard_name = standard_name coefficient_cube.long_name = long_name coefficient_cube.var_name = var_name coefficient_cube.units = units coefficient_cube.attributes['history'] = cmdprov.new_log(git_repo=repo_dir) iris.save(coefficient_cube, args.outfile)
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 __init__(self, sals, temps, pres, gamma, lat, lon): ##id of profiles plus info tempunit = "insitu" salunit = "practical" if tempunit not in ["insitu", "conservative", "potential"]: raise ValueError("This temperature unit is not supported") if salunit not in ["practical", "absolute", "insitu"]: raise ValueError("This salinity unit is not supported") self.lat = lat self.lon = lon nanmask = ~np.isnan(temps) nanmask = np.logical_and(~np.isnan(sals), nanmask) nanmask = np.logical_and(~np.isnan(pres), nanmask) nanmask = np.logical_and(~np.isnan(gamma), nanmask) #Temerature Salinity and Pressure self.temps = np.asarray(temps)[nanmask] self.sals = np.asarray(sals)[nanmask] self.pres = np.asarray(np.abs(pres))[nanmask] self.gamma = np.asarray(gamma)[nanmask] if salunit == "practical": self.sals = gsw.SA_from_SP(self.sals, self.pres, self.lon, self.lat) if tempunit == "potential": self.temps = gsw.CT_from_pt(self.sals, self.temps) if tempunit == "insitu": self.temps = gsw.CT_from_t(self.sals, self.temps, np.abs(self.pres)) s = np.argsort(self.pres) self.temps = self.temps[s] self.sals = self.sals[s] self.pres = self.pres[s] self.gamma = self.gamma[s] ##Interpolated Temperature, Salinity, and Pressure self.itemps = [] self.isals = [] self.ipres = [] self.igamma = [] self.idensities = [] self.neutraldepth = {} self.interpolate()
def teos10_insitu_dens(t, s, z, lat, lon): """ Computes the insitu density from potential temperature and salinity using the Thermodynamic Equation of Seawater 2010 (TEOS-10; IOC, SCOR and IAPSO, 2010). http://www.teos-10.org/pubs/TEOS-10_Manual.pdf """ depth = np.ones_like(t) * z[None, :, None] lat = np.ones_like(t) * lat[None, None, :] lon = np.ones_like(t) * lon[None, None, :] p = gsw.p_from_z(-depth, lat) SA = gsw.SA_from_SP(s, p, lon, lat) CT = gsw.CT_from_pt(SA, t) rho = gsw.rho(SA, CT, p) return rho
#GODAS SAL df = EcoFOCI_netCDF(godas_sal) global_atts = df.get_global_atts() vars_dic = df.get_vars() gd_sal = df.ncreadfile_dic() df.close() #ABS Sal f(sal, pres, lat, lon) #pressure needs to be determined from depth ABS_SA = np.ones_like(gd_sal['salt']) CONS_T = np.ones_like(gd_sal['salt']) for time_ind, month in enumerate(gd_sal['time']): print time_ind for level_ind, level in enumerate(gd_sal['level']): print level for lat_ind, lat in enumerate(gd_sal['lat']): if lat_ind % 100 == 0: print "{0} of {1}".format(lat_ind, ABS_SA.shape[2]) press = gsw.p_from_z(-1.0 * level, lat) for lon_ind, lon in enumerate(gd_sal['lon']): if lon_ind % 100 == 0: print "{0} of {1}".format(lon_ind, ABS_SA.shape[3]) ABS_SA[time_ind, level_ind, lat_ind, lon_ind] = \ gsw.SA_from_SP(gd_sal['salt'][time_ind,level_ind, lat_ind,lon_ind], press,lat,lon) CONS_T[time_ind, level_ind, lat_ind, lon_ind] = \ gsw.CT_from_pt(ABS_SA[time_ind, level_ind, lat_ind, lon_ind], gd_ptmp['pottmp'][time_ind,level_ind, lat_ind,lon_ind])
def construct_density(self, EOS='EOS10'): ''' Constructs the in-situ density using the salinity, temperture and depth_0 fields and adds a density attribute to the t-grid dataset Requirements: The supplied t-grid dataset must contain the Practical Salinity and the Potential Temperature variables. The depth_0 field must also be supplied. The GSW package is used to calculate The Absolute Pressure, Absolute Salinity and Conservate Temperature. Note that currently density can only be constructed using the EOS10 equation of state. Parameters ---------- EOS : equation of state, optional DESCRIPTION. The default is 'EOS10'. Returns ------- None. adds attribute NEMO.dataset.density ''' debug( f"Constructing in-situ density for {get_slug(self)} with EOS \"{EOS}\"" ) try: if EOS != 'EOS10': raise ValueError( str(self) + ': Density calculation for ' + EOS + ' not implemented.') if self.grid_ref != 't-grid': raise ValueError( str(self) + ': Density calculation can only be performed for a t-grid object,\ the tracer grid for NEMO.') try: shape_ds = (self.dataset.t_dim.size, self.dataset.z_dim.size, self.dataset.y_dim.size, self.dataset.x_dim.size) sal = self.dataset.salinity.to_masked_array() temp = self.dataset.temperature.to_masked_array() except AttributeError: shape_ds = (1, self.dataset.z_dim.size, self.dataset.y_dim.size, self.dataset.x_dim.size) sal = self.dataset.salinity.to_masked_array()[np.newaxis, ...] temp = self.dataset.temperature.to_masked_array()[np.newaxis, ...] density = np.ma.zeros(shape_ds) s_levels = self.dataset.depth_0.to_masked_array() lat = self.dataset.latitude.values lon = self.dataset.longitude.values # Absolute Pressure pressure_absolute = np.ma.masked_invalid( gsw.p_from_z(-s_levels, lat)) # depth must be negative # Absolute Salinity sal_absolute = np.ma.masked_invalid( gsw.SA_from_SP(sal, pressure_absolute, lon, lat)) sal_absolute = np.ma.masked_less(sal_absolute, 0) # Conservative Temperature temp_conservative = np.ma.masked_invalid( gsw.CT_from_pt(sal_absolute, temp)) # In-situ density density = np.ma.masked_invalid( gsw.rho(sal_absolute, temp_conservative, pressure_absolute)) coords = { 'depth_0': (('z_dim', 'y_dim', 'x_dim'), self.dataset.depth_0.values), 'latitude': (('y_dim', 'x_dim'), self.dataset.latitude.values), 'longitude': (('y_dim', 'x_dim'), self.dataset.longitude.values) } dims = ['z_dim', 'y_dim', 'x_dim'] attributes = { 'units': 'kg / m^3', 'standard name': 'In-situ density' } if shape_ds[0] != 1: coords['time'] = (('t_dim'), self.dataset.time.values) dims.insert(0, 't_dim') self.dataset['density'] = xr.DataArray(np.squeeze(density), coords=coords, dims=dims, attrs=attributes) except AttributeError as err: error(err)
mat = loadmat(infile) # load mat-file print(mat['date']) P = mat['P_slow'] JAC_C = mat['JAC_C'] JAC_T = mat['JAC_T'] W = mat['W_slow'] Turb = mat['Turbidity'] Chla = mat['Chlorophyll'] lat = 54 lon = -60 SP = gsw.SP_from_C(JAC_C, JAC_T, P) SA = gsw.SA_from_SP(SP, P, lon, lat) CT = gsw.CT_from_pt(SA, JAC_T) sig0 = gsw.sigma0(SA, CT) # Bring Chla / Turb to resolution of CTD bin_size = len(Turb) / len(P) Turb = Turb.reshape(-1, int(bin_size)).mean(axis=1) Chla = Chla.reshape(-1, int(bin_size)).mean(axis=1) Turb = Turb.reshape(len(Turb), 1) Chla = Chla.reshape(len(Chla), 1) df = pd.DataFrame(np.concatenate((P, CT, SP, sig0, W, Turb, Chla), axis=1), columns=[ 'pressure', 'conserv_temp', 'abs_salinity', 'sigma_0', 'vert_vel', 'Turbidity', 'Chlorophyll' ])
# ======================================================================================= # TRANSFORMATIONS ON DIFFERENT GRIDS (Density, Spatial auxiliary grid) # ======================================================================================= # --------------------------------------------------------------------------------------- # - Spatial auxiliary grid auxgrd_name = [ 'lat395model', 'lat198model', 'lat170eq80S90N', 'lat340eq80S90N' ][0] # choose aux grid lat_auxgrd, zT_auxgrd, z_w_auxgrd = utils_mask.gen_auxgrd(ncdat, auxgrd_name) lat_mgrd = ncdat.TLAT.isel( nlon=0) # mean of LAT for each j #! very inappropriate # --------------------------------------------------------------------------------------- # - Potential density and binning SA = ncdat.SALT[0, :, :, :].values # absolute salinity PT = ncdat.TEMP[0, :, :, :].values # potential temperature CT = gsw.CT_from_pt(SA, PT) # conservative temperature sig2 = gsw.sigma2(SA, CT) # potential density anomaly referenced to 2000dbar RHO = ncdat.RHO[ 0, :, :, :].values * 1000 - 1000 # in-situ density anomaly [SI] PD_bins = np.linspace(27, 38, 200) # PD_bins = np.linspace(1.004,1.036,65) # --------------------------------------------------------------------------------------- # - Paths path_auxgrd = paths.get_path2var(auxgrd_name) utils_misc.checkdir(path_auxgrd) path_mgrd = 'vars_mgrd/' path_dens = 'vars_dens/' varname_binning = 'eqbins_{}to{}in{}steps'.format(int(PD_bins.min()), int(PD_bins.max()), int(len(PD_bins))) # =======================================================================================
# Compute climatologies for temperature and salinity tempJFM = np.nanmean(np.squeeze(temp[indJFM, :, :]), axis=0) tempJAS = np.nanmean(np.squeeze(temp[indJAS, :, :]), axis=0) tempANN = np.nanmean(temp, axis=0) saltJFM = np.nanmean(np.squeeze(salt[indJFM, :, :]), axis=0) saltJAS = np.nanmean(np.squeeze(salt[indJAS, :, :]), axis=0) saltANN = np.nanmean(salt, axis=0) # Compute sigma's lonmean = np.nanmean(lon) latmean = np.nanmean(lat) pressure = gsw.p_from_z(-depth, latmean) SA = gsw.SA_from_SP(saltJFM, pressure[:, np.newaxis], lonmean, latmean) CT = gsw.CT_from_pt(SA, tempJFM) sigma2JFM = gsw.density.sigma2(SA, CT) sigma0JFM = gsw.density.sigma0(SA, CT) SA = gsw.SA_from_SP(saltJAS, pressure[:, np.newaxis], lonmean, latmean) CT = gsw.CT_from_pt(SA, tempJAS) sigma2JAS = gsw.density.sigma2(SA, CT) sigma0JAS = gsw.density.sigma0(SA, CT) SA = gsw.SA_from_SP(saltANN, pressure[:, np.newaxis], lonmean, latmean) CT = gsw.CT_from_pt(SA, tempANN) sigma2ANN = gsw.density.sigma2(SA, CT) sigma0ANN = gsw.density.sigma0(SA, CT) # Plot OSNAP section West k0 = 0
os.chdir('/home/hourstonh/Documents/OCADS/todo') ocads_data = pd.read_csv('./amended_2015-09Carbon.csv', header=[0, 1], skiprows=0, na_values=-999) print(ocads_data.iloc[0, :]) print(ocads_data.OXYGEN) # 1 ml/l = 103/22.391 = 44.661 μmol/l print(ocads_data.CTDSAL) print(ocads_data.CTDPRS) sa = gsw.SA_from_SP(ocads_data.CTDSAL, ocads_data.CTDPRS, ocads_data.LONGITUDE, ocads_data.LATITUDE) pt = gsw.pt_from_t(sa, ocads_data.CTDTMP, ocads_data.CTDPRS, 0) ct = gsw.CT_from_pt(sa, pt) print(sa) print(ct) print(ocads_data.CTDPRS) density = gsw.rho(sa, ct, ocads_data.CTDPRS) print(density) # 44.661 to convert to umol/l then convert to umol/kg if ocads_data.CTDOXY.columns[0].upper() == '(ML/L)': ocads_data['CTDOXY_2'] = ocads_data.CTDOXY * 44.661 / density * 1000. ctdoxy_digits = mode_decimals(ocads_data['CTDOXY']) ocads_data['CTDOXY_2'] = ocads_data['CTDOXY_2'].round( decimals=ctdoxy_digits) if ocads_data.OXYGEN.columns[0].upper() == '(ML/L)': ocads_data['OXYGEN_2'] = ocads_data.OXYGEN * 44.661 / density * 1000. oxygen_digits = mode_decimals(ocads_data['OXYGEN'])
def construct_pressure( self, ref_density=None, z_levels=None, extrapolate=False ): ''' This method is for calculating the hydrostatic and surface pressure fields on horizontal levels in the vertical (z-levels). The motivation is to enable the calculation of horizontal gradients; however, the variables can quite easily be interpolated onto the original vertical grid. Requirements: The object's t-grid dataset must contain the sea surface height, Practical Salinity and the Potential Temperature variables. The GSW package is used to calculate the Absolute Pressure, Absolute Salinity and Conservate Temperature. Three new variables (density, hydrostatic pressure, surface pressure) are created and added to the Contour_t.data_contour dataset: density_zlevels (t_dim, depth_z_levels, r_dim) pressure_h_zlevels (t_dim, depth_z_levels, r_dim) pressure_s (t_dim, r_dim) Note that density is constructed using the EOS10 equation of state. Parameters ---------- ref_density: float reference density value, if None, then the Contour mean across time, depth and along contour will be used. z_levels : (optional) numpy array 1d array that defines the depths to interpolate the density and pressure on to. extrapolate : boolean, default False If true the variables are extrapolated to the deepest z_level, if false, values below the bathymetry are set to NaN Returns ------- None. ''' # If there is no time dimension, add one, this is so # indexing can assume a time dimension exists if 't_dim' not in self.data_contour.dims: self.data_contour = self.data_contour.expand_dims(dim={'t_dim':1},axis=0) # Generate vertical levels if not supplied if z_levels is None: z_levels = self.gen_z_levels( self.data_contour.bathymetry.max().item() ) shape_ds = ( self.data_contour.t_dim.size, len(z_levels), self.data_contour.r_dim.size ) salinity_z = np.ma.zeros( shape_ds ) temperature_z = np.ma.zeros( shape_ds ) salinity_s = self.data_contour.salinity.to_masked_array() temperature_s = self.data_contour.temperature.to_masked_array() s_levels = self.data_contour.depth_0.values # Interpolate salinity and temperature onto z-levels # Note. At the current time there does not appear to be a good algorithm for # performing this type of interpolation without loops, which can be a bottleneck. # Griddata is an option but does not support extrapolation and did not # have noticable performance benefit. for it in self.data_contour.t_dim: for ir in self.data_contour.r_dim: if not np.all(np.isnan(salinity_s[it,:,ir].data)): # Need to remove the levels below the (envelope) bathymetry which are NaN salinity_s_r = salinity_s[it,:,ir].compressed() temperature_s_r = temperature_s[it,:,ir].compressed() s_levels_r = s_levels[:len(salinity_s_r),ir] sal_func = interpolate.interp1d( s_levels_r, salinity_s_r, kind='linear', fill_value="extrapolate") temp_func = interpolate.interp1d( s_levels_r, temperature_s_r, kind='linear', fill_value="extrapolate") if extrapolate is True: salinity_z[it,:,ir] = sal_func(z_levels) temperature_z[it,:,ir] = temp_func(z_levels) else: # set levels below the bathymetry to nan salinity_z[it,:,ir] = np.where( z_levels <= self.data_contour.bathymetry.values[ir], sal_func(z_levels), np.nan ) temperature_z[it,:,ir] = np.where( z_levels <= self.data_contour.bathymetry.values[ir], temp_func(z_levels), np.nan ) if extrapolate is False: # remove redundent levels active_z_levels = np.count_nonzero(~np.isnan(salinity_z),axis=1).max() salinity_z = salinity_z[:,:active_z_levels,:] temperature_z = temperature_z[:,:active_z_levels,:] z_levels = z_levels[:active_z_levels] # Absolute Pressure (depth must be negative) pressure_absolute = np.ma.masked_invalid( gsw.p_from_z( -z_levels[:,np.newaxis], self.data_contour.latitude ) ) # Absolute Salinity salinity_absolute = np.ma.masked_invalid( gsw.SA_from_SP( salinity_z, pressure_absolute, self.data_contour.longitude, self.data_contour.latitude ) ) salinity_absolute = np.ma.masked_less(salinity_absolute,0) # Conservative Temperature temp_conservative = np.ma.masked_invalid( gsw.CT_from_pt( salinity_absolute, temperature_z ) ) # In-situ density density_z = np.ma.masked_invalid( gsw.rho( salinity_absolute, temp_conservative, pressure_absolute ) ) coords={'depth_z_levels': (('depth_z_levels'), z_levels), 'latitude': (('r_dim'), self.data_contour.latitude), 'longitude': (('r_dim'), self.data_contour.longitude)} dims=['depth_z_levels', 'r_dim'] attributes = {'units': 'kg / m^3', 'standard name': 'In-situ density on the z-level vertical grid'} if shape_ds[0] != 1: coords['time'] = (('t_dim'), self.data_contour.time.values) dims.insert(0, 't_dim') if ref_density is None: ref_density = np.mean( density_z ) self.data_contour['density_zlevels'] = xr.DataArray( np.squeeze(density_z), coords=coords, dims=dims, attrs=attributes ) # Cumulative integral of perturbation density on z levels density_cumulative = -cumtrapz( density_z - ref_density, x=-z_levels, axis=1, initial=0) hydrostatic_pressure = density_cumulative * self.GRAVITY attributes = {'units': 'kg m^{-1} s^{-2}', 'standard name': 'Hydrostatic perturbation pressure on the z-level vertical grid'} self.data_contour['pressure_h_zlevels'] = xr.DataArray( np.squeeze(hydrostatic_pressure), coords=coords, dims=dims, attrs=attributes ) self.data_contour['pressure_s'] = ref_density * self.GRAVITY * self.data_contour.ssh.squeeze() self.data_contour.pressure_s.attrs = {'units': 'kg m^{-1} s^{-2}', 'standard_name': 'Surface perturbation pressure'}
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
os.system('rm -f ' + cf_out) os.system('cp ' + cf_temp + ' ' + cf_out) print '\n' f_sal = Dataset(cf_sal) # r+ => can read and write in the file... ) xsal = f_sal.variables[cv_sal][:, :, :, :] f_sal.close() print '\n' # Opening the Netcdf file: f_out = Dataset(cf_out, 'r+') # r+ => can read and write in the file... ) print 'File ', cf_out, 'is open...\n' # Extracting tmask at surface level: xtemp = f_out.variables[cv_temp][:, :, :, :] #xtemp[:,:,:,:] = xtemp[:,:,:,:]*2. #gsw.CT_from_pt(SA, pt) f_out.variables[cv_temp][:, :, :, :] = gsw.CT_from_pt(xsal, xtemp) f_out.variables[ cv_temp].long_name = 'Conservative Temperature (TEOS10) built from potential temperature' f_out.close() print cf_out + ' sucessfully created!'
dsOut['zonalAvgTemp'].attrs[ 'description'] = 'Zonal average of regional potential temperature' dsOut['zonalAvgSalt'][ilat - 1, :] = binSalt dsOut['zonalAvgSalt'].attrs['units'] = 'psu' dsOut['zonalAvgSalt'].attrs[ 'description'] = 'Zonal average of regional salinity' x = latbincenters y = -refBottomDepth fldtemp = dsOut.zonalAvgTemp.values.T fldsalt = dsOut.zonalAvgSalt.values.T # Compute sigma0 and sigma2 [lat, z] = np.meshgrid(x, y) pressure = gsw.p_from_z(z, lat) SA = gsw.SA_from_SP(fldsalt, pressure, 0., lat) CT = gsw.CT_from_pt(SA, fldtemp) sigma2 = gsw.density.sigma2(SA, CT) sigma0 = gsw.density.sigma0(SA, CT) ax1[iregion].set_facecolor('darkgrey') cfS = ax1[iregion].contourf(x, y, fldsalt, cmap=colormapS, norm=cnormS, levels=clevelsS, extend='both') #cfS = ax1[iregion].pcolor(x, y, fldsalt, cmap=colormapS, vmin=clevelsS[0], vmax=clevelsS[-1]) if sigma2contours is not None: cs1 = ax1[iregion].contour(x, y,
def __init__(self,eyed, data,tempunit,salunit): ##id of profiles plus info if tempunit not in ["insitu","conservative","potential"]: raise ValueError("This temperature unit is not supported") if salunit not in ["practical","absolute","insitu"]: raise ValueError("This salinity unit is not supported") if not {"sal","temp","pres","lat","lon"}.issubset(data.keys()): raise ValueError("This does not contain the required information") if abs(max(data["pres"])-min(data["pres"])) <50: print(data["pres"]) raise ValueError("This does not contain enough pressure information ") self.eyed = eyed self.lat = np.abs(data["lat"]) self.maplat = data["lat"] self.lon = data["lon"] self.f = gsw.f(self.lat) self.gamma = (9.8)/(self.f*1025.0) if "time" in data.keys(): self.time = data["time"] if "cruise" in data.keys(): self.cruise = data["cruise"]#+str(self.time.year) if "station" in data.keys(): self.station = data["station"]#+str(self.time.year) if "knownns" in data.keys(): self.knownns = data["knownns"] else: self.knownns = {} if "relcoord" in data.keys(): self.relcoord = data["relcoord"] if "knownu" in data.keys(): self.knownu = data["knownu"] self.knownv = data["knownv"] if "knownpsi" in data.keys(): self.knownpsi = data["knownpsi"] if "kapredi" in data.keys(): self.kapredi = data["kapredi"] self.kapgm = data["kapgm"] self.diffkr = data["diffkr"] #Temerature Salinity and Pressure self.temps = np.asarray(data["temp"]) self.sals = np.asarray(data["sal"]) self.pres = np.abs(np.asarray(data["pres"])) if hasattr(self.temps,"mask"): print("mask") flter = np.logical_or(~self.temps.mask,~self.sals.mask) self.temps = self.temps[flter] self.sals = self.sals[flter] self.pres = self.pres[flter] if np.isnan(self.temps).any() or np.isnan(self.sals).any(): print("huh") if salunit == "practical": self.sals = gsw.SA_from_SP(self.sals,self.pres,self.lon,self.maplat) if tempunit == "potential": self.temps = gsw.CT_from_pt(self.sals,self.temps) if tempunit == "insitu": self.temps = gsw.CT_from_t(self.sals,self.temps,np.abs(self.pres)) s = np.argsort(self.pres) self.temps = self.temps[s] self.sals = self.sals[s] self.pres = self.pres[s] ##Interpolated Temperature, Salinity, and Pressure self.itemps = [] self.isals = [] self.ipres = [] theta = np.deg2rad(self.lat) r = (90-self.lon) *111*1000 x = (r*np.cos(theta)) y = (r*np.sin(theta)) self.x = x self.y = y self.idensities = [] self.neutraldepth = {} self.interpolate()
uni['den']['cmap']=pden_cmap uni['den']['vmin']=24.5 uni['den']['vmax']=28 uni['o2']={} uni['o2']['vmin']=270 uni['o2']['vmax']=325 uni['o2']['cmap']=cm.rainbow uni['odiff']={} uni['odiff']['vmin']=-20 uni['odiff']['vmax']=20 uni['odiff']['cmap']=cm.RdBu_r salvec=linspace(31,36,103) tmpvec=linspace(-3,16,103) salmat,tmpmat=meshgrid(salvec,tmpvec) SA_vec=gsw.SA_from_SP(salvec,zeros(len(salvec)),-44,59.5) SA_vec_1000=gsw.SA_from_SP(salvec,1e3*ones(len(salvec)),-44,59.5) CT_vec=gsw.CT_from_pt(SA_vec,tmpvec) pdenmat=zeros((shape(salmat))) pdenmat2=zeros((shape(salmat))) sigma1mat=zeros((shape(salmat))) for ii in range(len(salvec)): for jj in range(len(tmpvec)): pdenmat[jj,ii]=gsw.sigma0(SA_vec[ii],CT_vec[jj]) pdenmat2[jj,ii]=gsw.pot_rho_t_exact(SA_vec[ii],tmpvec[jj],750,0)-1e3 sigma1mat[jj,ii]=gsw.sigma1(SA_vec[ii],CT_vec[jj])
def spectral_PE(self, water_path, harbour_path, name, str_date): dt = datetime.datetime.strptime(str_date[0], "%y/%m/%d %H:%M:%S") start_num = dates.date2num(dt) dt = datetime.datetime.strptime(str_date[1], "%y/%m/%d %H:%M:%S") end_num = dates.date2num(dt) #sorted from surface to bottom [dateTimeArr, resultsArr, tempArr, TH_dateTimeArr, TH_resultsArr, TH_tempArr] = \ upwelling.read_lake_and_harbour_data(str_date, [start_num,end_num], water_path, harbour_path) if name == "Lake Ontario": time = dateTimeArr z = list(range(3, len(time) + 3, 1)) t = resultsArr elif name == "Toronto Harbour": time = TH_dateTimeArr z = list(range(1, len(time) + 1, 1)) t = TH_resultsArr g = 9.81 #calculate temperature spectrum based on Potential energy #SA = Absolute Salinity [ g/kg ] #t = in-situ temperature (ITS-90) [ deg C ] #p = sea pressure [ dbar ]( i.e. absolute pressure - 10.1325 dbar ) #OPTIONAL: #p_ref = reference pressure [ dbar ] ( i.e. absolute reference pressure - 10.1325 dbar ) #(If reference pressure is not given then it is assumed that reference pressure is zero). #pt = potential temperature with [ deg C ] pt = np.zeros(len(z), dtype=np.ndarray) parr = np.zeros(len(time[0])) p_ref = 0 SA = np.zeros(len(time[0])) for i in range(0, len(z)): pt[i] = np.zeros(len(time[i])) #p = sea pressure [ dbar ] ( i.e. absolute pressure - 10.1325 dbar ) depth = -z[i] p = gsw.p_from_z(depth, [43.4]) #parr.empty(len(time[i])) #parr.fill(p[0]) #for j in range(0, len(time[i])): # pt[i][j] = gsw.pt_from_t(SA,t[i],p,p_ref)[0] pt[i] = gsw.pt_from_t(SA, t[i], p[0], p_ref) #SA = Absolute Salinity [ g/kg ] #pt = potential temperature (ITS-90) [ deg C ] #SA & pt need to have the same dimensions. #CT = Conservative Temperature [ deg C ] CT = np.zeros(len(z), dtype=np.ndarray) for i in range(0, len(z)): CT[i] = np.zeros(len(time[i])) #for j in range(0, len(time[i])): # CT[i][j] = gsw.CT_from_pt(SA,pt[i][j])[0] CT[i] = gsw.CT_from_pt(SA, pt[i]) #SA = Absolute Salinity [ g/kg ] #CT = Conservative Temperature [ deg C ] #p = sea pressure [ dbar ](i.e. absolute pressure - 10.1325 dbar) # rho = in-situ density [ kg m^-3 ] rho = np.zeros(len(z), dtype=np.ndarray) for i in range(0, len(z)): rho[i] = np.zeros(len(time[i])) #for j in range(0, len(time[i])): # rho[i][j] = gsw.rho(SA,CT[i][j],p)[0] rho[i] = gsw.rho(SA, CT[i], p) #integrate the PE PE = np.zeros(len(time[0])) for j in range(0, len(time[0])): for i in range(0, len(z) - 1): PE[j] = rho[i][j] * g * z[i] * (z[i + 1] - z[i]) draw = False type = 'amplitude' # type = 'power' label = "PSD Potential Energy [($J m^{-2})^2cph^{-1}$]" title = "" ufft.spectral_analysis.doSpectralAnalysis([time[0],PE], name, label, title, draw, window = "hanning", num_segments=6,\ tunits = "day", funits = "cph", log = 'loglog', b_wavelets = False)
da_sal = ds['salinity'] df_sal = da_sal.to_pandas() ## Un-comment for fall only df_sal = df_sal[(df_sal.index.month >= 5) & (df_sal.index.month >= 9)] df_temp = df_temp[(df_temp.index.month >= 5) & (df_temp.index.month >= 9)] sal_prof = df_sal.mean(axis=0) temp_prof = df_temp.mean(axis=0) Z = ds.level.values SP = sal_prof.values PT = temp_prof.values SA = gsw.SA_from_SP(SP, Z, -50, 50) CT = gsw.CT_from_pt(SA, PT) RHO = gsw.rho(SA, CT, Z) fig = plt.figure(1) plt.clf() plt.plot(RHO, Z) plt.xlabel(r'$\rm \rho (kg m^{-3})$', fontsize=14, fontweight='bold') plt.ylabel('Z (m)', fontsize=14, fontweight='bold') plt.gca().invert_yaxis() fig.set_size_inches(w=8, h=8) fig_name = 'BB_section_rho.png' fig.set_dpi(300) fig.savefig(fig_name) fig = plt.figure(2)
saltOnCell1 = ncid.variables['timeMonthly_avg_activeTracers_salinity'][0, cellsOnEdge1-1, :] saltOnCell2 = ncid.variables['timeMonthly_avg_activeTracers_salinity'][0, cellsOnEdge2-1, :] ncid.close() # Mask T,S values that fall on land and topography tempOnCell1 = np.ma.masked_array(tempOnCell1, ~cellMask1) tempOnCell2 = np.ma.masked_array(tempOnCell2, ~cellMask2) saltOnCell1 = np.ma.masked_array(saltOnCell1, ~cellMask1) saltOnCell2 = np.ma.masked_array(saltOnCell2, ~cellMask2) # Interpolate T,S values onto edges temp = np.nanmean(np.array([tempOnCell1, tempOnCell2]), axis=0) salt = np.nanmean(np.array([saltOnCell1, saltOnCell2]), axis=0) # Compute sigma's SA = gsw.SA_from_SP(salt, pressure[np.newaxis, :], lonmean, latmean) CT = gsw.CT_from_pt(SA, temp) sigma2 = gsw.density.sigma2(SA, CT) sigma0 = gsw.density.sigma0(SA, CT) zmax = z[np.max(maxLevelEdge)] # Plot sections # T first figtitle = 'Temperature ({}), {} ({}, years={}-{})'.format( transectName, s, casename, climoyearStart, climoyearEnd) figfile = '{}/Temp_{}_{}_{}_years{:04d}-{:04d}.png'.format( figdir, transectName.replace(' ', ''), casename, s, climoyearStart, climoyearEnd) fig = plt.figure(figsize=figsize, dpi=figdpi) ax = fig.add_subplot() ax.set_facecolor('darkgrey') cf = ax.contourf(x, y, temp, cmap=colormapT, norm=cnormT, levels=clevelsT, extend='max')