def oxygen_concentration_correction(data, ncvar): oxy_yaml = ncvar['oxygen_concentration'] if 'reference_salinity' not in oxy_yaml.keys(): _log.warning( 'No reference_salinity found in oxygen deployment yaml. Assuming reference salinity of 0 psu' ) ref_sal = 0 else: ref_sal = float(oxy_yaml['reference_salinity']) _log.info(f'Correcting oxygen using reference salinity {ref_sal} PSU') ds_oxy = data.oxygen_concentration[~np.isnan(data.oxygen_concentration)] # Match the nearest temperature and salinity values from their timestamps ds_temp = data.potential_temperature[~np.isnan(data.potential_temperature )].reindex(time=ds_oxy.time, method="nearest") ds_sal = data.salinity[~np.isnan(data.salinity)].reindex(time=ds_oxy.time, method="nearest") o2_sol = gsw.O2sol_SP_pt(ds_sal, ds_temp) o2_sat = ds_oxy / gsw.O2sol_SP_pt(ds_sal * 0 + ref_sal, ds_temp) data['oxygen_concentration'].values[~np.isnan(data.oxygen_concentration )] = o2_sat * o2_sol data['oxygen_concentration'].attrs['oxygen_concentration_QC:RTQC_methodology'] =\ f'oxygen concentration corrected for salinity using gsw.O2sol_SP_pt with salinity and potential temperature ' \ f'from dataset. Original oxygen concentration assumed to have been calculated using salinity = {ref_sal} PSU' return data
def add_psal(netCDFfile): ds = Dataset(netCDFfile, 'a') var_temp = ds.variables["TEMP"] var_psal = ds.variables["PSAL"] var_pres = ds.variables["PRES"] t = var_temp[:] SP = var_psal[:] p = var_pres[:] SA = gsw.SA_from_SP(SP, p, ds.longitude, ds.latitude) pt = gsw.pt0_from_t(SA, t, p) oxsol = gsw.O2sol_SP_pt(SP, pt) ncVarOut = ds.createVariable("OXSOL", "f4", ("TIME",), fill_value=np.nan, zlib=True) # fill_value=nan otherwise defaults to max ncVarOut[:] = oxsol ncVarOut.units = "umol/kg" ncVarOut.comment = "calculated using gsw-python https://teos-10.github.io/GSW-Python/index.html function gsw.O2sol_SP_pt" # update the history attribute try: hist = ds.history + "\n" except AttributeError: hist = "" ds.setncattr('history', hist + datetime.utcnow().strftime("%Y-%m-%d") + " : added oxygen solubility") ds.close()
def add_oxsol(netCDFfile): ds = Dataset(netCDFfile, 'a') var_temp = ds.variables["TEMP"] var_psal = ds.variables["PSAL"] t = var_temp[:] SP = var_psal[:] if "PRES" in ds.variables: var_pres = ds.variables["PRES"] pres_var = "PRES" comment = "" p = var_pres[:] elif "NOMINAL_DEPTH" in ds.variables: var_pres = ds.variables["NOMINAL_DEPTH"] pres_var = "NOMINAL_DEPTH" comment = ", using nominal depth of " + str(var_pres[:]) p = var_pres[:] else: p = 0 pres_var = "nominal depth of 0 dbar" comment = ", using nominal depth 0 dbar" lat = -47 lon = 142 try: lat = ds.variables["LATITUDE"][0] lon = ds.variables["LONGITUDE"][0] except: pass SA = gsw.SA_from_SP(SP, p, lon, lat) pt = gsw.pt0_from_t(SA, t, p) oxsol = gsw.O2sol_SP_pt(SP, pt) if 'OXSOL' in ds.variables: ncVarOut = ds.variables['OXSOL'] else: ncVarOut = ds.createVariable( "OXSOL", "f4", ("TIME", ), fill_value=np.nan, zlib=True) # fill_value=nan otherwise defaults to max ncVarOut[:] = oxsol ncVarOut.units = "umol/kg" ncVarOut.long_name = "moles_of_oxygen_per_unit_mass_in_sea_water_at_saturation" ncVarOut.comment = "calculated using gsw-python https://teos-10.github.io/GSW-Python/index.html function gsw.O2sol_SP_pt" + comment ncVarOut.coordinates = 'TIME LATITUDE LONGITUDE NOMINAL_DEPTH' # update the history attribute try: hist = ds.history + "\n" except AttributeError: hist = "" ds.setncattr( 'history', hist + datetime.utcnow().strftime("%Y-%m-%d") + " added oxygen solubility") ds.close() return netCDFfile
def add_optode_oxygen(netCDFfile): ds = Dataset(netCDFfile, 'a') var_temp = ds.variables["TEMP"] var_psal = ds.variables["PSAL"] var_bphase = ds.variables["BPHASE"] var_otemp = ds.variables["OTEMP"] #var_otemp = ds.variables["TEMP"] t = var_temp[:] SP = var_psal[:] phase = var_bphase[:] otemp = var_otemp[:] try: var_pres = ds.variables["PRES"] p = var_pres[:] except: p = 0 lat = -47 lon = 142 try: lat = ds.variables["LATITUDE"][0] lon = ds.variables["LONGITUDE"][0] except: pass SA = gsw.SA_from_SP(SP, p, lon, lat) pt = gsw.pt0_from_t(SA, t, p) sigmat = gsw.sigma0(SA, t) oxsol = gsw.O2sol_SP_pt(SP, pt) if 'OXSOL' in ds.variables: out_oxsol_var = ds.variables['OXSOL'] else: out_oxsol_var = ds.createVariable( "OXSOL", "f4", ("TIME", ), fill_value=np.nan, zlib=True) # fill_value=nan otherwise defaults to max out_oxsol_var[:] = oxsol out_oxsol_var.units = "umol/kg" out_oxsol_var.comment = "calculated using gsw-python https://teos-10.github.io/GSW-Python/index.html function gsw.O2sol_SP_pt" C0 = var_bphase.calibration_C0 C1 = var_bphase.calibration_C1 C2 = var_bphase.calibration_C2 A0 = var_bphase.calibration_A0 A1 = var_bphase.calibration_A1 B0 = var_bphase.calibration_B0 B1 = var_bphase.calibration_B1 if 'DOX2_RAW' in ds.variables: out_ox_var = ds.variables['DOX2_RAW'] else: out_ox_var = ds.createVariable( "DOX2_RAW", "f4", ("TIME", ), fill_value=np.nan, zlib=True) # fill_value=nan otherwise defaults to max oxygen = ( (A0 + A1 * otemp) / (B0 + B1 * phase) - 1) / (C0 + C1 * otemp + C2 * np.power(otemp, 2)) out_ox_var[:] = oxygen out_ox_var.comment_calc1 = 'calculated using ((A0 + A1 * otemp)/(B0 + B1 * phase) - 1)/(C0 + C1 * otemp + C2 * otemp * otemp)' out_ox_var.units = "umol" out_ox_var.long_name = "mole_concentration_of_dissolved_molecular_oxygen_in_sea_water (not salinity or pressure corrected)" out_ox_var.valid_max = np.float32(400) out_ox_var.valid_min = np.float32(0) out_ox_var.coordinates = "TIME LATITUDE LONGITUDE NOMINAL_DEPTH" # update the history attribute try: hist = ds.history + "\n" except AttributeError: hist = "" ds.setncattr( 'history', hist + datetime.utcnow().strftime("%Y-%m-%d") + " : calculated optode oxygen and oxygen solubility") ds.close()