Permalink
Fetching contributors…
Cannot retrieve contributors at this time
2039 lines (1587 sloc) 85.7 KB
#!/usr/bin/env python
"""
@package ion_functions.data.vel_functions
@file ion_functions/data/vel_functions.py
@author Stuart Pearce, Russell Desiderio
@brief Module containing velocity family instrument related functions
"""
import numpy as np
import numexpr as ne
from numpy import sin, cos, radians
from ion_functions.data.generic_functions import magnetic_declination, magnetic_correction
# NOTE:
# The previous version of this module had each function return an
# array of all fill values (-9999) if the lat or lon is invalid. This
# should not occur. Really lat and lon should be checked and handled
# in the QAQC functions, and only apply a fill value for the single
# instance of invalid lat & lon rather than the whole array. I
# believe they were coded here for testing purposes. The part that
# returned the fill values now instead just raises the ValueError
# exception.
# -Stuart Pearce
# (this message should be removed if/when the lats & lons
# are checked in the QAQC functions)
from exceptions import ValueError
### Constants (VEL3D-K) ###
# XYZ_TRANSFORMS is a dictionary constant that is generated when the
# module is first imported. XYZ_TRANSFORMS is generated by the
# generate_beam_transforms function and must be created after the
# function is declared. Therefore XYZ_TRANSFORMS is not here in the
# constants section. See line 1649.
"""
Order of functions in this module
Functions that directly calculate data products:
fsi_acm_rsn_east -- calculates VELPTMN-VLE_L1 from VEL3D-A
fsi_acm_rsn_north -- calculates VELPTMN-VLN_L1 from VEL3D-A
fsi_acm_sio_east -- calculates VELPTMN-VLE_L1 from VEL3D-L
fsi_acm_sio_north -- calculates VELPTMN-VLN_L1 from VEL3D-L
fsi_acm_up_profiler_ascending -- calculates VELPTMN-VLU-ASC_L1 from VEL3D-AL
fsi_acm_up_profiler_descending -- calculates VELPTMN-VLU-DSC_L1 from VEL3D-AL
nobska_mag_corr_east -- calculates VELPTTU-VLE_L1 from VEL3D-B
nobska_mag_corr_north -- calculates VELPTTU-VLN_L1 from VEL3D-B
nobska_scale_up_vel -- calculates VELPTTU-VLU_L1 from VEL3D-B
nortek_mag_corr_east -- calculates VELPTTU-VLE_L1 from VEL3D-CD
nortek_mag_corr_north -- calculates VELPTTU-VLN_L1 from VEL3D-CD
nortek_up_vel -- calculates VELPTTU-VLU_L1 from VEL3D-CD
vel3dk_east -- calculates VELPTTU-VLE_L1 from VEL3D-K
vel3dk_north -- calculates VELPTTU-VLN_L1 from VEL3D-K
vel3dk_up -- calculates VELPTTU-VLU_L1 from VEL3D-K
velpt_mag_corr_east -- calculates VELPTMN-VLE_L1 from VELPT-ABDJ
velpt_mag_corr_north -- calculates VELPTMN-VLN_L1 from VELPT-ABDJ
velpt_up_vel -- calculates VELPTMN-VLU_L1 from VELPT-ABDJ
Subfunctions:
fsi_acm_horz_vel -- used by vel3d-a,l
fsi_acm_nautical_heading -- used by vel3d-a
fsi_acm_compass_cal -- used by vel3d-a
generate_beam_transforms -- used by vel3d-k
get_XYZ_transform -- used by vel3d-k
generate_ENU_transform -- used by vel3d-k
vel3dk_transform -- used by vel3d-k
vel_mag_correction -- used by most of the horz vel fns
Helper sub-functions:
valid_lat
valid_lon
"""
# wrapper functions for use in ION
def fsi_acm_rsn_east(vp1, vp3, hx, hy, hdg_cal, hx_cal, hy_cal, lat, lon, timestamp):
"""
Description:
Calculates the VEL3D Series A eastwards velocity data product VELPTMN-VLE_L1
for the Falmouth Scientific (FSI) Acoustic Current Meter (ACM) mounted on a McLane
profiler as deployed by RSN. The horizontal velocities are corrected for magnetic
declination.
Usage:
u = fsi_acm_rsn_east(vp1, vp3, hx, hy, hdg_cal, hx_cal, hy_cal, lat, lon, timestamp)
where
u = eastwards velocity VELPTMN-VLE_L1 [m/s]
vp1 = raw beam velocity from the port stinger finger; VELPTMN-VP1_L0 [cm/s]
vp3 = raw beam velocity from the starboard stinger finger; VELPTMN-VP3_L0 [cm/s]
hx = direction cosine of magnetic field projected onto the instrument x-axis;
VELPTMN-HXX_L0
hy = direction cosine of magnetic field projected onto the instrument y-axis;
VELPTMN-HYY_L0
hdg_cal = 8-element vector of reference ACM headings from a compass calibration
spin test. heading convention: nautical [degrees clockwise from magnetic north].
see Notes.
hx_cal = 8-element vector of direction cosines of the magnetic field projected along
the instrument x-axis acquired during a compass calibration spin test.
hy_cal = 8-element vector of direction cosines of the magnetic field projected along
the instrument y-axis acquired during a compass calibration spin test.
lat = latitude of the instrument [decimal degrees]. East is positive, West negative.
lon = longitude of the instrument [decimal degrees]. North is positive, South negative.
timestamp = NTP time stamp from a data particle [secs since 1900-01-01].
Implemented by:
2015-02-13: Russell Desiderio. Initial code.
2015-05-29: Russell Desiderio. Time-vectorized calcoeffs by removing exception checking of the
lengths of calcoeff arrays. This is now done by checking the
shapes of these variables in the fsi_acm_compass_cal routine
which is called by fsi_acm_nautical_heading.
Notes:
The VEL3D series A and L instruments are FSI current meters modified for use on a
McLane profiler. The FSI ACM has 4 raw beam velocities. The correspondences between
the MMP manual designations and the IDD designations are:
(Xplus, Yplus, Xminus, Yminus) (MMP manual, page G-22)
(va , vb , vc , vd ) (IDD, VEL3D series A)
(vp1 , vp2 , vp3 , vp4 ) (IDD, VEL3D series L)
(left , down , right , up ) (spatial orientation)
This is also the ordering of these parameters in telemetered and recovered data.
SERIES A instruments are deployed by RSN. Compass calibrations from a spin test as
described in the MMP manual are used to correct field compass direction cosine
measurements so that headings can be calculated for the field data.
For more information see the Notes to worker function fsi_acm_horz_vel.
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf)
"""
# calculate the headings from the field direction cosines hx and hy and the cal data.
hdg = fsi_acm_nautical_heading(hx, hy, hdg_cal, hx_cal, hy_cal)
# call the worker function which calculates both the east and north data products
(u, _) = fsi_acm_horz_vel(vp1, vp3, hdg, lat, lon, timestamp)
return u
def fsi_acm_rsn_north(vp1, vp3, hx, hy, hdg_cal, hx_cal, hy_cal, lat, lon, timestamp):
"""
Description:
Calculates the VEL3D Series A northwards velocity data product VELPTMN-VLN_L1
for the Falmouth Scientific (FSI) Acoustic Current Meter (ACM) mounted on a McLane
profiler as deployed by RSN. The horizontal velocities are corrected for magnetic
declination.
Usage:
v = fsi_acm_rsn_north(vp1, vp3, hx, hy, hdg_cal, hx_cal, hy_cal, lat, lon, timestamp)
where
v = northwards velocity VELPTMN-VLN_L1 [m/s]
vp1 = raw beam velocity from the port stinger finger; VELPTMN-VP1_L0 [cm/s]
vp3 = raw beam velocity from the starboard stinger finger; VELPTMN-VP3_L0 [cm/s]
hx = direction cosine of magnetic field projected onto the instrument x-axis;
VELPTMN-HXX_L0
hy = direction cosine of magnetic field projected onto the instrument y-axis;
VELPTMN-HYY_L0
hdg_cal = 8-element vector of reference ACM headings from a compass calibration
spin test. heading convention: nautical [degrees clockwise from magnetic north].
see Notes.
hx_cal = 8-element vector of direction cosines of the magnetic field projected along
the instrument x-axis acquired during a compass calibration spin test.
hy_cal = 8-element vector of direction cosines of the magnetic field projected along
the instrument y-axis acquired during a compass calibration spin test.
lat = latitude of the instrument [decimal degrees]. East is positive, West negative.
lon = longitude of the instrument [decimal degrees]. North is positive, South negative.
timestamp = NTP time stamp from a data particle [secs since 1900-01-01].
Implemented by:
2015-02-13: Russell Desiderio. Initial code.
2015-05-29: Russell Desiderio. Time-vectorized calcoeffs by removing exception checking of the
lengths of calcoeff arrays. This is now done by checking the
shapes of these variables in the fsi_acm_compass_cal routine
which is called by fsi_acm_nautical_heading.
Notes:
The VEL3D series A and L instruments are FSI current meters modified for use on a
McLane profiler. The FSI ACM has 4 raw beam velocities. The correspondences between
the MMP manual designations and the IDD designations are:
(Xplus, Yplus, Xminus, Yminus) (MMP manual, page G-22)
(va , vb , vc , vd ) (IDD, VEL3D series A)
(vp1 , vp2 , vp3 , vp4 ) (IDD, VEL3D series L)
(left , down , right , up ) (spatial orientation)
This is also the ordering of these parameters in telemetered and recovered data.
SERIES A instruments are deployed by RSN. Compass calibrations from a spin test as
described in the MMP manual are used to correct field compass direction cosine
measurements so that headings can be calculated for the field data.
For more information see the Notes to worker function fsi_acm_horz_vel.
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf)
"""
# calculate the headings from the field direction cosines hx and hy and the cal data.
hdg = fsi_acm_nautical_heading(hx, hy, hdg_cal, hx_cal, hy_cal)
# call the worker function which calculates both the east and north data products
(_, v) = fsi_acm_horz_vel(vp1, vp3, hdg, lat, lon, timestamp)
return v
def fsi_acm_sio_east(vp1, vp3, hdg, lat, lon, timestamp):
"""
Description:
Calculates the VEL3D Series L eastwards velocity data product VELPTMN-VLE_L1
for the Falmouth Scientific (FSI) Acoustic Current Meter (ACM) mounted on a McLane
profiler as deployed by Scripps. Horizontal velocities are corrected for magnetic
variation.
Usage:
u = fsi_acm_sio_east(vp1, vp3, hdg, lat, lon, timestamp)
where
u = eastwards velocity VELPTMN-VLE_L1 [m/s]
vp1 = raw beam velocity from the port stinger finger; VELPTMN-VP1_L0 [cm/s]
vp3 = raw beam velocity from the starboard stinger finger; VELPTMN-VP3_L0 [cm/s]
hdg = ACM heading as reported by the instrument [degrees clockwise from
magnetic north]; VELPTMN-HDG_L0. see Notes.
lat = latitude of the instrument [decimal degrees]. East is positive, West negative.
lon = longitude of the instrument [decimal degrees]. North is positive, South negative.
timestamp = NTP time stamp from a data particle [secs since 1900-01-01].
Implemented by:
2015-02-18: Russell Desiderio. Initial code.
Notes:
The VEL3D series A and L instruments are FSI current meters modified for use on a
McLane profiler. The FSI ACM has 4 raw beam velocities. The correspondences between
the MMP manual designations and the IDD designations are:
(Xplus, Yplus, Xminus, Yminus) (MMP manual, page G-22)
(va , vb , vc , vd ) (IDD, VEL3D series A)
(vp1 , vp2 , vp3 , vp4 ) (IDD, VEL3D series L)
(left , down , right , up ) (spatial orientation)
This is also the ordering of these parameters in telemetered and recovered data.
SERIES L instruments are deployed by Scripps. Compass calibrations are not used to
correct field compass measurements from these instruments.
For more information see the Notes to worker function fsi_acm_horz_vel.
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf)
"""
# call the worker function which calculates both the east and north data products
(u, _) = fsi_acm_horz_vel(vp1, vp3, hdg, lat, lon, timestamp)
return u
def fsi_acm_sio_north(vp1, vp3, hdg, lat, lon, timestamp):
"""
Description:
Calculates the VEL3D Series L northwards velocity data product VELPTMN-VLN_L1
for the Falmouth Scientific (FSI) Acoustic Current Meter (ACM) mounted on a McLane
profiler as deployed by Scripps. Horizontal velocities are corrected for magnetic
variation.
Usage:
v = fsi_acm_sio_north(vp1, vp3, hdg, lat, lon, timestamp)
where
v = northwards velocity VELPTMN-VLN_L1 [m/s]
vp1 = raw beam velocity from the port stinger finger; VELPTMN-VP1_L0 [cm/s]
vp3 = raw beam velocity from the starboard stinger finger; VELPTMN-VP3_L0 [cm/s]
hdg = ACM heading as reported by the instrument [degrees clockwise from
magnetic north]; VELPTMN-HDG_L0. see Notes.
lat = latitude of the instrument [decimal degrees]. East is positive, West negative.
lon = longitude of the instrument [decimal degrees]. North is positive, South negative.
timestamp = NTP time stamp from a data particle [secs since 1900-01-01].
Implemented by:
2015-02-18: Russell Desiderio. Initial code.
Notes:
The VEL3D series A and L instruments are FSI current meters modified for use on a
McLane profiler. The FSI ACM has 4 raw beam velocities. The correspondences between
the MMP manual designations and the IDD designations are:
(Xplus, Yplus, Xminus, Yminus) (MMP manual, page G-22)
(va , vb , vc , vd ) (IDD, VEL3D series A)
(vp1 , vp2 , vp3 , vp4 ) (IDD, VEL3D series L)
(left , down , right , up ) (spatial orientation)
This is also the ordering of these parameters in telemetered and recovered data.
SERIES L instruments are deployed by Scripps. Compass calibrations are not used to
correct field compass measurements from these instruments.
For more information see the Notes to worker function fsi_acm_horz_vel.
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf)
"""
# call the worker function which calculates both the east and north data products
(_, v) = fsi_acm_horz_vel(vp1, vp3, hdg, lat, lon, timestamp)
return v
def fsi_acm_up_profiler_ascending(vp1, vp3, vp4):
"""
Description:
Calculates the VEL3D Series A and L upward velocity data product VELPTMN-VLU-ASC_L1
for the Falmouth Scientific (FSI) Acoustic Current Meter (ACM) mounted on a McLane
profiler.
Because of the orientation of the ACM stinger fingers (see Notes) upward
current velocity can be calculated in several different ways. This function
calculates the vertical velocity to be used when the profiler is ascending,
avoiding the use of data from vp2 which will be contaminated by the sheet-flow
wake of the stinger's central post.
Usage:
w_fsi_asc = fsi_acm_up_profiler_ascending(vp1, vp3, vp4)
where
w_fsi_asc = velocity up; VELPTMN-VLU-ASC_L1 [m/s]
vp1 = raw beam velocity from the port stinger finger; VELPTMN-VP1_L0 [cm/s]
vp3 = raw beam velocity from the starboard stinger finger; VELPTMN-VP3_L0 [cm/s]
vp4 = raw beam velocity from the upper stinger finger; VELPTMN-VP4_L0 [cm/s]
Implemented by:
2015-02-13: Russell Desiderio. Initial code.
Notes:
The VEL3D series A and L instruments are FSI current meters modified for use on a
McLane profiler. The FSI ACM has 4 raw beam velocities. The correspondences between
the MMP manual designations and the IDD designations are:
(Xplus, Yplus, Xminus, Yminus) (MMP manual, page G-22)
(va , vb , vc , vd ) (IDD, VEL3D series A)
(vp1 , vp2 , vp3 , vp4 ) (IDD, VEL3D series L)
(left , down , right , up ) (spatial orientation)
This is also the ordering of these parameters in telemetered and recovered data.
The MMP manual Rev E, page 8-30, incorrectly calculates the upward velocities wU and wD.
For more information see the Notes to worker function fsi_acm_horz_vel.
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf)
"""
# find the x-velocity in the instrument coordinate system
x = -(vp1 + vp3) / np.sqrt(2.0)
# the z-velocity in the instrument coordinate system is also the w velocity in the
# earth coordinate system because the effects of pitch and roll are negligible.
w = x - np.sqrt(2.0) * vp4
# change units from cm/s to m/s
return w / 100.0
def fsi_acm_up_profiler_descending(vp1, vp2, vp3):
"""
Description:
Calculates the VEL3D Series A and L upwards velocity data product VELPTMN-VLU-DSC_L1
for the Falmouth Scientific (FSI) Acoustic Current Meter (ACM) mounted on a McLane
profiler.
Because of the orientation of the ACM stinger fingers (see Notes) upward
current velocity can be calculated in several different ways. This function
calculates the vertical velocity to be used when the profiler is descending,
avoiding the use of data from vp4 which will be contaminated by the sheet-flow
wake of the stinger's central post.
Usage:
w_fsi_dsc = fsi_acm_up_profiler_descending(vp1, vp2, vp3)
where
w_fsi_dsc = velocity up; VELPTMN-VLU-DSC_L1 [m/s]
vp1 = raw beam velocity from the port stinger finger; VELPTMN-VP1_L0 [cm/s]
vp2 = raw beam velocity from the lower stinger finger; VELPTMN-VP2_L0 [cm/s]
vp3 = raw beam velocity from the starboard stinger finger; VELPTMN-VP3_L0 [cm/s]
Implemented by:
2015-02-13: Russell Desiderio. Initial code.
Notes:
The VEL3D series A and L instruments are FSI current meters modified for use on a
McLane profiler. The FSI ACM has 4 raw beam velocities. The correspondences between
the MMP manual designations and the IDD designations are:
(Xplus, Yplus, Xminus, Yminus) (MMP manual, page G-22)
(va , vb , vc , vd ) (IDD, VEL3D series A)
(vp1 , vp2 , vp3 , vp4 ) (IDD, VEL3D series L)
(left , down , right , up ) (spatial orientation)
This is also the ordering of these parameters in telemetered and recovered data.
The MMP manual Rev E, page 8-30, incorrectly calculates the upward velocities wU and wD.
For more information see the Notes to worker function fsi_acm_horz_vel.
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf)
"""
# find the x-velocity in the instrument coordinate system
x = -(vp1 + vp3) / np.sqrt(2.0)
# the z-velocity in the instrument coordinate system is also the w velocity in the
# earth coordinate system because the effects of pitch and roll are negligible.
w = -x + np.sqrt(2.0) * vp2
# change units from cm/s to m/s
return w / 100.0
def nobska_mag_corr_east(u, v, lat, lon, timestamp, z=0):
"""
Description:
Corrects the eastward velocity from a VEL3D-B Nobska MAVS 4
instrument for magnetic declination to produce an L1 VELPTTU-VLE
OOI data product.
Given a velocity vector with components u & v in the magnetic East
and magnetic North directions respectively, this function calculates
the magnetic declination for the location, depth, and time of the
vector from the World Magnetic Model (WMM) and transforms the vector
to a true Earth reference frame.
This function is a wrapper around the function "vel_mag_correction".
Usage:
u_cor = nobska_mag_corr_east(u, v, lat, lon, ntp_timestamp, z=0)
where
u_cor = eastward velocity VELPTTU-VLE_L1, in true Earth frame,
with the correction for magnetic declination applied. [m/s]
u = uncorrected eastward velocity in magnetic Earth frame. [cm/s]
v = uncorrected northward velocity in magnetic Earth frame. [cm/s]
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 of instrument relative to sea level [meters].
Positive values only. Default value is 0.
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)
"""
# Check for valid latitudes & longitudes
if not valid_lat(lat) or not valid_lon(lon):
# commented out next line according to NOTE above. -SP
#return np.ones(u.shape, dtype=np.float) * -9999
raise ValueError('Latitudes or Longitudes are not within the valid range!')
# correct for magnetic declination
u_cor = vel_mag_correction(u, v, lat, lon, timestamp, z)[0]
u_cor = ne.evaluate('u_cor / 100.') # convert from cm/s to m/s
# return true compass referenced East velocity in m/s
return u_cor
def nobska_mag_corr_north(u, v, lat, lon, timestamp, z=0):
"""
Description:
Corrects the northward velocity from a VEL3D-B Nobska MAVS 4
instrument for magnetic declination to produce an L1 VELPTTU-VLN
OOI data product.
Given a velocity vector with components u & v in the magnetic East
and magnetic North directions respectively, this function calculates
the magnetic declination for the location, depth, and time of the
vector from the World Magnetic Model (WMM) and transforms the vector
to a true Earth reference frame.
This function is a wrapper around the function "vel_mag_correction".
Usage:
v_cor = nobska_mag_corr_north(u, v, lat, lon, ntp_timestamp, z)
where
v_cor = northward velocity VELPTTU-VLN_L1, in true Earth frame,
with the correction for magnetic declination applied. [m/s]
u = uncorrected eastward velocity in magnetic Earth frame. [cm/s]
v = uncorrected northward velocity in magnetic Earth frame. [cm/s]
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 of instrument relative to sealevel [meters].
Positive values only. Default value is 0.
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)
"""
# check for valid latitudes & longitudes
if not valid_lat(lat) or not valid_lon(lon):
# commented out next line according to NOTE above. -SP
#return np.ones(u.shape, dtype=np.float) * -9999
raise ValueError('Latitudes or Longitudes are not within the valid range!')
# correct for magnetic declination
v_cor = vel_mag_correction(u, v, lat, lon, timestamp, z)[1]
v_cor = ne.evaluate('v_cor / 100.') # convert from cm/s to m/s
# return true compass referenced North velocity in m/s
return v_cor
def nobska_scale_up_vel(w):
"""
Description:
Computes the VELPTTU-VLU_L1 data product from a VEL3D-B Nobska MAVS-4 by converting
the units of the raw velocity vertical velocity measurement from cm/s to m/s.
Usage:
w_mps = nobska_scale_up_vel(w_cmps)
where
w_mps = Output vertical velocity VELPTTU-VLU_L1 [m/s]
w_cmps = Input vertical velocity [cm/s]
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)
"""
return w / 100.0
def nortek_mag_corr_east(u, v, lat, lon, timestamp, z=0.0):
"""
Description:
Corrects the eastward velocity from VEL3D-CD Nortek Vector instruments for
magnetic declination to produce an L1 VELPTTU-VLE OOI data product.
Given a velocity vector with components u & v in the magnetic East
and magnetic North directions respectively, this function calculates
the magnetic declination for the location, depth, and time of the
vector from the World Magnetic Model (WMM) and transforms the vector
to a true Earth reference frame.
This function is a wrapper around the function "vel_mag_correction".
Usage:
u_cor = nortek_mag_corr_east(u, v, lat, lon, ntp_timestamp, z)
where
u_cor = eastward velocity VELPTTU-VLE_L1, in true Earth frame,
with the correction for magnetic declination applied. [m/s]
u = uncorrected eastward velocity in magnetic Earth frame. [mm/s]
v = uncorrected northward velocity in magnetic Earth frame. [mm/s]
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 of instrument relative to sealevel [meters].
Positive values only. Default value is 0.
2015-06-08: Russell Desiderio. Changed DPA to reflect correct units
of input velocities. see Notes.
Notes:
As of 2015-06-08, the DPS referenced below is still incorrect:
the Nortek Vector outputs its velocities in units of mm/sec.
References:
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)
"""
# check for valid latitudes & longitudes
if not valid_lat(lat) or not valid_lon(lon):
# commented out next line according to NOTE above. -SP
#return np.ones(u.shape, dtype=np.float) * -9999
raise ValueError('Latitudes or Longitudes are not within the valid range!')
# change the units of the input velocities from mm/sec (see Notes) to m/sec
u = u / 1000.0
v = v / 1000.0
# correct for magnetic declination
u_cor = vel_mag_correction(u, v, lat, lon, timestamp, z)[0]
# return true compass referenced East velocity in m/s
return u_cor
def nortek_mag_corr_north(u, v, lat, lon, timestamp, z=0.0):
"""
Description:
Corrects the northward velocity from VEL3D-CD Nortek Vector instruments for
magnetic declination to produce an L1 VELPTTU-VLN OOI data product.
Given a velocity vector with components u & v in the magnetic East
and magnetic North directions respectively, this function calculates
the magnetic declination for the location, depth, and time of the
vector from the World Magnetic Model (WMM) and transforms the vector
to a true Earth reference frame.
This function is a wrapper around the function "vel_mag_correction".
Usage:
v_cor = nortek_mag_corr_north(u, v, lat, lon, ntp_timestamp, z)
where
v_cor = northward velocity VELPTTU-VLN_L1, in true Earth frame,
with the correction for magnetic declination applied. [m/s]
u = uncorrected eastward velocity in magnetic Earth frame. [mm/s]
v = uncorrected northward velocity in magnetic Earth frame. [mm/s]
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 of instrument relative to sealevel [meters].
Positive values only. Default value is 0.
2015-06-08: Russell Desiderio. Changed DPA to reflect correct units
of input velocities. see Notes.
Notes:
As of 2015-06-08, the DPS referenced below is still incorrect:
the Nortek Vector outputs its velocities in units of mm/sec.
References:
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)
"""
# check for valid latitudes & longitudes
if not valid_lat(lat) or not valid_lon(lon):
# commented out next line according to NOTE above. -SP
#return np.ones(u.shape, dtype=np.float) * -9999
raise ValueError('Latitudes or Longitudes are not within the valid range!')
# change the units of the input velocities from mm/sec (see Notes) to m/sec
u = u / 1000.0
v = v / 1000.0
# correct for magnetic declination
v_cor = vel_mag_correction(u, v, lat, lon, timestamp, z)[1]
# return true compass referenced North velocity in m/s
return v_cor
def nortek_up_vel(w):
"""
Description:
Computes the VELPTTU-VLU_L1 data product from a VEL3D-CD Nortek Vector by converting
the units of the raw velocity vertical velocity measurement from mm/s to m/s.
Usage:
w_l1 = nortek_up_vel(w_l0)
where
w_l1 = Output vertical velocity VELPTTU-VLU_L1 [m/s]
w_l0 = Input vertical velocity [mm/s]
2015-06-08: Russell Desiderio. Changed DPA to reflect correct units
of input velocities. see Notes.
Notes:
As of 2015-06-08, the DPS referenced below is still incorrect:
the Nortek Vector outputs its velocities in units of mm/sec.
References:
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)
"""
return w / 1000.0
def vel3dk_east(
vel0, vel1, vel2, heading, pitch, roll, beams, lat, lon,
timestamp, Vscale, z=0, vel3=0):
"""
Description:
Computes Eastward Velocity L1 VELPTTU-VLE in True Earth coordinates
for VEL3D-K instruments.
Transforms beam velocities to Earth coordinate velocities and then
corrects for magnetic declination to produce the true Earth frame
eastward velocity as the L1 VELPTTU-VLE OOI data product.
Takes 3 or 4 beam velocities in integer counts from a VEL3D-K
(Aquadopp II on a McLane Profiler(MMP)) with the provided Vscale,
beam configuration parameters, and attitude orientation (heading,
pitch, and roll) data from an MMP A#####.DEC binary data file.
Given velocities in beam coordinates in the configuration provided
by the beam parameters, this function transforms the beam velocities
to magnetic Earth coordinates (East, North, and Up). Then the East
and North velocity vectors (u & v) are corrected for magnetic
declination for the location, depth, and time of the vectors using
the World Magnetic Model (WMM), transforming the vectors to a true
Earth reference frame.
This function is a wrapper around the functions "vel_mag_correction"
and "vel3dk_transform".
Usage:
u_cor = vel3dk_east(
vel0, vel1, vel2, heading, pitch, roll, beams, lat, lon,
timestamp, Vscale, z=0, vel3=0)
where
u_cor = floating point eastward velocity VELPTTU-VLE_L1, in true Earth
frame, with the correction for magnetic declination applied. [m/s]
vel0, 1, 2, 3 = AquadoppII beam velocities as integers to be
scaled by 10^Vscale. vel3 is optional depending on the
number of beams used as listed in beams.
[scaled integer distance/s]
heading, pitch, roll = attitude data obtained from the
AquadoppII. [deci-degrees, i.e. 0.1degrees]
beams = beam configuration as an Nx5 array listing the
physical beams used that correspond to velocities vel0-3.
The 5th beam will always be zero since there is not a 5th
transducer and the 5th column will be ignored. Should be
configured as [beam1,beam2,beam3,beam4,beam5] where beam#
corresponds to vel#-1 (e.g. beam1 to vel0).
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].
Vscale = velocity scaling exponent factor.
z = depth of instrument relative to sealevel [meters].
Positive values only. Default value is 0.
References:
VEL3D-K IDD (2014) (No DPS as of 2014-03-03)
https://confluence.oceanobservatories.org/display/instruments/
VEL3D-K__stc_imodem+-+Telemetered
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)
"""
# convert from scaled, integer distance/s (as received from the
# binary data file) to floating point m/s using the Vscale parameter
# from the MMP binary data file A#####.DEC
vel0 = vel0 * 10.**Vscale
vel1 = vel1 * 10.**Vscale
vel2 = vel2 * 10.**Vscale
if vel3 != 0:
vel3 = vel3 * 10.**Vscale
# attitude variables are in deci-degrees (i.e. 0.1 degrees) and need
# to be converted back to degrees. I believe this is only true if
# parsing the binary data file (as opposed to the ascii produced by
# McLane's software) Source: Aquadopp2 Integrators guide.
heading = 0.1 * heading
roll = 0.1 * roll
pitch = 0.1 * pitch
# check for valid latitudes & longitudes
if not valid_lat(lat) or not valid_lon(lon):
raise ValueError('Latitudes or Longitudes are not within the valid range!')
# transform beam velocites in spherical coordinates to Earth
# coordinates using beam configuration and instrument attitude.
if vel3 != 0:
ENU = vel3dk_transform(
vel0, vel1, vel2, heading, pitch, roll, beams, vel3)
else:
ENU = vel3dk_transform(
vel0, vel1, vel2, heading, pitch, roll, beams)
# separate out the components from the Earth coordinate transformed
# data matrix. The zero index is needed since matrix is
# automatically 2-D, must change back to a 1-D array.
u = np.array(ENU[0, :])[0]
v = np.array(ENU[1, :])[0]
# correct for magnetic declination
u_cor = vel_mag_correction(u, v, lat, lon, timestamp, z)[0]
# return true compass referenced East velocity in m/s
# the zero index is needed here because the vel3dk
return u_cor
def vel3dk_north(
vel0, vel1, vel2, heading, pitch, roll, beams, lat, lon,
timestamp, Vscale, z=0, vel3=0):
"""
Description:
Computes Northward Velocity L1 VELPTTU-VLN in True Earth coordinates
for VEL3D-K instruments.
Transforms beam velocities to Earth coordinate velocities and then
corrects for magnetic declination to produce the true Earth frame
northward velocity as the L1 VELPTTU-VLN OOI data product.
Takes 3 or 4 beam velocities in integer counts from a VEL3D-K
(Aquadopp II on a McLane Profiler(MMP)) with the provided Vscale,
beam configuration parameters, and attitude orientation (heading,
pitch, and roll) data from an MMP A#####.DEC binary data file.
Given velocities in beam coordinates in the configuration provided
by the beam parameters, this function transforms the beam velocities
to magnetic Earth coordinates (East, North, and Up). Then the East
and North velocity vectors (u & v) are corrected for magnetic
declination for the location, depth, and time of the vectors using
the World Magnetic Model (WMM), transforming the vectors to a true
Earth reference frame.
This function is a wrapper around the functions "vel_mag_correction"
and "vel3dk_transform".
Usage:
v_cor = vel3dk_north(
vel0, vel1, vel2, heading, pitch, roll, beams, lat, lon,
ntp_timestamp, Vscale, z=0, vel3=0)
where
v_cor = floating point northward velocity VELPTTU-VLN_L1, in true Earth
frame, with the correction for magnetic declination applied. [m/s]
vel0, 1, 2, 3 = AquadoppII beam velocities as integers to be
scaled by 10^Vscale. vel3 is optional depending on the
number of beams used as listed in beams.
[scaled integer distance/s]
heading, pitch, roll = attitude data obtained from the
AquadoppII. [deci-degrees, i.e. 0.1degrees]
beams = beam configuration as an Nx5 array listing the
physical beams used that correspond to velocities vel0-3.
The 5th beam will always be zero since there is not a 5th
transducer and the 5th column will be ignored. Should be
configured as [beam1,beam2,beam3,beam4,beam5] where beam#
corresponds to vel#-1 (e.g. beam1 to vel0).
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].
Vscale = velocity scaling exponent factor.
z = depth of instrument relative to sealevel [meters].
Positive values only. Default value is 0.
References:
VEL3D-K IDD (2014) (No DPS as of 2014-03-03)
https://confluence.oceanobservatories.org/display/instruments/
VEL3D-K__stc_imodem+-+Telemetered
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)
"""
# convert from scaled, integer distance/s (as received from the
# binary data file) to floating point m/s using the Vscale parameter
# from the MMP binary data file A#####.DEC
vel0 = vel0 * 10.**Vscale
vel1 = vel1 * 10.**Vscale
vel2 = vel2 * 10.**Vscale
if vel3 != 0:
vel3 = vel3 * 10.**Vscale
# attitude variables are in deci-degrees (i.e. 0.1 degrees) and need
# to be converted back to degrees. I believe this is only true if
# parsing the binary data file (as opposed to the ascii produced by
# McLane's software) Source: Aquadopp2 Integrators guide.
heading = 0.1 * heading
roll = 0.1 * roll
pitch = 0.1 * pitch
# check for valid latitudes & longitudes
if not valid_lat(lat) or not valid_lon(lon):
raise ValueError('Latitudes or Longitudes are not within the valid range!')
# transform beam velocites in spherical coordinates to Earth
# coordinates using beam configuration and instrument attitude.
if vel3 != 0:
ENU = vel3dk_transform(
vel0, vel1, vel2, heading, pitch, roll, beams, vel3)
else:
ENU = vel3dk_transform(
vel0, vel1, vel2, heading, pitch, roll, beams)
# separate out the components from the Earth coordinate transformed
# data matrix. The zero index is needed since matrix is
# automatically 2-D, must change back to a 1-D array.
u = np.array(ENU[0, :])[0]
v = np.array(ENU[1, :])[0]
# correct for magnetic declination
v_cor = vel_mag_correction(u, v, lat, lon, timestamp, z)[1]
# return true compass referenced East velocity in m/s
return v_cor
def vel3dk_up(
vel0, vel1, vel2, heading, pitch, roll, beams, Vscale, vel3=0):
"""
Description:
Computes Northward Velocity L1 VELPTTU-VLU in True Earth coordinates
for VEL3D-K instruments.
Takes an integer vertical velocity in generic distance per second
units from a VEL3D-K (Aquadopp II on a McLane Profiler(MMP)) with
the provided Vscale parameter from an MMP A#####.DEC binary data
file to scale the velocity to a floating point in m/s.
Usage:
w_mps = vel3dk_up(
vel0, vel1, vel2, heading, pitch, roll,
beams, Vscale, vel3=0)
where
w_mps = floating point vertical velocity VELPTTU-VLU_L1 [m/s]
vel0, 1, 2, 3 = AquadoppII beam velocities as integers to be
scaled by 10^Vscale. vel3 is optional depending on the
number of beams used as listed in beams.
[scaled integer distance/s]
heading, pitch, roll = attitude data obtained from the
AquadoppII. [deci-degrees, i.e. 0.1degrees]
beams = beam configuration as an Nx5 array listing the
physical beams used that correspond to velocities vel0-3.
The 5th beam will always be zero since there is not a 5th
transducer and the 5th column will be ignored. Should be
configured as [beam1,beam2,beam3,beam4,beam5] where beam#
corresponds to vel#-1 (e.g. beam1 to vel0).
Vscale = velocity scaling exponent factor.
References:
VEL3D-K IDD (2014) (No DPS as of 2014-03-03)
https://confluence.oceanobservatories.org/display/instruments/
VEL3D-K__stc_imodem+-+Telemetered
"""
# convert from scaled, integer distance/s (as received from the
# binary data file) to floating point m/s using the Vscale parameter
# from the MMP binary data file A#####.DEC
vel0 = vel0 * 10.**Vscale
vel1 = vel1 * 10.**Vscale
vel2 = vel2 * 10.**Vscale
if vel3 != 0:
vel3 = vel3 * 10.**Vscale
# attitude variables are in deci-degrees (i.e. 0.1 degrees) and need
# to be converted back to degrees. I believe this is only true if
# parsing the binary data file (as opposed to the ascii produced by
# McLane's software) Source: Aquadopp2 Integrators guide.
heading = 0.1 * heading
roll = 0.1 * roll
pitch = 0.1 * pitch
# transform the beam velocities to Earth coordinates
if vel3 != 0:
ENU = vel3dk_transform(
vel0, vel1, vel2, heading, pitch, roll, beams, vel3)
else:
ENU = vel3dk_transform(
vel0, vel1, vel2, heading, pitch, roll, beams)
# seperate out the components from the
w = np.array(ENU[2, :])[0]
# return vertical velocity in m/s
return w
def velpt_mag_corr_east(u, v, lat, lon, timestamp, z=0.0):
"""
Description:
Corrects the eastward velocity from all series of VELPT instruments (ABDJ)
instrument for magnetic declination to produce an L1 VELPTMN-VLE OOI
data product. All instruments in the VELPT category are a variety of
Nortek Aquadopp. However, this DPA does not apply to VEL3D-K.
Given a velocity vector with components u & v in the magnetic East
and magnetic North directions respectively, this function calculates
the magnetic declination for the location, depth, and time of the
vector from the World Magnetic Model (WMM) and transforms the vector
to a true Earth reference frame.
This function is a wrapper around the function "vel_mag_correction".
Usage:
u_cor = velpt_mag_corr_east(u, v, lat, lon, ntp_timestamp, z)
where
u_cor = eastward velocity VELPTMN-VLE_L1, in true Earth frame,
with the correction for magnetic declination applied. [m/s]
u = uncorrected eastward velocity in magnetic Earth frame. [mm/s]
v = uncorrected northward velocity in magnetic Earth frame. [mm/s]
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 of instrument relative to sealevel [meters].
Positive values only. Default value is 0.
References:
OOI (2012). Data Product Specification for Mean Point Water
Velocity. Document Control Number 1341-00790.
https://alfresco.oceanobservatories.org/ (See: Company Home
>> OOI >> Controlled >> 1000 System Level >>
1341-00790_Data_Product_SPEC_VELPTMN_OOI.pdf)
"""
# check for valid latitudes & longitudes
if not valid_lat(lat) or not valid_lon(lon):
# commented out next line according to NOTE above. -SP
#return np.ones(u.shape, dtype=np.float) * -9999
raise ValueError('Latitudes or Longitudes are not within the valid range!')
# correct for magnetic declination
u_cor = vel_mag_correction(u, v, lat, lon, timestamp, z)[0]
# return true compass referenced East velocity in m/s
return u_cor / 1000.
def velpt_mag_corr_north(u, v, lat, lon, timestamp, z=0.0):
"""
Description:
Corrects the northward velocity from all series of VELPT instruments (ABDJ)
instrument for magnetic declination to produce an L1 VELPTMN-VLN OOI
data product. All instruments in the VELPT category are a variety of
Nortek Aquadopp. However, this DPA does not apply to VEL3D-K.
Given a velocity vector with components u & v in the magnetic East
and magnetic North directions respectively, this function calculates
the magnetic declination for the location, depth, and time of the
vector from the World Magnetic Model (WMM) and transforms the vector
to a true Earth reference frame.
This function is a wrapper around the function "vel_mag_correction".
Usage:
v_cor = velpt_mag_corr_north(u, v, lat, lon, ntp_timestamp, z)
where
v_cor = northward velocity VELPTMN-VLN_L1, in true Earth frame,
with the correction for magnetic declination applied. [m/s]
u = uncorrected eastward velocity in magnetic Earth frame. [mm/s]
v = uncorrected northward velocity in magnetic Earth frame. [mm/s]
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 of instrument relative to sealevel [meters].
Positive values only. Default value is 0.
References:
OOI (2012). Data Product Specification for Mean Point Water
Velocity. Document Control Number 1341-00790.
https://alfresco.oceanobservatories.org/ (See: Company Home
>> OOI >> Controlled >> 1000 System Level >>
1341-00790_Data_Product_SPEC_VELPTMN_OOI.pdf)
"""
# check for valid latitudes & longitudes
if not valid_lat(lat) or not valid_lon(lon):
# commented out next line according to NOTE above. -SP
#return np.ones(u.shape, dtype=np.float) * -9999
raise ValueError('Latitudes or Longitudes are not within the valid range!')
# correct for magnetic declination
v_cor = vel_mag_correction(u, v, lat, lon, timestamp, z)[1]
# return true compass referenced North velocity in m/s
return v_cor / 1000.
def velpt_up_vel(w):
"""
Description:
Computes the VELPTMN-VLU_L1 data product from all series (ABDJ) of the instrument
class VELPT. The units of the raw upwards velocity measurements are converted from
mm/s to m/s. This DPA does not apply to VEL3D-K.
Usage:
w_mps = velpt_up_vel(w_mmps)
where
w_mps = Output vertical velocity VELPTMN-VLU_L1 [m/s]
w_mmps = Input vertical velocity [mm/s]
References:
OOI (2012). Data Product Specification for Mean Point Water
Velocity. Document Control Number 1341-00790.
https://alfresco.oceanobservatories.org/ (See: Company Home
>> OOI >> Controlled >> 1000 System Level >>
1341-00790_Data_Product_SPEC_VELPTMN_OOI.pdf)
"""
return w / 1000.
##### Sub functions #####
## VEL3D-A,L subfunctions ##
def fsi_acm_horz_vel(vp1, vp3, hdg, lat, lon, timestamp):
"""
Description:
Worker function which calculates eastward and northward velocities
corrected for magnetic declination for VEL3D series A and L instruments.
Usage:
(u, v) = fsi_acm_horz_vel(vp1, vp3, hdg, lat, lon, timestamp)
where
u = eastwards velocity [m/s]
v = northwards velocity [m/s]
vp1 = raw beam velocity from the port stinger finger; VELPTMN-VP1_L0 [cm/s]
vp3 = raw beam velocity from the starboard stinger finger; VELPTMN-VP3_L0 [cm/s]
hdg = ACM nautical heading [degrees clockwise from magnetic north to the instrument's
x-axis]
lat = latitude of the instrument [decimal degrees]. East is positive, West negative.
lon = longitude of the instrument [decimal degrees]. North is positive, South negative.
timestamp = NTP time stamp from a data particle [secs since 1900-01-01].
Implemented by:
2015-02-18: Russell Desiderio. Initial code.
Notes:
The VEL3D series A and L instruments are FSI current meters modified for use
on a McLane profiler. The FSI ACM manuals do *not* show the sensor used on the
McLane. The modified horizontal-looking configuration used on the McLane is
called the stinger configuration, a picture of which is on page 2-1 of the McLane
Moored Profiler (MMP) User Manual Rev E. There are 4 stinger 'fingers' oriented
at 45 degrees from a central post such that their tips describe a square.
The FSI ACM has 4 raw beam velocities. The correspondences between the MMP manual
designations and the IDD designations are:
(Xplus, Yplus, Xminus, Yminus) (MMP manual, page G-22)
(va , vb , vc , vd ) (IDD, VEL3D series A)
(vp1 , vp2 , vp3 , vp4 ) (IDD, VEL3D series L)
(left , down , right , up ) (spatial orientation)
This is also the ordering of these parameters in telemetered and recovered data.
The instrument coordinate system is defined as: the x-axis is along the central post
moving away from the profiler. The y-axis is to port of the x-axis and the z-axis is
up. Headings are defined with respect to the orientation of the x-axis with respect
to clockwise from North (for nautical headings) or counterclockwise from East (for
cartesian headings).
Raw vp1 and vp3 beam velocities are positive for flow along the acoustic path from the
central post towards the finger. Raw vp2 and vp4 beam velocities are positive for flow
along the acoustic path from the finger towards the central post.
The spatial orientation of these fingers is (left, down, right, up). Because vp1
and vp3 lie in the horizontal plane and vp2 and vp4 lie in the orthogonal vertical
plane, transformation from beam to instrument coordinates is particularly simple. In
addition, because the ACM is mounted on the profiler, the pitch and roll angles are
considered to be small and negligible, so that the transformation from instrument
to earth coordinates involves only heading corrections.
For series A, the hdg values are calculated from field (hx,hy) direction cosine
data and correction parameters computed from a compass calibration. For series L,
the hdg values are directly output by the ACM.
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf)
"""
# convert from beam coordinates to instrument coordinates
Vx = (-vp1 - vp3) / np.sqrt(2.0)
Vy = (vp1 - vp3) / np.sqrt(2.0)
# find the speed; change units from cm/s to m/s
speed = 0.01 * np.sqrt(Vx*Vx + Vy*Vy)
# get the magnetic variation:
# degrees clockwise from geographic north to magnetic north are positive.
# degrees counter-clockwise from geographic north to magnetic north are negative.
magvar = magnetic_declination(lat, lon, timestamp)
# figure out the cartesian heading theta of the velocity vector (Vx, Vy) in the earth frame,
# which is the angle defined as radians ccw from geographic east to the velocity vector.
# (1) in instrument coordinates the cartesian heading is atan2(Vy/Vx) [radians ccw from x-axis]
# (2) the nautical (magnetic) heading of the instrument's x-axis is converted to cartesian.
# (3) the magnetic variation corrections for nautical headings change sign when correcting
# cartesian headings because nautical headings become more positive in the clockwise
# direction, cartesian headings are more positive moving counterclockwise.
theta_cartesian = np.arctan2(Vy, Vx) + np.deg2rad((90.0 - hdg) - magvar)
# (4) the MMP manual defines magvar using the opposite of the standard sign convention as
# described above. the manual adds their mdev (=magvar) to the cartesian heading, which
# is correct given their sign convention.
# (5) note: the version of the Scripps code I saw adds nautical heading values supplied by
# the ACM to the cartesian angle of the velocity vector (Vx, Vy), which is incorrect.
# calculate the eastward (u) and northward (v) velocities
u = speed * np.cos(theta_cartesian)
v = speed * np.sin(theta_cartesian)
return u, v
def fsi_acm_nautical_heading(hx, hy, hdg_cal, hx_cal, hy_cal):
"""
Description:
Calculates ACM compass headings from field direction cosine data (hx,hy) and a spin
test compass calibration as described in the MMP manual. Used only for VEL3D series
A instruments (FSI ACMs deployed by RSN on a McLane profiler).
Usage:
hdg = fsi_acm_nautical_heading(hx, hy, hdg_cal, hx_cal, hy_cal)
where
hdg = heading values associated with field data [degrees clockwise from magnetic north to
the instrument's x-axis].
hx = the direction cosine of the local magnetic field projected onto the instrument x-axis.
hy = the direction cosine of the local magnetic field projected onto the instrument y-axis.
hdg_cal = 8-element vector of reference stinger headings from a compass calibration spin test.
heading convention: nautical [degrees clockwise from magnetic north to the instrument's
x-axis]
hx_cal = 8-element vector of direction cosines of the magnetic field projected along
the instrument x-axis acquired during a compass calibration spin test.
hy_cal = 8-element vector of direction cosines of the magnetic field projected along
the instrument y-axis acquired during a compass calibration spin test.
Implemented by:
2015-02-18: Russell Desiderio. Initial code.
Notes:
See Notes for the function fsi_acm_compass_cal.
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf). see p. 8-18 and Appendix D.
"""
# calculate the compass cal correction values
(hx_offset, hy_offset, hx_scale, hy_scale, compass_bias) = fsi_acm_compass_cal(
hdg_cal, hx_cal, hy_cal)
# correct the field direction cosine data.
hxcorr = (hx-hx_offset)/hx_scale
hycorr = (hy-hy_offset)/hy_scale
# calculate cartesian heading as per manual: atan2(hxcorr/hycorr) and not as y/x.
# this heading is the orientation of the instrument x-axis in degrees ccw from
# magnetic east. using this convention, the compass bias correction is added to
# the cartesian heading.
hdg_cartesian = np.rad2deg(np.arctan2(hxcorr, hycorr)) + compass_bias
# convert to the nautical heading convention
hdg_nautical = 90.0 - hdg_cartesian
# and make sure values lie in [0 360)
hdg_nautical = np.mod(360.0 + hdg_nautical, 360.0)
return hdg_nautical
def fsi_acm_compass_cal(hdg_cal, hx_cal, hy_cal):
"""
Description:
Calculates compass calibration correction parameters based on an 8-point spin test
for field data acquired from FSI acoustic current meters. Used only for VEL3D series
A instruments (FSI ACMs deployed by RSN on a McLane profiler).
Usage:
(hx_offset, hy_offset, hx_scale, hy_scale, compass_bias) = fsi_acm_compass_cal(
hdg_cal, hx_cal, hy_cal)
where
hx_offset = subtractive correction offset to the direction cosine hx of the local
magnetic field projected onto the instrument x-axis.
hy_offset = subtractive correction offset to hy.
hx_scale = multiplicative scaling factor correction to the direction cosine hx of the
local magnetic field projected onto the instrument x-axis.
hy_scale = multiplicative scaling factor correction to hy.
compass_bias = additive correction to derived cartesian heading values [degrees]
hdg_cal = 8-element vector of reference stinger headings from a compass calibration
spin test. heading convention: nautical (0 degrees is North, positive angles are cw)
heading units: degrees
hx_cal = 8-element vector of direction cosines of the magnetic field projected along
the instrument x-axis acquired during a compass calibration spin test.
hy_cal = 8-element vector of direction cosines of the magnetic field projected along
the instrument y-axis acquired during a compass calibration spin test.
Implemented by:
2015-02-16: Russell Desiderio. Initial code.
2015-06-01: Russell Desiderio. Adjusted code to process vertically stacked (in time)
input variables.
Notes:
The 8-compass-point spin test involves acquiring hx_cal and hy_cal direction cosine
measurements from the FSI ACM as a function of the independently known and recorded
rotational orientation (hdg_cal) of the ACM instrument's x-axis in degrees clockwise
relative to magnetic North. The spacing of the compass points should be 45 degrees.
Because of the way the RSN ACMs are mounted on the McLane profiler it is anticipated
that these values will be:
RSN ACM CAL HEADINGS: 335, 20, 65, 110, 155, 200, 245, 290.
However, the order is unimportant, as are the actual compass directions used, as long
as the heading of the x-axis of the ACM is used and the compass points are equi-distantly
spaced out around a circle.
Note that the procedure in the MMP manual works in a cartesian heading system (defined
as the bearing of the instrument's x-asis in degrees counter-clockwise from magnetic east).
The DPA converts the nautical calibration heading values to cartesian when calculating
direction cosine and compass corrections.
If no cal is available, the following compass cal entries can be used to give offsets and
biases of 0 and scaling factors of 1:
hdg_cal hx_cal hy_cal
0 1.0 0.0
45 1.0 1.0
90 0.0 1.0
135 -1.0 1.0
180 -1.0 0.0
225 -1.0 -1.0
270 0.0 -1.0
315 1.0 -1.0
References:
OOI (2015). Data Product Specification for Mean Point Water Velocity
Data from FSI Acoustic Current Meters. Document Control Number
1341-00792. https://alfresco.oceanobservatories.org/ (See:
Company Home >> OOI >> Controlled >> 1000 System Level >>
1341-00792_Data_Product_SPEC_VELPTMN_ACM_OOI.pdf)
OOI (2015). 1341-00792_VELPTMN Artifact: McLane Moored Profiler User Manual.
https://alfresco.oceanobservatories.org/ (See: Company Home >> OOI >>
>> REFERENCE >> Data Product Specification Artifacts >> 1341-00792_VELPTMN >>
MMP-User Manual-Rev-E-WEB.pdf). see p. 8-18 and Appendix D.
"""
# make sure that the cal variables are sized correctly.
# variables should be passed to DPAs as 2D vectors, but make sure to avoid tuple out of range.
hdg_cal = np.atleast_2d(hdg_cal)
hx_cal = np.atleast_2d(hx_cal)
hy_cal = np.atleast_2d(hy_cal)
lFlag = hdg_cal.shape[1] != 8 or hx_cal.shape[1] != 8 or hy_cal.shape[1] != 8
if lFlag:
raise ValueError('Each row of the compass calibration variables hdg_cal, '
'hx_cal, and hy_cal must contain 8 elements.')
# the offsets are found by taking the vector average.
# return column vectors so that python's default broadcasting action will give desired result.
hx_offset = np.mean(hx_cal, axis=1, keepdims=True)
hy_offset = np.mean(hy_cal, axis=1, keepdims=True)
# the scaling factors are calculated as
hx_scale = np.max(np.abs(hx_cal - hx_offset), axis=1, keepdims=True)
hy_scale = np.max(np.abs(hy_cal - hy_offset), axis=1, keepdims=True)
# the x and y offsets and scaling factors will be used to correct the field data.
# they are also used to find the average compass bias (BT in the MMP manual);
# first correct the cal direction cosines (same procedure as is used to correct the
# field data).
hxcalcorr = (hx_cal-hx_offset)/hx_scale
hycalcorr = (hy_cal-hy_offset)/hy_scale
# convert nautical heading to cartesian
hdg_cal_cartesian = 90.0 - hdg_cal
# arctan(hx/hy) is correct because of the instrument axes and heading conventions.
# the np.arctan2 function takes the 'y' coordinate first, which in this case is hx.
compass_bias = hdg_cal_cartesian - np.rad2deg(np.arctan2(hxcalcorr, hycalcorr))
# correct compass differences resulting from the wrap-around discontinuity
mask = np.abs(compass_bias) > 180.0
compass_bias[mask] = compass_bias[mask] - np.sign(compass_bias[mask]) * 360.0
# and take the mean, final answer. for symmetry, return answer as a column vector, but ...
compass_bias = np.mean(compass_bias, axis=1, keepdims=True)
# now return all arguments as 1D arrays.
hx_offset = hx_offset.reshape(-1)
hy_offset = hy_offset.reshape(-1)
hx_scale = hx_scale.reshape(-1)
hy_scale = hy_scale.reshape(-1)
compass_bias = compass_bias.reshape(-1)
return hx_offset, hy_offset, hx_scale, hy_scale, compass_bias
## VEL3D-K Beam coordinate transformations ##
def generate_beam_transforms():
"""
Description:
This function is used to create the 3 possible beam-to-cartesian
coordinate transform matrices that transforms velocity vectors
from beam coordinates of the Nortek Aquadopp II velocity
instrument (VEL3D-K), to the cartesian coordinates of the McLane
Moored Profiler (Wire Following Profiler [WFP]). The transform
used depends on the beams used by the Aquadopp II during a
profile. The spherical coordinates for the 4 beams on the
instrument and the orientation of the instrument on the profiler
are hard coded here (never expected to change) for processing
ease i.e. no required inputs to the function.
The 3 possible beam configurations are an upward traveling
profile (using 3 of 4 beams), a downward traveling profile
(using 3 of 4 beams), or a stationary profile (using 4 of 4
beams). These 3 transform matrices are returned in a dictionary
that is loaded into the module as a constant for use in the
actual transformation functions. The dictionary keys are
'upward', 'downward', or 'stationary'.
Implemented by:
2014-05-13: Stuart Pearce. Reimplementation of code from P.J.
Rusello at Nortek
References:
Lengthy discussions with Nortek and McLane representatives. No
DPS as of yet.
"""
## INTERNAL DESCRIPTION:
## First a matrix that transforms the velocities from cartesian
## coordinates to spherical beam coordinates is created (identified
## by the xyz2beam). To find the reverse matrix that transforms the
## velocities from spherical beams to cartesian coordinates, the
## inverse of the first matrix must be found (identified by
## beam2xyz). This is known as a "Change of basis". The permutation
## matrix then transforms the velocities from cartesian coordianates
## of the instrument, to cartesian coordinates of the profiler. The
## permutation matrix is muliplied by the beam2xyz to get the single
## transformation matrix beam2XYZ (capital XYZ indicates cartesian
## coordinates of the profiler). To get to Earth coordinates,
## another transformation matrix that reverses heading, pitch, and
## roll must be made, but that occurs in another function.
# BEAMS dictionary is the rotations for each beam from cartesian
# coordinates to spherical coordinates
BEAMS = {
1: (sin(radians(47.5)) * cos(radians(0.0)),
0.0, # sin(47.5 deg)*sin(0 deg) = 0
cos(radians(47.5))),
2: (0.0, # sin(25 deg)*cos(90 deg) = 0
sin(radians(25.0)) * sin(radians(90.0)),
cos(radians(25.0))),
3: (sin(radians(47.5)) * cos(radians(180.0)),
0.0, # sin(47.5 deg)*sin(180 deg) = 0
cos(radians(47.5))),
4: (0.0, # sin(25 deg)*cos(270 deg) = 0
sin(radians(25.0)) * sin(radians(270.0)),
cos(radians(25.0)))}
# the cartesian to beam transforms
upward_xyz2beam = np.matrix([BEAMS[1], BEAMS[2], BEAMS[4]])
downward_xyz2beam = np.matrix([BEAMS[2], BEAMS[3], BEAMS[4]])
stationary_xyz2beam = np.matrix([
[BEAMS[1][0], BEAMS[1][1], BEAMS[1][2], 0.0],
[BEAMS[2][0], BEAMS[2][1], 0.0, BEAMS[2][2]],
[BEAMS[3][0], BEAMS[3][1], BEAMS[3][2], 0.0],
[BEAMS[4][0], BEAMS[4][1], 0.0, BEAMS[4][2]]])
# get the inverse of the transforms
upward_beam2xyz = np.linalg.pinv(upward_xyz2beam)
downward_beam2xyz = np.linalg.pinv(downward_xyz2beam)
stationary_beam2xyz = np.linalg.pinv(stationary_xyz2beam)
# set ~0 float point errors to zero
upward_beam2xyz[abs(upward_beam2xyz) < 1e-15] = 0.0
downward_beam2xyz[abs(downward_beam2xyz) < 1e-15] = 0.0
stationary_beam2xyz[abs(stationary_beam2xyz) < 1e-15] = 0.0
# create permutation matrices
permutation_matrix3 = np.matrix([ # if 3 beams are used
[0, 0, 1],
[0, -1, 0],
[1, 0, 0]
])
permutation_matrix4 = np.matrix([ # if 4 beams are used
[0, 0, 0.5, 0.5],
[0, -1, 0, 0],
[1, 0, 0, 0]
])
# combine to create the beam2XYZ (profiler cartesian) transformation
T_beam2XYZ_up = permutation_matrix3 * upward_beam2xyz
T_beam2XYZ_down = permutation_matrix3 * downward_beam2xyz
T_beam2XYZ_stat = permutation_matrix4 * stationary_beam2xyz
beam2XYZ_transforms = {'upward': T_beam2XYZ_up,
'downward': T_beam2XYZ_down,
'stationary': T_beam2XYZ_stat}
return beam2XYZ_transforms
# XYZ_TRANSFORMS constant created here
XYZ_TRANSFORMS = generate_beam_transforms()
def get_XYZ_transform(beamlist):
"""
Description:
Sub-function that retrieves the proper beam-to-profiler-cartesian
coordinates from the stored dictionary constant based on the beam
configuration for a profile.
Usage:
beam2XYZ_transform = get_XYZ_transform(beamlist)
where
beam2XYZ_transform = the beam-to-profiler-cartesian transform
matrix
beamlist = a list (derived from the data file) that describes
the physical beams used in order. E.g. [1, 2, 4, 0]
"""
## Implemented by:
## 2014-05-13: Stuart Pearce. Reimplementation of code from P.J.
## Rusello at Nortek
if beamlist == [1, 2, 3, 4]:
t_beam2XYZ = XYZ_TRANSFORMS['stationary']
elif beamlist == [1, 2, 4, 0]:
t_beam2XYZ = XYZ_TRANSFORMS['upward']
elif beamlist == [2, 3, 4, 0]:
t_beam2XYZ = XYZ_TRANSFORMS['downward']
return t_beam2XYZ
def generate_ENU_transform(heading, pitch, roll):
"""
Description:
This function is used to create the cartesian-to-Earth
coordinate transform matrices that transforms velocity vectors
from cartesian coordinates of a McLane Profiler (with a Nortek
Aquadopp II velocity instrument (VEL3D-K)), to Earth coordinates
using heading, pitch, and roll data from the attitude sensor on
board the Aquadopp II.
Usage:
XYZ2Earth_trans = generate_ENU_transform(heading, pitch, roll)
where
XYZ2Earth_trans = the cartesian-to-Earth coordinate tranform
matrix
heading, pitch, roll = the attitude measurements by the Aquadopp
II velocity instrument.
Implemented by:
2014-05-13: Stuart Pearce. Reimplementation of code from P.J.
Rusello at Nortek
References:
Lengthy discussions with Nortek and McLane representatives. No
DPS as of yet.
Definitions of rotation matrices taken from Freescale Technical
Note Implementing a Tilt-Compensated eCompass using
Accelerometer and Magnetometer Sensors
http://cache.freescale.com/files/sensors/doc/app_note/AN4248.pdf
"""
heading = np.radians(heading)
# need to make pitch and roll angles negative so that rotation matrices
# effectively unpitch and unroll the data
pitch = np.radians(-1.0 * pitch)
roll = np.radians(-1.0 * roll)
# "un"-roll transform matrix
Rx = np.matrix([
[1.0, 0.0, 0.0],
[0.0, cos(roll), sin(roll)],
[0.0, -sin(roll), cos(roll)]]
)
# "un"-pitch transform matrix
Ry = np.matrix([
[cos(pitch), 0.0, -sin(pitch)],
[0.0, 1.0, 0.0],
[sin(pitch), 0.0, cos(pitch)]]
)
# "un"-heading transform matrix
Rz = np.matrix([
[cos(heading), sin(heading), 0.0],
[-sin(heading), cos(heading), 0.0],
[0.0, 0.0, 1.0]]
)
# multiply together to create the XYZ to Earth coordinate transform
XYZ2ENU = Rz * Ry * Rx
return XYZ2ENU
def vel3dk_transform(
vel0, vel1, vel2, heading, pitch, roll, beams, vel3=0):
"""
Description:
Transforms beam velocities to Earth coordinate velocities for an
OOI VEL3D-K instrument.
Takes 3 or 4 beam velocities in m/s from a VEL3D-K
(Aquadopp II on a McLane Profiler(MMP)), a beam configuration
array, and attitude orientation data (heading, pitch, and roll),
and transforms the velocities from beam coordinates to Earth
coordinates in the East, North, and Upwards directions.
Usage:
ENU = vel3dk_transform(vel0, vel1, vel2, heading, pitch, roll,
beams, vel3=0)
where
ENU = A matrix of velocity data in Earth coordinates (East,
North, Up) with East velocities in the first row, North
velocities in the second row and Upward velocities in the
3rd row.
vel0, 1, 2, 3 = AquadoppII beam velocities as integers to be
scaled by 10^Vscale. vel3 is optional depending on the
number of beams used as listed in beams.
[scaled integer distance/s]
heading, pitch, roll = attitude data obtained from the
AquadoppII. [degrees]
beams = beam configuration as an Nx5 array listing the
physical beams used that correspond to velocities vel0-3.
The 5th beam will always be zero since there is not a 5th
transducer and the 5th column will be ignored. Should be
configured as [beam1,beam2,beam3,beam4,beam5] where beam#
corresponds to vel#-1 (e.g. beam1 to vel0).
Documentation added: as of 2015-06-03, the IDD states that
the 5th beam value will be NULL which should turn into the
integer fill value -999999999 when presented to this DPA.
This DPA deletes the 5th column of beams, so this is moot.
Implemented by:
2014-05-13: Stuart Pearce. Reimplementation of code from P.J.
Rusello at Nortek
2015-06-02: Russell Desiderio. Trapped out instances of actionable
fill values in the beams configuration variable to return Nans
for those corresponding data products. Actionable fill values
are those that are situated in the 1st 4 columns; fill values
in the 5th column are ignored because the 5th column is deleted.
References:
Lengthy discussions with Nortek and McLane representatives. No
DPS as of yet.
"""
# denote the agreed upon fill value for all integer variables.
fill = -999999999
# at some point this will probably become a global variable.
# Ensure that the variables are in the right condition
heading = np.atleast_1d(heading)
roll = np.atleast_1d(roll)
pitch = np.atleast_1d(pitch)
beams = np.atleast_2d(beams)
# if the array dimension of the vels are greater than 1, it will
# break the call to np.matrix below.
vel0 = np.atleast_1d(vel0)
if vel0.ndim > 1:
vel0 = np.reshape(vel0, -1) # -1 auto-reshapes to 1 dimension
vel1 = np.atleast_1d(vel1)
if vel1.ndim > 1:
vel1 = np.reshape(vel1, -1)
vel2 = np.atleast_1d(vel2)
if vel2.ndim > 1:
vel2 = np.reshape(vel2, -1)
# build the vels into a data matrix for matrix math coming up.
# Each velocity is a row in this case so that later a 3x1 column
# vector is produced for each record
data = np.matrix([vel0, vel1, vel2])
# Not likely to happen, but if a 4th beam is ever added,
if vel3 != 0:
vel3 = np.atleast_1d(vel3)
if vel3.ndim > 1:
vel3 = np.reshape(vel3, -1)
# change the next statement from
#data[4, :] = vel3
# to
data = np.vstack((data, vel3))
# if the beams array has 5 beams, drop the 5th one since there is
# not a 5th transducer.
rows, cols = beams.shape
if cols == 5:
beams = np.delete(beams, 4, 1)
else:
raise ValueError(
"the VEL3D-K algorithm inputs expect a Nx5 beam array," +
"instead got a %dx%d array" % (rows, cols))
# the next section traps out rows in the beams configuration variable that contain
# the integer fill value; the corresponding columns in the product matrix ENU will
# contain NaNs.
# initialize output variable with nans
ENU = np.matrix(np.ones_like(data)) * np.nan # East, North, Up velocities
# find rows in the (now) 4-column beams variable that do not contain fill values.
mask = ~np.any(beams == fill, axis=1)
# if all of the rows contained fill values, we're done;
# for this case, return nans for all values.
if np.all(~mask):
return ENU
# else, send only those data corresponding to good beams data for further processing
beams = beams[mask, :]
heading = heading[mask]
pitch = pitch[mask]
roll = roll[mask]
data = data[:, mask]
# initialize loop product variable
ENU_loop = np.matrix(np.ones_like(data)) * np.nan # East, North, Up velocities
# Now grab the first beam configuration and the transform to start
beams_used = list(beams[0, :])
t_beam2XYZ = get_XYZ_transform(beams_used)
# need a transformation matrix for each measurement
# because Heading Pitch & Roll will change with each record
for ii in range(np.size(heading)):
if list(beams[ii, :]) != beams_used:
beams_used = list(beams[ii, :])
t_beam2XYZ = get_XYZ_transform(beams_used)
t_XYZ2ENU = generate_ENU_transform(heading[ii], pitch[ii], roll[ii])
ENU_loop[:, ii] = t_XYZ2ENU * t_beam2XYZ * data[:, ii]
# now insert calculated loop product into output variable
ENU[:, mask] = ENU_loop
return ENU
## magnetic correction subfunction
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
# helper sub-functions
def valid_lat(lat):
"""valid_lat(lat) -> boolean
Checks if inputs are valid latitude values.
Returns True if value is between -90 and 90,
False otherwise.
"""
if isinstance(lat, np.ndarray):
if np.any(lat > 90) or np.any(lat < -90):
return False
return True
else:
return -90 <= lat and lat <= 90
def valid_lon(lon):
"""valid_lon(lon) -> boolean
Checks if inputs are valid longitude values.
Returns True if value is between -180 and 180,
False otherwise.
"""
if isinstance(lon, np.ndarray):
if np.any(lon > 180) or np.any(lon < -180):
return False
return True
else:
return -180 <= lon and lon <= 180