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
Example #3
0
    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
Example #5
0
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)
Example #7
0
 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    
Example #10
0
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
Example #11
0
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
Example #14
0
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
Example #15
0
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
Example #16
0
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
Example #17
0
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
Example #18
0
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
Example #19
0
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