def test_magnetic_declination(self): """ Test magnetic_declination function. Some values based on those defined in the WMM document, WMM2010testvalues.pdf which accompanies the software. Others were created and checked using online calculators. Implemented by Stuart Pearce, April 2013 """ lat = np.array([45.0, 45.0, 80.0, 0.0, -80.0, 80.0, 0.0, -80.0]) lon = np.array([-128.0, -128.0, 0.0, 120.0, 240.0, 0.0, 120.0, 240.0]) z = np.array([0.0, 1000.0, 0.0, 0.0, 0.0, 100000.0, 100000.0, 100000.0]) timestamp = np.array([3575053740.7382507, # 2013-04-15 22:29:00 3575053740.7382507, # UTC 3471292800.0, # 2010-01-01 UTC 3471292800.0, 3471292800.0, 3471292800.0, 3471292800.0, 3471292800.0]) decln = np.array([16.46093044096720, 16.46376239313584, -6.13, 0.97, 70.21, -6.57, 0.94, 69.62]) out = gfunc.magnetic_declination(lat, lon, timestamp, z, -1) self.assertTrue(np.allclose(out, decln, rtol=0, atol=1e-2))
def adcp_earth_northward(u, v, z, lat, lon, dt): """ Wrapper function to compute the Northward Velocity Profile (VELPROF-VLN) from the Earth coordinate transformed data. """ # force shapes of inputs to arrays of the correct dimensions u = np.atleast_2d(u) v = np.atleast_2d(v) z = np.atleast_1d(z) / 10. # scale decimeter depth input to meters lat = np.atleast_1d(lat) lon = np.atleast_1d(lon) dt = np.atleast_1d(dt) # calculate the magnetic declination using the WWM2010 model theta = magnetic_declination(lat, lon, dt, z) # iterate through arrays for processing multiple records vv_cor = np.empty(u.shape) for indx in range(u.shape[0]): # apply the magnetic variation correction ucor, vv_cor[indx, :] = magnetic_correction(theta[indx], u[indx, :], v[indx, :]) # scale northward velocity to m/s vv_cor = vv_cor / 1000. # mm/s -> m/s # return the Northward Velocity Profile return vv_cor
def test_magnetic_declination(self): """ Test magnetic_declination function. Some values based on those defined in the WMM document, WMM2010testvalues.pdf which accompanies the software. Others were created and checked using online calculators. Implemented by Stuart Pearce, April 2013 """ lat = np.array([45.0, 45.0, 80.0, 0.0, -80.0, 80.0, 0.0, -80.0]) lon = np.array([-128.0, -128.0, 0.0, 120.0, 240.0, 0.0, 120.0, 240.0]) z = np.array( [0.0, 1000.0, 0.0, 0.0, 0.0, 100000.0, 100000.0, 100000.0]) timestamp = np.array([ 3575053740.7382507, # 2013-04-15 22:29:00 3575053740.7382507, # UTC 3471292800.0, # 2010-01-01 UTC 3471292800.0, 3471292800.0, 3471292800.0, 3471292800.0, 3471292800.0 ]) decln = np.array([ 16.46093044096720, 16.46376239313584, -6.13, 0.97, 70.21, -6.57, 0.94, 69.62 ]) out = gfunc.magnetic_declination(lat, lon, timestamp, z, -1) self.assertTrue(np.allclose(out, decln, rtol=0, atol=1e-2))
def windavg_mag_corr_east(uu, vv, lat, lon, timestamp, z=0): """ Corrects the eastward wind velocity from a METBK instrument for magnetic declination. This function calls the magnetic_declination function and the magnetic_correction function from the ion_functions.data.generic_function module. magnetic_declination calculates the declination based on data and lat & lon. magnetic_correction translates the vectors from the magnetic compass headings to true compass headings """ #******** Original Code ******** #wmm = WMM(wmm_model) #uu = np.asanyarray(uu, dtype=np.float) #vv = np.asanyarray(vv, dtype=np.float) #lat = np.asanyarray(lat, dtype=np.float) #lon = np.asanyarray(lon, dtype=np.float) #z = np.asanyarray(z, dtype=np.float)/1000. #timestamp = np.asanyarray(timestamp, dtype=np.int64) - 2208988800 #uu_cor = wmm.velocity_correction(uu, vv, lat, lon, z, timestamp)[0] #return uu_cor #******** New Code ******** # calculate the magnetic declination using the WMM model mag_dec = magnetic_declination(lat, lon, timestamp, z) # rotate the vectors from the magnetic to the true compass frame magvar = np.vectorize(magnetic_correction) uu_cor, vv_cor = magvar(mag_dec, uu, vv) return uu_cor
def adcp_earth_northward(u, v, z, lat, lon, dt): """ Description: Wrapper function to compute the Northward Velocity Profile (VELPROF-VLN) from Earth coordinate transformed velocity profiles as defined in the Data Product Specification for Velocity Profile and Echo Intensity - DCN 1341-00750. Implemented by: 2013-04-10: Christopher Wingard. Initial code. 2014-02-03: Christopher Wingard. Formatting and adjusting to use magnetic declination values calculated use the WMM 2010. 2014-04-04: Russell Desiderio. Optimized code performance by replacing the for loops previously used to calculate 2D and 3D vectorized coordinate transformations with calls to np.einsum (numpy Einstein summation function). 2014-06-25: Christopher Wingard. Edited to account for units of heading, pitch, roll and depth Usage: vv_cor = adcp_earth_northward(u, v, z, lat, lon, dt) where vv_cor = northward velocity profiles in Earth coordinates corrected for the magnetic declination (VELPROF-VLN_L1) [m s-1] u = Eastward velocity profiles (VELPROF-VLE_L0) [mm s-1] v = Northward velocity profiles (VELPROF-VLN_L0) [mm s-1] z = instrument's pressure sensor reading (depth) [daPa] lat = instrument's deployment latitude [decimal degrees] lon = instrument's deployment longitude [decimal degrees] dt = sample date and time value [seconds since 1900-01-01] """ # force shapes of inputs to arrays u = np.atleast_2d(u) v = np.atleast_2d(v) z = np.atleast_1d(z) / 1000. # scale daPa depth input to dbar z = z * 1.019716 # use a simple approximation to calculate depth in m lat = np.atleast_1d(lat) lon = np.atleast_1d(lon) dt = np.atleast_1d(dt) # compute the magnetic variation, and ... theta = magnetic_declination(lat, lon, dt, z) # ... correct for it _, vv_cor = magnetic_correction(theta, u, v) # scale velocity to m/s vv_cor = vv_cor / 1000. # mm/s -> m/s # return the Northward Velocity Profile return vv_cor
def test_magnetic_correction(self): """ Performance test for the magnetic_correction function for the correcting vectors for magnetic declination, used in multiple data product algorithms. """ stats = [] theta = magnetic_declination(self.lat, self.lon, self.ts, 3) magcor = np.vectorize(magnetic_correction) self.profile(stats, magcor, theta, self.ve, self.vn)
def test_magnetic_correction(self): """ Performance test for the magnetic_correction function for the correcting vectors for magnetic declination, used in multiple data product algorithms. """ stats = [] theta = magnetic_declination(self.lat, self.lon, self.ts, 3) magcor = np.vectorize(magnetic_correction) self.profile(stats, magcor, theta, self.ve, self.vn)
def vel_mag_correction(uu, vv, lat, lon, timestamp, z, zflag=-1): """ Description: Magnetic declination correction for velocities referenced to magnetic North. Given the directional velocity components U and V, it finds the magnetic declination for the location, depth, and date, rotates the vectors from relative to magnetic North to true North. It should be called with the directional string to get an individual horizontal vector component. Implemented by: 2013-04-17: Stuart Pearce. Initial code. 2013-04-24: S.P. Changed to be general for all velocities Usage: vel_corr = vel_mag_correction(uu, vv, lat, lon, timestamp, z, dirstr='all') where vel_corr = The corrected velocity components [D/T]. A tuple of (uu_corr,vv_corr) is returned if dirstr == 'all'. uu = Uncorrected input eastward velocity [D/T] uu = Uncorrected input northward velocity [D/T] lat = Instrument latitude (North positive) [decimal degrees] lon = Instrument longitude (East positive) [decimal degrees] timestamp = The data timestamp (NTP timestamp format) [seconds since 1900-01-01] z = Instrument depth relative to sea level (positive values only) [meters]. dirstr = String of the direction for the requested component ('east','north','all'). The default is 'all'. References: OOI (2012). Data Product Specification for Turbulent Point Water Velocity. Document Control Number 1341-00781. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00781_Data_Product_SPEC_VELPTTU_Nobska_OOI.pdf) """ # retrieve magnetic declination theta = magnetic_declination(lat, lon, timestamp, z, zflag=-1) # correct the velocities for magnetic declination # the algorithm for Nobska & Nortek VELPTTU's are the same as # adcp_magvar magvar = np.vectorize(adcp_magvar) uu_cor, vv_cor = magvar(theta, uu, vv) return (uu_cor, vv_cor)
def adcp_earth_eastward(u, v, z, lat, lon, dt): """ Wrapper function to compute the Eastward Velocity Profile (VELPROF-VLE) from the Earth coordinate transformed data. """ # calculate the magnetic variation and correct the velocity profiles zflag = -1 # sets depth to negative for below sea surface zm = z / 10. # scale decimeter depth input to meters theta = magnetic_declination(lat, lon, dt, zm, zflag) u_cor, v_cor = adcp_magvar(theta, u, v) # scale eastward velocity from [mm s-1] to [m s-1] u_cor = u_cor / 1000. # return the Eastward Velocity Profile (VELPROF-VLE_L1) return u_cor
def wav_triaxys_correct_mean_wave_direction(dir_raw, lat, lon, ntp_ts): """ Description: Function to compute the WAVSTAT-D_L2 data product (mean wave direction corrected for magnetic declination) for the WAVSS instrument class (TRIAXYS Wave Sensor, manufactured by AXYS Technologies). Implemented by: 2014-04-08: Russell Desiderio. Initial code. Usage: dir_cor = wav_triaxys_correct_mean_wave_direction(dir_raw, lat, lon, ntp_ts) where dir_cor = mean wave direction corrected for magnetic declination (WAVSTAT-D_L2) [deg, [0 360)]. dir_raw = uncorrected mean wave direction (WAVSTAT-D_L0) [deg, [0 360)]. lat = latitude of the instrument [decimal degrees]. North is positive, South negative. lon = longitude of the instrument [decimal degrees]. East is positive, West negative. ntp_ts = NTP time stamp from a data particle [secs since 1900-01-01]. References: OOI (2012). Data Product Specification for Wave Statistics. Document Control Number 1341-00450. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00450_Data_Product_WAVE_STATISTICS_OOI.pdf) """ # calculate the magnetic declination using the WWM2010 model # the WAVSS is a surface wave sensor, so that height above sealevel = 0, # which is the default value used in the magnetic_declination calculation. theta = magnetic_declination(lat, lon, ntp_ts) # directions are [0,360) degrees; and magnetic declinations can be positive or negative dir_cor = np.mod(dir_raw + theta + 360, 360) # return corrected direction return dir_cor
def wav_triaxys_correct_mean_wave_direction(dir_raw, lat, lon, ntp_ts): """ Description: Function to compute the WAVSTAT-D_L2 data product (mean wave direction corrected for magnetic declination) for the WAVSS instrument class (TRIAXYS Wave Sensor, manufactured by AXYS Technologies). Implemented by: 2014-04-08: Russell Desiderio. Initial code. Usage: dir_cor = wav_triaxys_correct_mean_wave_direction(dir_raw, lat, lon, ntp_ts) where dir_cor = mean wave direction corrected for magnetic declination (WAVSTAT-D_L2) [deg, [0 360)]. dir_raw = uncorrected mean wave direction (WAVSTAT-D_L0) [deg, [0 360)]. lat = latitude of the instrument [decimal degrees]. North is positive, South negative. lon = longitude of the instrument [decimal degrees]. East is positive, West negative. ntp_ts = NTP time stamp from a data particle [secs since 1900-01-01]. References: OOI (2012). Data Product Specification for Wave Statistics. Document Control Number 1341-00450. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00450_Data_Product_WAVE_STATISTICS_OOI.pdf) """ # calculate the magnetic declination using the WWM2010 model # the WAVSS is a surface wave sensor, so that height above sealevel = 0, # which is the default value used in the magnetic_declination calculation. theta = magnetic_declination(lat, lon, ntp_ts) # directions are [0,360) degrees; and magnetic declinations can be positive or negative dir_cor = np.mod(dir_raw + theta + 360, 360) # return corrected direction return dir_cor
def adcp_beam_northward(b1, b2, b3, b4, h, p, r, vf, lat, lon, z, dt): """ Wrapper function to compute the Northward Velocity Profile (VELPROF-VLN) from the beam coordinate transformed data. """ # compute the beam to instrument transform u, v, w, e = adcp_beam2ins(b1, b2, b3, b4) # compute the instrument to earth beam transform uu, vv, ww = adcp_ins2earth(u, v, w, h, p, r, vf) # calculate the magnetic variation and correct the velocity profiles zflag = -1 # sets depth to negative for below sea surface zm = z / 10. # scale decimeter depth input to meters theta = magnetic_declination(lat, lon, dt, zm, zflag) uu_cor, vv_cor = adcp_magvar(theta, uu, vv) # scale northward velocity to m/s vv_cor = vv_cor/1000. # mm/s/1000 = m/s # return the Northward Velocity Profile return vv_cor
def adcp_beam_northward(b1, b2, b3, b4, h, p, r, vf, lat, lon, z, dt): """ Description: Wrapper function to compute the Eastward Velocity Profile (VELPROF-VLN) from beam coordinate transformed velocity profiles as defined in the Data Product Specification for Velocity Profile and Echo Intensity - DCN 1341-00750. Implemented by: 2013-04-10: Christopher Wingard. Initial code. 2014-02-03: Christopher Wingard. Formatting and adjusting to use magnetic declination values calulated use the WMM 2010. Usage: uu_cor = adcp_beam_eastward(b1, b2, b3, b4, h, p, r, vf, lat, lon, z, dt) where uu_corr = east velocity profiles in Earth coordinates corrected for the magnetic declination (VELPROF-VLE_L1) [mm s-1] b1 = "beam 1" velocity profiles in beam coordinates (VELPROF-B1_L0) [mm s-1] b2 = "beam 2" velocity profiles in beam coordinates (VELPROF-B2_L0) [mm s-1] b3 = "beam 3" velocity profiles in beam coordinates (VELPROF-B3_L0) [mm s-1] b4 = "beam 4" velocity profiles in beam coordinates (VELPROF-B4_L0) [mm s-1] h = instrument's uncorrected magnetic heading [degrees] p = instrument pitch [degrees] r = instrument roll [degrees] vf = instrument's vertical orientation (0 = downward looking and 1 = upward looking) lat = instrument's deployment latitude [decimal degrees] lon = instrument's deployment longitude [decimal degrees] z = instrument's pressure sensor reading (depth) [dm] dt = sample date and time value [seconds since 1900-01-01] """ # force shapes of inputs to arrays of the correct dimensions b1 = np.atleast_2d(b1) b2 = np.atleast_2d(b2) b3 = np.atleast_2d(b3) b4 = np.atleast_2d(b4) h = np.atleast_1d(h) p = np.atleast_1d(p) r = np.atleast_1d(r) vf = np.atleast_1d(vf) z = np.atleast_1d(z) / 10. # scale decimeter depth input to meters lat = np.atleast_1d(lat) lon = np.atleast_1d(lon) dt = np.atleast_1d(dt) # compute the beam to instrument transform u, v, w, e = adcp_beam2ins(b1, b2, b3, b4) # calculate the magnetic declination using the WWM2010 model theta = magnetic_declination(lat, lon, dt, z) # iterate through arrays for processing multiple records vv_cor = np.empty((b1.shape)) for indx in range(b1.shape[0]): # compute the instrument to earth beam transform uu, vv, ww = adcp_ins2earth(u[indx, :], v[indx, :], w[indx, :], h[indx], p[indx], r[indx], vf[indx]) # apply the magnetic variation correction ucor, vv_cor[indx, :] = magnetic_correction(theta[indx], uu, vv) # scale northward velocity to m/s vv_cor = vv_cor / 1000. # mm/s -> m/s # return the Northward Velocity Profile return vv_cor
def wav_triaxys_magcor_buoymotion_y(x, y, lat, lon, ntp_timestamp): """ Description: Function to compute the WAVSTAT-MOTY_L1 data product (northward buoy displacement) for the WAVSS instrument class (TRIAXYS Wave Sensor, manufactured by AXYS Technologies) from the WAVSTAT-MOTX_L0 and WAVSTAT-MOTY_L0 data products. All that is required is to correct for magnetic declination (variation). Implemented by: 2014-04-10: Russell Desiderio. Initial code. Uses magnetic declination values calculated using the WMM 2010 model. WAVSS is a surface sensor, so that the depth variable for calculating declination is 0 (default value for the magnetic_declination function). Usage: moty = wav_triaxys_magcor_buoymotion_y(x, y, lat, lon, dt) where moty = North displacement of the buoy on which the WAVSS is mounted, corrected for magnetic declination (WAVSTAT-MOTY_L1) [m] x = uncorrected eastward displacement (WAVSTAT-MOTX_L0) [m] y = uncorrected northward displacement (WAVSTAT-MOTY_L0) [m] lat = instrument's deployment latitude [decimal degrees] lon = instrument's deployment longitude [decimal degrees] ntp_timestamp = NTP time stamp corresponding to the date and time specified in the $TSPHA data sentence [secs since 1900-01-01]. Note as to the values of ntp_timestamp used in the calculation: See Note in Usage section of wav_triaxys_magcor_buoymotion_x. References: OOI (2012). Data Product Specification for Wave Statistics. Document Control Number 1341-00450. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00450_Data_Product_WAVE_STATISTICS_OOI.pdf) """ # force shapes of inputs to arrays x = np.atleast_2d(x) y = np.atleast_2d(y) lat = np.atleast_1d(lat) lon = np.atleast_1d(lon) ntp_timestamp = np.atleast_1d(ntp_timestamp) # calculate the magnetic declination using the WWM2010 model. # the WAVSS surface wave sensor is at sealevel, which is the default z value for mag dec. theta = magnetic_declination(lat, lon, ntp_timestamp) # correct for declination by rotating coordinates. # the function magnetic_correction_einsum was written to correct (u,v) velocities, but # it also applies to (E,N) coordinates. _, moty = magnetic_correction_einsum(theta, x, y) # return corrected Northward buoy displacement(s) return moty
def wav_triaxys_correct_directional_wave_direction(dir_raw, lat, lon, ntp_ts): """ FLAG: The numbers of values in the L0 and L2 data product WAVSTAT_DDS for each datapacket are determined by the values of the nfreq_dir variable, which can vary as a function of measured ocean conditions at fixed instrument setting. See also the FLAG note for function def wav_triaxys_dir_freq. Description: Function to compute the WAVSTAT-DDS_L2 data product (directional wave directions corrected for magnetic declination) for the WAVSS instrument class (TRIAXYS Wave Sensor, manufactured by AXYS Technologies). Implemented by: 2014-04-09: Russell Desiderio. Initial code. Usage: dir_cor = wav_triaxys_correct_directional_wave_direction(dir_raw, lat, lon, ntp_ts) where dir_cor = directional waves' directions corrected for magnetic declination (WAVSTAT-DDS_L2) [deg, [0 360)]. dir_raw = uncorrected directional waves' directions (WAVSTAT-DDS_L0) [deg, [0 360)]. lat = latitude of the instrument [decimal degrees]. North is positive, South negative. lon = longitude of the instrument [decimal degrees]. East is positive, West negative. ntp_ts = NTP time stamp from a data particle [secs since 1900-01-01]. References: OOI (2012). Data Product Specification for Wave Statistics. Document Control Number 1341-00450. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00450_Data_Product_WAVE_STATISTICS_OOI.pdf) """ # assume that the dir_raw data product comes in as a 2D numpy array with fill values # appropriately placed to account for the cases in which the number of reported # directional wave frequency bins differs from data packet to data packet (and is # less than the number of reported non-directional frequency bins). dir_raw = np.array(dir_raw, ndmin=2) # change fill values to Nans, so that subsequent array operations will leave the # Nan entries unchanged. dir_raw[dir_raw == fill_value] = np.nan # calculate the magnetic declination using the WWM2010 model # the WAVSS is a surface wave sensor, so that height above sealevel = 0, # which is the default value used in the magnetic_declination calculation. theta = magnetic_declination(lat, lon, ntp_ts) # theta in general will be a vector, so replicate it into a matrix to match the dir_raw dimensions. theta = np.tile(theta, (dir_raw.shape[1], 1)).transpose() # directions are [0,360) degrees; and magnetic declinations can be positive or negative dir_cor = np.mod(dir_raw + theta + 360, 360) # replace Nans with fills dir_cor[np.isnan(dir_cor)] = fill_value # return corrected directions return dir_cor
def vadcp_beam_northward(b1, b2, b3, b4, h, p, r, vf, lat, lon, z, dt): """ Description: Wrapper function to compute the Northward Velocity Profile (VELTURB-VLN) from beam coordinate transformed velocity profiles as defined in the Data Product Specification for Turbulent Velocity Profile and Echo Intensity - DCN 1341-00760. Implemented by: 2014-06-25: Christopher Wingard. Initial code, based on existing ADCP Usage: vv_cor = vadcp_beam_northward(b1, b2, b3, b4, h, p, r, vf, lat, lon, z, dt) where vv_cor = north velocity profiles in Earth coordinates corrected for the magnetic declination (VELTURB-VLN_L1) [m s-1] b1 = "beam 1" velocity profiles in beam coordinates (VELTURB-B1_L0) [mm s-1] b2 = "beam 2" velocity profiles in beam coordinates (VELTURB-B2_L0) [mm s-1] b3 = "beam 3" velocity profiles in beam coordinates (VELTURB-B3_L0) [mm s-1] b4 = "beam 4" velocity profiles in beam coordinates (VELTURB-B4_L0) [mm s-1] h = instrument's uncorrected magnetic heading [cdegrees] p = instrument pitch [cdegrees] r = instrument roll [cdegrees] vf = instrument's vertical orientation (0 = downward looking and 1 = upward looking) lat = instrument's deployment latitude [decimal degrees] lon = instrument's deployment longitude [decimal degrees] z = instrument's pressure sensor reading (depth) [dm] dt = sample date and time value [seconds since 1900-01-01] """ # force shapes of inputs to arrays of the correct dimensions b1 = np.atleast_2d(b1) b2 = np.atleast_2d(b2) b3 = np.atleast_2d(b3) b4 = np.atleast_2d(b4) h = np.atleast_1d(h) / 100. # scale cdegrees input to degrees p = np.atleast_1d(p) / 100. # scale cdegrees input to degrees r = np.atleast_1d(r) / 100. # scale cdegrees input to degrees vf = np.atleast_1d(vf) z = np.atleast_1d(z) / 1000. # scale daPa depth input to dbar z = z * 1.019716 # use a simple approximation to calculate depth in m lat = np.atleast_1d(lat) lon = np.atleast_1d(lon) dt = np.atleast_1d(dt) # compute the beam to instrument transform u, v, w, _ = adcp_beam2ins(b1, b2, b3, b4) # compute the instrument to earth beam transform uu, vv, _ = adcp_ins2earth(u, v, w, h, p, r, vf) # compute the magnetic variation, and ... theta = magnetic_declination(lat, lon, dt, z) # ... corect for it _, vv_cor = magnetic_correction(theta, uu, vv) # scale velocity to m/s vv_cor = vv_cor / 1000. # mm/s -> m/s # return the Northward Velocity Profile return vv_cor
def wav_triaxys_correct_directional_wave_direction(dir_raw, lat, lon, ntp_ts): """ FLAG: The numbers of values in the L0 and L2 data product WAVSTAT_DDS for each datapacket are determined by the values of the nfreq_dir variable, which can vary as a function of measured ocean conditions at fixed instrument setting. See also the FLAG note for function def wav_triaxys_dir_freq. Description: Function to compute the WAVSTAT-DDS_L2 data product (directional wave directions corrected for magnetic declination) for the WAVSS instrument class (TRIAXYS Wave Sensor, manufactured by AXYS Technologies). Implemented by: 2014-04-09: Russell Desiderio. Initial code. Usage: dir_cor = wav_triaxys_correct_directional_wave_direction(dir_raw, lat, lon, ntp_ts) where dir_cor = directional waves' directions corrected for magnetic declination (WAVSTAT-DDS_L2) [deg, [0 360)]. dir_raw = uncorrected directional waves' directions (WAVSTAT-DDS_L0) [deg, [0 360)]. lat = latitude of the instrument [decimal degrees]. North is positive, South negative. lon = longitude of the instrument [decimal degrees]. East is positive, West negative. ntp_ts = NTP time stamp from a data particle [secs since 1900-01-01]. References: OOI (2012). Data Product Specification for Wave Statistics. Document Control Number 1341-00450. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00450_Data_Product_WAVE_STATISTICS_OOI.pdf) """ # assume that the dir_raw data product comes in as a 2D numpy array with fill values # appropriately placed to account for the cases in which the number of reported # directional wave frequency bins differs from data packet to data packet (and is # less than the number of reported non-directional frequency bins). dir_raw = np.array(dir_raw, ndmin=2) # change fill values to Nans, so that subsequent array operations will leave the # Nan entries unchanged. dir_raw[dir_raw == fill_value] = np.nan # calculate the magnetic declination using the WWM2010 model # the WAVSS is a surface wave sensor, so that height above sealevel = 0, # which is the default value used in the magnetic_declination calculation. theta = magnetic_declination(lat, lon, ntp_ts) # theta in general will be a vector, so replicate it into a matrix to match the dir_raw dimensions. theta = np.tile(theta, (dir_raw.shape[1], 1)).transpose() # directions are [0,360) degrees; and magnetic declinations can be positive or negative dir_cor = np.mod(dir_raw + theta + 360, 360) # replace Nans with fills dir_cor[np.isnan(dir_cor)] = fill_value # return corrected directions return dir_cor
def adcp_beam_northward(b1, b2, b3, b4, h, p, r, vf, lat, lon, z, dt): """ Description: Wrapper function to compute the Northward Velocity Profile (VELPROF-VLN) from beam coordinate transformed velocity profiles as defined in the Data Product Specification for Velocity Profile and Echo Intensity - DCN 1341-00750. Implemented by: 2013-04-10: Christopher Wingard. Initial code. 2014-02-03: Christopher Wingard. Formatting and adjusting to use magnetic declination values calculated use the WMM 2010. 2014-03-28: Russell Desiderio. Corrected documentation only. 2014-04-04: Russell Desiderio. Optimized code performance by replacing the for loops previously used to calculate 2D and 3D vectorized coordinate transformations with calls to np.einsum (numpy Einstein summation function). 2014-06-25: Christopher Wingard. Edited to account for units of heading, pitch, roll and depth Usage: vv_cor = adcp_beam_northward(b1, b2, b3, b4, h, p, r, vf, lat, lon, z, dt) where vv_corr = north velocity profiles in Earth coordinates corrected for the magnetic declination (VELPROF-VLN_L1) [m s-1] b1 = "beam 1" velocity profiles in beam coordinates (VELPROF-B1_L0) [mm s-1] b2 = "beam 2" velocity profiles in beam coordinates (VELPROF-B2_L0) [mm s-1] b3 = "beam 3" velocity profiles in beam coordinates (VELPROF-B3_L0) [mm s-1] b4 = "beam 4" velocity profiles in beam coordinates (VELPROF-B4_L0) [mm s-1] h = instrument's uncorrected magnetic heading [cdegrees] p = instrument pitch [cdegrees] r = instrument roll [cdegrees] vf = instrument's vertical orientation (0 = downward looking and 1 = upward looking) lat = instrument's deployment latitude [decimal degrees] lon = instrument's deployment longitude [decimal degrees] z = instrument's pressure sensor reading (depth) [daPa] dt = sample date and time value [seconds since 1900-01-01] """ # force shapes of inputs to arrays of the correct dimensions b1 = np.atleast_2d(b1) b2 = np.atleast_2d(b2) b3 = np.atleast_2d(b3) b4 = np.atleast_2d(b4) h = np.atleast_1d(h) / 100. # scale cdegrees input to degrees p = np.atleast_1d(p) / 100. # scale cdegrees input to degrees r = np.atleast_1d(r) / 100. # scale cdegrees input to degrees vf = np.atleast_1d(vf) z = np.atleast_1d(z) / 1000. # scale daPa depth input to dbar z = z * 1.019716 # use a simple approximation to calculate depth in m lat = np.atleast_1d(lat) lon = np.atleast_1d(lon) dt = np.atleast_1d(dt) # compute the beam to instrument transform u, v, w, _ = adcp_beam2ins(b1, b2, b3, b4) # compute the instrument to earth beam transform uu, vv, _ = adcp_ins2earth(u, v, w, h, p, r, vf) # compute the magnetic variation, and ... theta = magnetic_declination(lat, lon, dt, z) # ... correct for it _, vv_cor = magnetic_correction(theta, uu, vv) # scale velocity to m/s vv_cor = vv_cor / 1000. # mm/s -> m/s # return the Northward Velocity Profile return vv_cor
def wav_triaxys_magcor_buoymotion_y(x, y, lat, lon, ntp_timestamp): """ Description: Function to compute the WAVSTAT-MOTY_L1 data product (northward buoy displacement) for the WAVSS instrument class (TRIAXYS Wave Sensor, manufactured by AXYS Technologies) from the WAVSTAT-MOTX_L0 and WAVSTAT-MOTY_L0 data products. All that is required is to correct for magnetic declination (variation). Implemented by: 2014-04-10: Russell Desiderio. Initial code. Uses magnetic declination values calculated using the WMM 2010 model. WAVSS is a surface sensor, so that the depth variable for calculating declination is 0 (default value for the magnetic_declination function). Usage: moty = wav_triaxys_magcor_buoymotion_y(x, y, lat, lon, dt) where moty = North displacement of the buoy on which the WAVSS is mounted, corrected for magnetic declination (WAVSTAT-MOTY_L1) [m] x = uncorrected eastward displacement (WAVSTAT-MOTX_L0) [m] y = uncorrected northward displacement (WAVSTAT-MOTY_L0) [m] lat = instrument's deployment latitude [decimal degrees] lon = instrument's deployment longitude [decimal degrees] ntp_timestamp = NTP time stamp corresponding to the date and time specified in the $TSPHA data sentence [secs since 1900-01-01]. Note as to the values of ntp_timestamp used in the calculation: See Note in Usage section of wav_triaxys_magcor_buoymotion_x. References: OOI (2012). Data Product Specification for Wave Statistics. Document Control Number 1341-00450. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00450_Data_Product_WAVE_STATISTICS_OOI.pdf) """ # force shapes of inputs to arrays x = np.atleast_2d(x) y = np.atleast_2d(y) lat = np.atleast_1d(lat) lon = np.atleast_1d(lon) ntp_timestamp = np.atleast_1d(ntp_timestamp) # calculate the magnetic declination using the WWM2010 model. # the WAVSS surface wave sensor is at sealevel, which is the default z value for mag dec. theta = magnetic_declination(lat, lon, ntp_timestamp) # correct for declination by rotating coordinates. # the function magnetic_correction_einsum was written to correct (u,v) velocities, but # it also applies to (E,N) coordinates. _, moty = magnetic_correction_einsum(theta, x, y) # return corrected Northward buoy displacement(s) return moty
def vel_mag_correction(u, v, lat, lon, ntp_timestamp, z=0.0, zflag=-1): """ Description: Given a velocity vector U, measured in a sensor frame that is referenced to Earth's magnetic field, with components u & v in the magnetic East and magnetic North directions respectively; vel_mag_correction transforms U to true Earth referenced directions by a rotation that removes the magnetic declination. Magnetic Declination, theta(x,y,z,t), is the azimuthal angular offset between true North and magnetic North as a function of Earth referenced location (latitude, longitude, & height/depth) and time. Magnetic declination is estimated from the World Magnetic Model (WMM) using the location and time of the vector. Usage: u_cor, v_cor = vel_mag_correction(u, v, lat, lon, ntp_timestamp, z, zflag) where u_cor = eastward velocity, in true Earth frame, with the correction for magnetic declination applied. v_cor = northward velocity, in true Earth frame, with the correction for magnetic declination applied. u = uncorrected eastward velocity in magnetic Earth frame. v = uncorrected northward velocity in magnetic Earth frame. lat = latitude of the instrument [decimal degrees]. East is positive, West negative. lon = longitude of the instrument [decimal degrees]. North is positive, South negative. ntp_timestamp = NTP time stamp from a data particle [secs since 1900-01-01]. z = depth or height of instrument relative to sealevel [meters]. Positive values only. Default value is 0. zflag = indicates whether to use z as a depth or height relative to sealevel. -1=depth (i.e. -z) and 1=height (i.e. +z). -1 is the default, because Oceanography! Implemented by: 2013-04-17: Stuart Pearce. Initial code. 2013-04-24: Stuart Pearce. Changed to be general for all velocity instruments. 2014-02-05: Christopher Wingard. Edited to use magnetic corrections in the generic_functions module. References: OOI (2012). Data Product Specification for Turbulent Point Water Velocity. Document Control Number 1341-00781. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00781_Data_Product_SPEC_VELPTTU_Nobska_OOI.pdf) OOI (2012). Data Product Specification for Turbulent Point Water Velocity. Document Control Number 1341-00780. https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >> Controlled >> 1000 System Level >> 1341-00780_Data_Product_SPEC_VELPTTU_Nortek_OOI.pdf) """ # retrieve the magnetic declination theta = magnetic_declination(lat, lon, ntp_timestamp, z, zflag) # apply the magnetic declination correction magvar = np.vectorize(magnetic_correction) u_cor, v_cor = magvar(theta, u, v) return u_cor, v_cor