From 4cb24d2b4667888dfc4d4747d42876e20d8ae6bc Mon Sep 17 00:00:00 2001
From: "Mads M. Pedersen" <mmpe@dtu.dk>
Date: Wed, 21 Dec 2016 11:08:50 +0100
Subject: [PATCH] wsp and pitot mapping moved to wind.dir_mapping.py

---
 .gitignore                        |   2 +
 wetb/utils/geometry.py            | 204 +---------------------------
 wetb/utils/tests/test_geometry.py |  68 +---------
 wetb/wind/dir_mapping.py          | 214 ++++++++++++++++++++++++++++++
 4 files changed, 219 insertions(+), 269 deletions(-)
 create mode 100644 wetb/wind/dir_mapping.py

diff --git a/.gitignore b/.gitignore
index 5c2598f..1e37b33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,5 @@ wetb/hawc2/ascii2bin/tests/test_files/Hawc2ascii_bin.dat
 wetb/prepost/tests/data/demo_dlc/remote*
 
 /wetb/fatigue_tools/rainflowcounting/compile.py
+/docs/api
+/htmlcov
diff --git a/wetb/utils/geometry.py b/wetb/utils/geometry.py
index 3a7761c..211a811 100644
--- a/wetb/utils/geometry.py
+++ b/wetb/utils/geometry.py
@@ -87,207 +87,5 @@ def std_rad(dir):
     """
     return np.sqrt(1 - (np.nanmean(np.sin(dir)) ** 2 + np.nanmean(np.cos(dir)) ** 2))
 
-def wsp_dir2uv(wsp, dir, dir_ref=None):
-    """Convert horizontal wind speed and direction to u,v
-
-    Parameters
-    ----------
-    wsp : array_like
-        Horizontal wind speed
-    dir : array_like
-        Wind direction
-    dir_ref : int or float, optional
-        Reference direction\n
-        If None, default, the mean direction is used as reference
-
-    Returns
-    -------
-    u : array_like
-        u wind component
-    v : array_like
-        v wind component
-    """
-    if dir_ref is None:
-        dir = dir[:] - mean_deg(dir[:])
-    else:
-        dir = dir[:] - dir_ref
-    u = np.cos(rad(dir)) * wsp[:]
-    v = -np.sin(rad(dir)) * wsp[:]
-    return np.array([u, v])
-
-def wsp_dir_tilt2uvw(wsp, dir, tilt, wsp_horizontal, dir_ref=None):
-    """Convert horizontal wind speed and direction to u,v,w
-
-    Parameters
-    ----------
-    wsp : array_like
-        - if wsp_horizontal is True: Horizontal wind speed, $\sqrt{u^2+v^2}\n
-        - if wsp_horizontal is False: Wind speed, $\sqrt{u^2+v^2+w^2}
-    dir : array_like
-        Wind direction
-    tilt : array_like
-        Wind tilt
-    wsp_horizontal : bool
-        See wsp
-    dir_ref : int or float, optional
-        Reference direction\n
-        If None, default, the mean direction is used as reference
-
-
-    Returns
-    -------
-    u : array_like
-        u wind component
-    v : array_like
-        v wind component
-    w : array_like
-        v wind component
-    """
-    wsp, dir, tilt = wsp[:], dir[:], tilt[:]
-    if wsp_horizontal:
-        w = tand(tilt) * wsp
-        u, v = wsp_dir2uv(wsp, dir, dir_ref)
-    else:
-        w = sind(tilt) * wsp
-        u, v = wsp_dir2uv(np.sqrt(wsp ** 2 - w ** 2), dir, dir_ref)
-    return np.array([u, v, w])
-
-
-
-def xyz2uvw(x, y, z, left_handed=True):
-    """Convert sonic x,y,z measurements to u,v,w wind components
-
-    Parameters
-    ----------
-    x : array_like
-        Sonic x component
-    y : array_like
-        Sonic x component
-    z : array_like
-        Sonic x component
-    left_handed : boolean
-        if true (default), xyz are defined in left handed coodinate system (default for some sonics)
-        if false, xyz are defined in normal right handed coordinate system
-
-    Returns
-    -------
-    u : array_like
-        u wind component
-    v : array_like
-        v wind component
-    w : array_like
-        w wind component
-    """
-    x, y, z = map(np.array, [x, y, z])
-    if left_handed:
-        y *= -1
-    theta = deg(np.arctan2(np.mean(y), np.mean(x)))
-    SV = cosd(theta) * y - sind(theta) * x
-    SUW = cosd(theta) * x + sind(theta) * y
-
-    #% rotation around y of tilt
-    tilt = deg(np.arctan2(np.mean(z), np.mean(SUW)))
-    SU = SUW * cosd(tilt) + z * sind(tilt);
-    SW = z * cosd(tilt) - SUW * sind(tilt);
-
-    return np.array([SU, SV, SW])
-
 def rpm2rads(rpm):
-    return rpm * 2 * np.pi / 60
-
-
-def abvrel2xyz_old(alpha, beta, vrel):
-    """Convert pitot tube alpha, beta and relative velocity to local Cartesian wind speed velocities
-
-    Parameters
-    ----------
-    alpha : array_like
-        Pitot tube angle of attack [rad]. Zero: Parallel to pitot tube. Positive: Flow from wind side (pressure side)
-    beta : array_like
-        Pitot tube side slip angle [rad]. Zero: Parallel to pitot tube. Positive: Flow from root side
-    vrel : array_like
-        Pitot tube relative velocity. Positive: flow towards pitot tube
-
-    Returns
-    -------
-    x : array_like
-        Wind component towards pitot tube (positive for postive vrel and -90<beta<90)
-    y : array_like
-        Wind component in alpha plane (positive for positive alpha)
-    z : array_like
-        Wind component in beta plane (positive for negative beta)
-    """
-    alpha = np.array(alpha, dtype=np.float)
-    beta = np.array(beta, dtype=np.float)
-    vrel = np.array(vrel, dtype=np.float)
-
-    sign_vsx = -((np.abs(beta) > np.pi / 2) * 2 - 1)  # +1 for |beta| < 90, -1 for |beta|>90
-    sign_vsy = np.sign(alpha)  #+ for alpha > 0
-    sign_vsz = -np.sign(beta)  #- for beta>0
-
-
-    x = sign_vsx * np.sqrt(vrel ** 2 / (1 + np.tan(alpha) ** 2 + np.tan(beta) ** 2))
-
-    m = alpha != 0
-    y = np.zeros_like(alpha)
-    y[m] = sign_vsy[m] * np.sqrt(vrel[m] ** 2 / ((1 / np.tan(alpha[m])) ** 2 + 1 + (np.tan(beta[m]) / np.tan(alpha[m])) ** 2))
-
-    m = beta != 0
-    z = np.zeros_like(alpha)
-    z[m] = sign_vsz[m] * np.sqrt(vrel[m] ** 2 / ((1 / np.tan(beta[m])) ** 2 + 1 + (np.tan(alpha[m]) / np.tan(beta[m])) ** 2))
-
-    return x, y, z
-
-def abvrel2xyz(alpha, beta, vrel):
-    """Convert pitot tube alpha, beta and relative velocity to local Cartesian wind speed velocities
-
-    x : parallel to pitot tube, direction pitot tube root to tip, i.e. normal flow gives negative x\n
-    y : component in alpha plane
-    z : component in beta plane
-
-    For typical usage where pitot tube is mounted on leading edge:\n
-    x: Opposite rotational direction\n
-    y: Direction of mean wind\n
-    z: From blade root to tip\n
-
-
-    Parameters
-    ----------
-    alpha : array_like
-        Pitot tube angle of attack [rad]. Zero for flow towards pitot tube. Positive around z-axis. I.e.
-        negative alpha (normal flow) gives positive y component
-    beta : array_like
-        Pitot tube side slip angle [rad]. Zero for flow towards pitot tube. Positive around y-axis. I.e.
-        Positive beta (normal flow due to expansion and position in front of blade) gives positive z
-    vrel : array_like
-        Pitot tube relative velocity. Positive: flow towards pitot tube
-
-    Returns
-    -------
-    x : array_like
-        Wind component away from pitot tube (positive for postive vrel and -90<beta<90)
-    y : array_like
-        Wind component in alpha plane (positive for positive alpha)
-    z : array_like
-        Wind component in beta plane (positive for negative beta)
-    """
-    alpha = np.array(alpha, dtype=np.float)
-    beta = np.array(beta, dtype=np.float)
-    vrel = np.array(vrel, dtype=np.float)
-
-    sign_vsx = ((np.abs(beta) > np.pi / 2) * 2 - 1)  # -1 for |beta| < 90, +1 for |beta|>90
-    sign_vsy = -np.sign(alpha)  #- for alpha > 0
-    sign_vsz = np.sign(beta)  # for beta>0
-
-
-    x = sign_vsx * np.sqrt(vrel ** 2 / (1 + np.tan(alpha) ** 2 + np.tan(beta) ** 2))
-
-    m = alpha != 0
-    y = np.zeros_like(alpha)
-    y[m] = sign_vsy[m] * np.sqrt(vrel[m] ** 2 / ((1 / np.tan(alpha[m])) ** 2 + 1 + (np.tan(beta[m]) / np.tan(alpha[m])) ** 2))
-
-    m = beta != 0
-    z = np.zeros_like(alpha)
-    z[m] = sign_vsz[m] * np.sqrt(vrel[m] ** 2 / ((1 / np.tan(beta[m])) ** 2 + 1 + (np.tan(alpha[m]) / np.tan(beta[m])) ** 2))
-
-    return np.array([x, y, z]).T
+    return rpm * 2 * np.pi / 60
\ No newline at end of file
diff --git a/wetb/utils/tests/test_geometry.py b/wetb/utils/tests/test_geometry.py
index 1ae8283..a624ce7 100644
--- a/wetb/utils/tests/test_geometry.py
+++ b/wetb/utils/tests/test_geometry.py
@@ -13,8 +13,7 @@ import unittest
 
 import wetb.gtsdf
 import numpy as np
-from wetb.utils.geometry import rad, deg, mean_deg, sind, cosd, std_deg, xyz2uvw, \
-    wsp_dir2uv, wsp_dir_tilt2uvw, tand, abvrel2xyz
+from wetb.utils.geometry import rad, deg, mean_deg, sind, cosd, std_deg, tand
 import os
 
 
@@ -68,70 +67,7 @@ class TestGeometry(unittest.TestCase):
     def test_std_deg_nan(self):
         self.assertAlmostEqual(std_deg(np.array([0, 90, 180, 270, np.nan])), 57.296, 2)
 
-    def test_wspdir2uv(self):
-        u, v = wsp_dir2uv(np.array([1, 1, 1]), np.array([30, 0, 330]))
-        np.testing.assert_array_almost_equal(u, [0.8660, 1, 0.8660], 3)
-        np.testing.assert_array_almost_equal(v, [-0.5, 0, 0.5], 3)
-
-    def test_wspdir2uv_dir_ref(self):
-        u, v = wsp_dir2uv(np.array([1, 1, 1]), np.array([30, 0, 330]), 30)
-        np.testing.assert_array_almost_equal(u, [1, 0.8660, .5], 3)
-        np.testing.assert_array_almost_equal(v, [0, 0.5, .8660], 3)
-
-    def test_xyz2uvw(self):
-        u, v, w = xyz2uvw([1, 1, 0], [0, 1, 1], 0, left_handed=False)
-        np.testing.assert_almost_equal(u, [np.sqrt(1 / 2), np.sqrt(2), np.sqrt(1 / 2)])
-        np.testing.assert_almost_equal(v, [-np.sqrt(1 / 2), 0, np.sqrt(1 / 2)])
-
-
-        u, v, w = xyz2uvw([1, 1, 0], [0, 1, 1], 0, left_handed=True)
-        np.testing.assert_almost_equal(u, [np.sqrt(1 / 2), np.sqrt(2), np.sqrt(1 / 2)])
-        np.testing.assert_almost_equal(v, [np.sqrt(1 / 2), 0, -np.sqrt(1 / 2)])
-
-        u, v, w = xyz2uvw(np.array([-1, -1, -1]), np.array([-0.5, 0, .5]), np.array([0, 0, 0]), left_handed=False)
-        np.testing.assert_array_almost_equal(u, np.array([1, 1, 1]))
-        np.testing.assert_array_almost_equal(v, np.array([.5, 0, -.5]))
-        np.testing.assert_array_almost_equal(w, np.array([0, 0, 0]))
-
-        u, v, w = xyz2uvw(np.array([.5, cosd(30), 1]), np.array([sind(60), sind(30), 0]), np.array([0, 0, 0]), left_handed=False)
-        np.testing.assert_array_almost_equal(u, np.array([sind(60), 1, sind(60)]))
-        np.testing.assert_array_almost_equal(v, np.array([.5, 0, -.5]))
-        np.testing.assert_array_almost_equal(w, np.array([0, 0, 0]))
-
-        u, v, w = xyz2uvw(np.array([.5, cosd(30), 1]), np.array([0, 0, 0]), np.array([sind(60), sind(30), 0]), left_handed=False)
-        np.testing.assert_array_almost_equal(u, np.array([sind(60), 1, sind(60)]))
-        np.testing.assert_array_almost_equal(v, np.array([0, 0, 0]))
-        np.testing.assert_array_almost_equal(w, np.array([.5, 0, -.5]))
-
-
-    def test_wspdir2uv2(self):
-        time, data, info = wetb.gtsdf.load(self.tfp + "SonicDataset.hdf5")
-        stat, x, y, z, temp, wsp, dir, tilt = data[2:3].T  #xyz is left handed
-        np.testing.assert_array_almost_equal(xyz2uvw(*wsp_dir2uv(wsp, dir), z=0), xyz2uvw(x, y, 0))
-
-    def test_wspdirtil2uvw(self):
-        time, data, info = wetb.gtsdf.load(self.tfp + "SonicDataset.hdf5")
-        stat, x, y, z, temp, wsp, dir, tilt = data[3:6].T  #xyz is left handed
-        wsp = np.sqrt(wsp ** 2 + z ** 2)
-        np.testing.assert_array_almost_equal(xyz2uvw(*wsp_dir_tilt2uvw(wsp, dir, tilt, wsp_horizontal=False), left_handed=False), xyz2uvw(x, y, z))
-
-    def test_wspdirtil2uvw_horizontal_wsp(self):
-        time, data, info = wetb.gtsdf.load(self.tfp + "SonicDataset.hdf5")
-        stat, x, y, z, temp, wsp, dir, tilt = data[:].T  #xyz is left handed
-        np.testing.assert_array_almost_equal(xyz2uvw(*wsp_dir_tilt2uvw(wsp, dir, tilt, wsp_horizontal=True), left_handed=False), xyz2uvw(x, y, z))
-
-        np.testing.assert_array_almost_equal(wsp_dir_tilt2uvw(wsp, dir, tilt, wsp_horizontal=True, dir_ref=180), np.array([x, -y, z]), 5)
-        np.testing.assert_array_almost_equal(xyz2uvw(*wsp_dir_tilt2uvw(wsp, dir, tilt, wsp_horizontal=True), left_handed=False), xyz2uvw(x, y, z))
-
-    def test_abvrel2xyz(self):
-        abvrel = np.array([(0., 0, 1), (30, 0, 1), (-30, 0, 1), (0, 30, 1), (0, -30, 1), (30, 30, 1), (30, 30, 2)])
-        abvrel[:, :2] = rad(abvrel[:, :2])
-        for (x, y, z), (a, b, vrel) in zip(abvrel2xyz(*abvrel.T), abvrel):
-            #print (deg(a), deg(b), vrel, x, y, z)
-            self.assertAlmostEqual(a, np.arctan(y / x))
-            self.assertAlmostEqual(b, np.arctan(-z / x))
-            self.assertAlmostEqual(vrel, np.sqrt(x ** 2 + y ** 2 + z ** 2))
-
+    
 
 if __name__ == "__main__":
     #import sys;sys.argv = ['', 'Test.test_rad']
diff --git a/wetb/wind/dir_mapping.py b/wetb/wind/dir_mapping.py
new file mode 100644
index 0000000..4da160f
--- /dev/null
+++ b/wetb/wind/dir_mapping.py
@@ -0,0 +1,214 @@
+'''
+Created on 19. dec. 2016
+
+@author: mmpe
+'''
+
+from wetb.utils.geometry import mean_deg, rad, tand, sind, deg, cosd
+
+import numpy as np
+
+
+def wsp_dir2uv(wsp, dir, dir_ref=None):
+    """Convert horizontal wind speed and direction to u,v
+
+    Parameters
+    ----------
+    wsp : array_like
+        Horizontal wind speed
+    dir : array_like
+        Wind direction
+    dir_ref : int or float, optional
+        Reference direction\n
+        If None, default, the mean direction is used as reference
+
+    Returns
+    -------
+    u : array_like
+        u wind component
+    v : array_like
+        v wind component
+    """
+    if dir_ref is None:
+        dir = dir[:] - mean_deg(dir[:])
+    else:
+        dir = dir[:] - dir_ref
+    u = np.cos(rad(dir)) * wsp[:]
+    v = -np.sin(rad(dir)) * wsp[:]
+    return np.array([u, v])
+
+def wsp_dir_tilt2uvw(wsp, dir, tilt, wsp_horizontal, dir_ref=None):
+    """Convert horizontal wind speed and direction to u,v,w
+
+    Parameters
+    ----------
+    wsp : array_like
+        - if wsp_horizontal is True: Horizontal wind speed, $\sqrt{u^2+v^2}\n
+        - if wsp_horizontal is False: Wind speed, $\sqrt{u^2+v^2+w^2}
+    dir : array_like
+        Wind direction
+    tilt : array_like
+        Wind tilt
+    wsp_horizontal : bool
+        See wsp
+    dir_ref : int or float, optional
+        Reference direction\n
+        If None, default, the mean direction is used as reference
+
+
+    Returns
+    -------
+    u : array_like
+        u wind component
+    v : array_like
+        v wind component
+    w : array_like
+        v wind component
+    """
+    wsp, dir, tilt = wsp[:], dir[:], tilt[:]
+    if wsp_horizontal:
+        w = tand(tilt) * wsp
+        u, v = wsp_dir2uv(wsp, dir, dir_ref)
+    else:
+        w = sind(tilt) * wsp
+        u, v = wsp_dir2uv(np.sqrt(wsp ** 2 - w ** 2), dir, dir_ref)
+    return np.array([u, v, w])
+
+
+
+def xyz2uvw(x, y, z, left_handed=True):
+    """Convert sonic x,y,z measurements to u,v,w wind components
+
+    Parameters
+    ----------
+    x : array_like
+        Sonic x component
+    y : array_like
+        Sonic x component
+    z : array_like
+        Sonic x component
+    left_handed : boolean
+        if true (default), xyz are defined in left handed coodinate system (default for some sonics)
+        if false, xyz are defined in normal right handed coordinate system
+
+    Returns
+    -------
+    u : array_like
+        u wind component
+    v : array_like
+        v wind component
+    w : array_like
+        w wind component
+    """
+    x, y, z = map(np.array, [x, y, z])
+    if left_handed:
+        y *= -1
+    theta = deg(np.arctan2(np.mean(y), np.mean(x)))
+    SV = cosd(theta) * y - sind(theta) * x
+    SUW = cosd(theta) * x + sind(theta) * y
+
+    #% rotation around y of tilt
+    tilt = deg(np.arctan2(np.mean(z), np.mean(SUW)))
+    SU = SUW * cosd(tilt) + z * sind(tilt);
+    SW = z * cosd(tilt) - SUW * sind(tilt);
+
+    return np.array([SU, SV, SW])
+
+
+
+
+def abvrel2xyz_old(alpha, beta, vrel):
+    """Convert pitot tube alpha, beta and relative velocity to local Cartesian wind speed velocities
+
+    Parameters
+    ----------
+    alpha : array_like
+        Pitot tube angle of attack [rad]. Zero: Parallel to pitot tube. Positive: Flow from wind side (pressure side)
+    beta : array_like
+        Pitot tube side slip angle [rad]. Zero: Parallel to pitot tube. Positive: Flow from root side
+    vrel : array_like
+        Pitot tube relative velocity. Positive: flow towards pitot tube
+
+    Returns
+    -------
+    x : array_like
+        Wind component towards pitot tube (positive for postive vrel and -90<beta<90)
+    y : array_like
+        Wind component in alpha plane (positive for positive alpha)
+    z : array_like
+        Wind component in beta plane (positive for negative beta)
+    """
+    alpha = np.array(alpha, dtype=np.float)
+    beta = np.array(beta, dtype=np.float)
+    vrel = np.array(vrel, dtype=np.float)
+
+    sign_vsx = -((np.abs(beta) > np.pi / 2) * 2 - 1)  # +1 for |beta| < 90, -1 for |beta|>90
+    sign_vsy = np.sign(alpha)  #+ for alpha > 0
+    sign_vsz = -np.sign(beta)  #- for beta>0
+
+
+    x = sign_vsx * np.sqrt(vrel ** 2 / (1 + np.tan(alpha) ** 2 + np.tan(beta) ** 2))
+
+    m = alpha != 0
+    y = np.zeros_like(alpha)
+    y[m] = sign_vsy[m] * np.sqrt(vrel[m] ** 2 / ((1 / np.tan(alpha[m])) ** 2 + 1 + (np.tan(beta[m]) / np.tan(alpha[m])) ** 2))
+
+    m = beta != 0
+    z = np.zeros_like(alpha)
+    z[m] = sign_vsz[m] * np.sqrt(vrel[m] ** 2 / ((1 / np.tan(beta[m])) ** 2 + 1 + (np.tan(alpha[m]) / np.tan(beta[m])) ** 2))
+
+    return x, y, z
+
+def abvrel2xyz(alpha, beta, vrel):
+    """Convert pitot tube alpha, beta and relative velocity to local Cartesian wind speed velocities
+
+    x : parallel to pitot tube, direction pitot tube root to tip, i.e. normal flow gives negative x\n
+    y : component in alpha plane
+    z : component in beta plane
+
+    For typical usage where pitot tube is mounted on leading edge:\n
+    x: Opposite rotational direction\n
+    y: Direction of mean wind\n
+    z: From blade root to tip\n
+
+
+    Parameters
+    ----------
+    alpha : array_like
+        Pitot tube angle of attack [rad]. Zero for flow towards pitot tube. Positive around z-axis. I.e.
+        negative alpha (normal flow) gives positive y component
+    beta : array_like
+        Pitot tube side slip angle [rad]. Zero for flow towards pitot tube. Positive around y-axis. I.e.
+        Positive beta (normal flow due to expansion and position in front of blade) gives positive z
+    vrel : array_like
+        Pitot tube relative velocity. Positive: flow towards pitot tube
+
+    Returns
+    -------
+    x : array_like
+        Wind component away from pitot tube (positive for postive vrel and -90<beta<90)
+    y : array_like
+        Wind component in alpha plane (positive for positive alpha)
+    z : array_like
+        Wind component in beta plane (positive for negative beta)
+    """
+    alpha = np.array(alpha, dtype=np.float)
+    beta = np.array(beta, dtype=np.float)
+    vrel = np.array(vrel, dtype=np.float)
+
+    sign_vsx = ((np.abs(beta) > np.pi / 2) * 2 - 1)  # -1 for |beta| < 90, +1 for |beta|>90
+    sign_vsy = -np.sign(alpha)  #- for alpha > 0
+    sign_vsz = np.sign(beta)  # for beta>0
+
+
+    x = sign_vsx * np.sqrt(vrel ** 2 / (1 + np.tan(alpha) ** 2 + np.tan(beta) ** 2))
+
+    m = alpha != 0
+    y = np.zeros_like(alpha)
+    y[m] = sign_vsy[m] * np.sqrt(vrel[m] ** 2 / ((1 / np.tan(alpha[m])) ** 2 + 1 + (np.tan(beta[m]) / np.tan(alpha[m])) ** 2))
+
+    m = beta != 0
+    z = np.zeros_like(alpha)
+    z[m] = sign_vsz[m] * np.sqrt(vrel[m] ** 2 / ((1 / np.tan(beta[m])) ** 2 + 1 + (np.tan(alpha[m]) / np.tan(beta[m])) ** 2))
+
+    return np.array([x, y, z]).T
-- 
GitLab