diff --git a/wetb/fatigue_tools/rainflowcounting/compile.py b/wetb/fatigue_tools/rainflowcounting/compile.py index 26663108f33745e6c1f5dbad1829cc0abb992ffd..989b753c31d2424c4e7187206624dd125822d18e 100644 --- a/wetb/fatigue_tools/rainflowcounting/compile.py +++ b/wetb/fatigue_tools/rainflowcounting/compile.py @@ -1,6 +1,5 @@ -import sys -sys.path.append("../../../../MMPE/") -from mmpe.cython_compile.cython_compile import cython_import +from wetb.utils.cython_compile.cython_compile import cython_import + cython_import('pair_range') cython_import('peak_trough') diff --git a/wetb/fatigue_tools/rainflowcounting/pair_range.pyd b/wetb/fatigue_tools/rainflowcounting/pair_range.pyd index 30f8baed7a441394607bf0e5759a496a08e83a6d..7f84c44c60aecdc881934f4457bb926fd8d719e9 100644 Binary files a/wetb/fatigue_tools/rainflowcounting/pair_range.pyd and b/wetb/fatigue_tools/rainflowcounting/pair_range.pyd differ diff --git a/wetb/fatigue_tools/rainflowcounting/peak_trough.pyd b/wetb/fatigue_tools/rainflowcounting/peak_trough.pyd index 250f85f0e8de0b2c2fe387e0175e92e9c8415cf7..0c51f1e87fd5fbe6715cdc259504e21cea284308 100644 Binary files a/wetb/fatigue_tools/rainflowcounting/peak_trough.pyd and b/wetb/fatigue_tools/rainflowcounting/peak_trough.pyd differ diff --git a/wetb/fatigue_tools/rainflowcounting/rainflowcount.py b/wetb/fatigue_tools/rainflowcounting/rainflowcount.py index f05a1a0a1f38f4fe17c3a436a8be7e548e0e133a..93c980bb7232026f8923d87e917ce5456f443042 100644 --- a/wetb/fatigue_tools/rainflowcounting/rainflowcount.py +++ b/wetb/fatigue_tools/rainflowcounting/rainflowcount.py @@ -1,4 +1,7 @@ import numpy as np +from wetb.utils.cython_compile.cython_compile import cython_import + + def check_signal(signal): # check input data validity if not type(signal).__name__ == 'ndarray': @@ -61,13 +64,18 @@ def rainflow_windap(signal, levels=255., thresshold=(255 / 50)): signal = signal / gain signal = np.round(signal).astype(np.int) + + # If possible the module is compiled using cython otherwise the python implementation is used + cython_import('wetb.fatigue_tools.rainflowcounting.peak_trough') + cython_import('wetb.fatigue_tools.rainflowcounting.pair_range') + from wetb.fatigue_tools.rainflowcounting.peak_trough import peak_trough + from wetb.fatigue_tools.rainflowcounting.pair_range import pair_range_amplitude_mean #Convert to list of local minima/maxima where difference > thresshold sig_ext = peak_trough(signal, thresshold) - from wetb.fatigue_tools.rainflowcounting.pair_range import pair_range_amplitude_mean #rainflow count ampl_mean = pair_range_amplitude_mean(sig_ext) @@ -114,7 +122,7 @@ def rainflow_astm(signal): # Import find extremes and rainflow. # If possible the module is compiled using cython otherwise the python implementation is used - #cython_import('fatigue_tools.rainflowcount_astm') + cython_import('wetb.fatigue_tools.rainflowcounting.rainflowcount_astm') from wetb.fatigue_tools.rainflowcounting.rainflowcount_astm import find_extremes, rainflowcount # Remove points which is not local minimum/maximum @@ -123,4 +131,4 @@ def rainflow_astm(signal): # rainflow count ampl_mean = np.array(rainflowcount(sig_ext)) - return np.array(ampl_mean).T \ No newline at end of file + return np.array(ampl_mean).T diff --git a/wetb/fatigue_tools/rainflowcounting/rainflowcount_astm.pyd b/wetb/fatigue_tools/rainflowcounting/rainflowcount_astm.pyd index e985824ec83011c3b893870352cdef19cba7a582..7b90534e6695dad59e19a543b6284ed5cc5ee381 100644 Binary files a/wetb/fatigue_tools/rainflowcounting/rainflowcount_astm.pyd and b/wetb/fatigue_tools/rainflowcounting/rainflowcount_astm.pyd differ diff --git a/wetb/gtsdf/tests/test_unix_time.py b/wetb/gtsdf/tests/test_unix_time.py new file mode 100644 index 0000000000000000000000000000000000000000..e69c48bd854bedbcc1fb2ef8b2238480c8dfc963 --- /dev/null +++ b/wetb/gtsdf/tests/test_unix_time.py @@ -0,0 +1,24 @@ +''' +Created on 03/12/2015 + +@author: mmpe +''' +import unittest +import numpy as np +import datetime +from wetb.utils.timing import print_time +from wetb.gtsdf.unix_time import to_unix + +class Test(unittest.TestCase): + + @print_time + def r(self, dt): + return [to_unix(dt) for dt in dt] + + def test_to_unix(self): + dt = [datetime.datetime(2000, 1, 1, 12, s % 60) for s in np.arange(1000000)] + self.r(dt) + +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.testName'] + unittest.main() diff --git a/wetb/utils/__init__.py b/wetb/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/wetb/utils/caching.py b/wetb/utils/caching.py new file mode 100644 index 0000000000000000000000000000000000000000..184825ede0a2fd20bb3714856223ad96ac595647 --- /dev/null +++ b/wetb/utils/caching.py @@ -0,0 +1,80 @@ +''' +Created on 07/02/2014 + +@author: MMPE +''' +import inspect + +def set_cache_property(obj, name, get_func, set_func=None): + """Create a cached property + + Parameters + ---------- + obj : object + Class to add property to + name : str + Name of property + get_func : func + Getter function + set_func : func, optional + Setter function + + Examples + -------- + >>> class Example(object): + >>> def __init__(self): + >>> set_cache_property(self, "test", self.slow_function) + >>> + >>> e = Example() + >>> e.test # Call, store and return result of e.slow_function + >>> e.test # Return stored result of e.slow_function + """ + _name = "_" + name + setattr(obj, _name, None) + def get(self): + if getattr(obj, _name) is None: + setattr(obj, _name, get_func()) + return getattr(obj, _name) + + p = property(lambda self:get(self), set_func) + return setattr(obj.__class__, name, p) + +def cache_function(f): + """Cache function decorator + + Example: + >>> class Example(object): + >>> @cache_function + >>> def slow_function(self): + >>> # calculate slow result + >>> return 1 + >>> + >>> e = Example() + >>> e.slow_function() # Call, store and return result of e.slow_function + >>> e.slow_function() # Return stored result of e.slow_function + """ + def wrap(*args, **kwargs): + self = args[0] + name = "_" + f.__name__ + if not hasattr(self, name) or getattr(self, name) is None or kwargs.get("reload", False): + try: + del kwargs['reload'] + except KeyError: + pass + # ======HERE============ + setattr(self, name, f(*args, **kwargs)) + # ====================== + if not hasattr(self, "cache_attr_lst"): + self.cache_attr_lst = set() + def clear_cache(): + for attr in self.cache_attr_lst: + delattr(self, attr) + self.cache_attr_lst = set() + self.clear_cache = clear_cache + self.cache_attr_lst.add(name) + + return getattr(self, name) + if 'reload' in inspect.getargspec(f)[0]: + raise AttributeError("Functions decorated with cache_function are not allowed to take a parameter called 'reload'") + return wrap + diff --git a/wetb/utils/cython_compile/__init__.py b/wetb/utils/cython_compile/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8d7b1d75f5bd28e05d322f0edf4abec2c514ea6b --- /dev/null +++ b/wetb/utils/cython_compile/__init__.py @@ -0,0 +1,5 @@ +d = None;d = dir() + +from .cython_compile import cython_compile, cython_import, cython_compile_autodeclare, is_compiled + +__all__ = [m for m in set(dir()) - set(d)] \ No newline at end of file diff --git a/wetb/utils/cython_compile/examples/__init__.py b/wetb/utils/cython_compile/examples/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/wetb/utils/cython_compile/examples/cycheck.py b/wetb/utils/cython_compile/examples/cycheck.py new file mode 100644 index 0000000000000000000000000000000000000000..b3979a91d8d4bd8c9578b074ae0c6b65b49e8921 --- /dev/null +++ b/wetb/utils/cython_compile/examples/cycheck.py @@ -0,0 +1,33 @@ +''' +Created on 29/03/2013 + +@author: Mads +''' +import cython +import math + + +def cycheck(p): + for i in range(10): + for y in range(2, int(math.sqrt(p)) + 1): + if p % y == 0: + return False + return True + +@cython.ccall +@cython.locals(y=cython.int, p=cython.ulonglong) +def cycheck_pure(p): + for i in range(10): + for y in range(2, int(math.sqrt(p)) + 1): + if p % y == 0: + return False + return True + + +def cycheck_cdef(p): #cpdef cycheck_cdef(unsigned long long p): + #cdef int y + for i in range(10): + for y in range(2, int(math.sqrt(p)) + 1): + if p % y == 0: + return False + return True diff --git a/wetb/utils/cython_compile/examples/examples.py b/wetb/utils/cython_compile/examples/examples.py new file mode 100644 index 0000000000000000000000000000000000000000..53fbe7a0b243b0608ce4e8c3cdace11d8dc2764c --- /dev/null +++ b/wetb/utils/cython_compile/examples/examples.py @@ -0,0 +1,54 @@ +''' +Created on 11/07/2013 + +@author: Mads M. Pedersen (mmpe@dtu.dk) +''' +import math + +from wetb.utils.cython_compile.cython_compile import cython_compile, \ + cython_compile_autodeclare, cython_import +from wetb.utils.cython_compile.examples import cycheck + + +def pycheck(p): + for i in range(10): + for y in range(2, int(math.sqrt(p)) + 1): + if p % y == 0: + return False + return True + + +@cython_compile +def cycheck_compile(p): + import math + for i in range(10): + for y in range(2, int(math.sqrt(p)) + 1): + if p % y == 0: + return False + return True + + +@cython_compile_autodeclare +def cycheck_compile_autodeclare(p): + import math + for i in range(10): + for y in range(2, int(math.sqrt(p)) + 1): + if p % y == 0: + return False + return True + + +p = 17 + +print (pycheck(p)) + +cython_import('cycheck') +print (cycheck.cycheck(p)) +print (cycheck.cycheck_pure(p)) +print (cycheck.cycheck_cdef(p)) + +print (cycheck_compile(p)) + +print (cycheck_compile_autodeclare(p)) + + diff --git a/wetb/utils/geometry.py b/wetb/utils/geometry.py new file mode 100644 index 0000000000000000000000000000000000000000..586ad401e0b514fa234d33c11424700ec1497141 --- /dev/null +++ b/wetb/utils/geometry.py @@ -0,0 +1,198 @@ +import numpy as np + +def rad(deg): + return deg * np.pi / 180 + +def deg(rad): + return rad / np.pi * 180 + +def sind(dir_deg): + return np.sin(rad(dir_deg)) + +def cosd(dir_deg): + return np.cos(rad(dir_deg)) + +def tand(dir_deg): + return np.tan(rad(dir_deg)) + +def mean_deg(dir, axis=0): + """Mean of angles in degrees + + Parameters + ---------- + dir : array_like + Angles in degrees + + Returns + ------- + mean_deg : float + Mean angle + """ + return deg(np.arctan2(np.mean(sind(dir[:]), axis), np.mean(cosd(dir[:]), axis))) + +def std_deg(dir): + """Standard deviation of angles in degrees + + Parameters + ---------- + dir : array_like + Angles in degrees + + Returns + ------- + std_deg : float + standard deviation + """ + return deg(np.sqrt(1 - (np.mean(sind(dir)) ** 2 + np.mean(cosd(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(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 + beta : array_like + Pitot tube side slip angle + vrel : array_like + Pitot tube relative velocity + + 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 positive 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 * 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 * 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 diff --git a/wetb/utils/process_exec.py b/wetb/utils/process_exec.py new file mode 100644 index 0000000000000000000000000000000000000000..caeb49750b88a33e96961aec34bef5eacc9f6c7f --- /dev/null +++ b/wetb/utils/process_exec.py @@ -0,0 +1,54 @@ +''' +Created on 10/03/2014 + +@author: MMPE +''' + +import os +import psutil + +DEBUG = False +def pexec(args, cwd=None): + """ + usage: errorcode, stdout, stderr, cmd = pexec("MyProgram.exe arg1, arg2", r"c:\tmp\") + + """ + import subprocess + if not isinstance(args, (list, tuple)): + args = [args] + args = [str(arg) for arg in args] + for i in range(len(args)): + if os.path.exists(args[i]): + args[i] = str(args[i]).replace('/', os.path.sep).replace('\\', os.path.sep).replace('"', '') + + cmd = "%s" % '{} /c "{}"'.format (os.environ.get("COMSPEC", "cmd.exe"), subprocess.list2cmdline(args)) + if os.path.isfile(cwd): + cwd = os.path.dirname(cwd) + proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, cwd=cwd) + stdout, stderr = proc.communicate() + errorcode = proc.returncode + + return errorcode, stdout.decode(), stderr.decode(), cmd + + +def process(args, cwd=None): + import subprocess + if not isinstance(args, (list, tuple)): + args = [args] + args = [str(arg) for arg in args] + for i in range(len(args)): + if os.path.exists(args[i]): + args[i] = str(args[i]).replace('/', os.path.sep).replace('\\', os.path.sep).replace('"', '') + + cmd = "%s" % '{} /c "{}"'.format (os.environ.get("COMSPEC", "cmd.exe"), subprocess.list2cmdline(args)) + if cwd is not None and os.path.isfile(cwd): + cwd = os.path.dirname(cwd) + return subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, cwd=cwd) + +def exec_process(process): + stdout, stderr = process.communicate() + errorcode = process.returncode + + return errorcode, stdout.decode(), stderr.decode() + + diff --git a/wetb/utils/tests/__init__.py b/wetb/utils/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/wetb/utils/tests/test_caching.py b/wetb/utils/tests/test_caching.py new file mode 100644 index 0000000000000000000000000000000000000000..4d42a6e90c6d046af78da551e9730a4175a9b306 --- /dev/null +++ b/wetb/utils/tests/test_caching.py @@ -0,0 +1,71 @@ +''' +Created on 08/11/2013 + +@author: mmpe +''' +import multiprocessing +import time +import unittest + + +from wetb.utils.timing import get_time +from wetb.utils.caching import cache_function, set_cache_property + + +class Example(object): + def __init__(self, *args, **kwargs): + object.__init__(self, *args, **kwargs) + + set_cache_property(self, "test", self.slow_function) + set_cache_property(self, 'pool', lambda : multiprocessing.Pool(20)) + + def slow_function(self): + time.sleep(1) + return 1 + + @cache_function + def test_cache_function(self): + return self.slow_function() + + @get_time + def prop(self, prop): + return getattr(self, prop) + + + + +def f(x): + return x ** 2 + +class TestCacheProperty(unittest.TestCase): + def setUp(self): + pass + + def testcache_property_test(self): + e = Example() + self.assertAlmostEqual(e.prop("test")[1], 1, 2) + self.assertAlmostEqual(e.prop("test")[1], 0, 2) + + def testcache_property_pool(self): + e = Example() + print (e.prop("pool")) + self.assertAlmostEqual(e.prop("pool")[1], 0, places=4) + print (get_time(e.pool.map)(f, range(10))) + + + def test_cache_function(self): + e = Example() + self.assertAlmostEqual(get_time(e.test_cache_function)()[1], 1, places=2) + self.assertAlmostEqual(get_time(e.test_cache_function)()[1], 0, places=2) + self.assertAlmostEqual(get_time(e.test_cache_function)(reload=True)[1], 1, places=2) + self.assertAlmostEqual(get_time(e.test_cache_function)()[1], 0, places=2) + e.clear_cache() + self.assertAlmostEqual(get_time(e.test_cache_function)()[1], 1, places=2) + + + + + +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.testName'] + unittest.main() diff --git a/wetb/utils/tests/test_geometry.py b/wetb/utils/tests/test_geometry.py new file mode 100644 index 0000000000000000000000000000000000000000..7c2010446dd72f1ee94a740e574fd25ae4d9cc35 --- /dev/null +++ b/wetb/utils/tests/test_geometry.py @@ -0,0 +1,113 @@ +''' +Created on 15/01/2014 + +@author: MMPE +''' +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 + + +class Test(unittest.TestCase): + + + def test_rad(self): + self.assertEqual(rad(45), np.pi / 4) + self.assertEqual(rad(135), np.pi * 3 / 4) + + + def test_deg(self): + self.assertEqual(45, deg(np.pi / 4)) + self.assertEqual(135, deg(np.pi * 3 / 4)) + + def test_rad_deg(self): + for i in [15, 0.5, 355, 400]: + self.assertEqual(i, deg(rad(i)), i) + + def test_sind(self): + self.assertAlmostEqual(sind(30), .5) + + def test_cosd(self): + self.assertAlmostEqual(cosd(60), .5) + + def test_tand(self): + self.assertAlmostEqual(tand(30), 0.5773, 3) + + + def test_mean_deg(self): + self.assertEqual(mean_deg(np.array([0, 90])), 45) + self.assertAlmostEqual(mean_deg(np.array([350, 10])), 0) + + + def test_mean_deg_array(self): + a = np.array([[0, 90], [350, 10], [0, -90]]) + np.testing.assert_array_almost_equal(mean_deg(a, 1), [45, 0, -45]) + np.testing.assert_array_almost_equal(mean_deg(a.T, 0), [45, 0, -45]) + + + def test_std_deg(self): + self.assertEqual(std_deg(np.array([0, 0, 0])), 0) + self.assertAlmostEqual(std_deg(np.array([0, 90, 180, 270])), 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("test_files/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("test_files/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("test_files/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)) + + +if __name__ == "__main__": + #import sys;sys.argv = ['', 'Test.test_rad'] + unittest.main() diff --git a/wetb/utils/timing.py b/wetb/utils/timing.py new file mode 100644 index 0000000000000000000000000000000000000000..f3aea9a345a8725e7e75ffc1f8b3f33c92106679 --- /dev/null +++ b/wetb/utils/timing.py @@ -0,0 +1,116 @@ +from six import exec_ +import time +import inspect +def get_time(f): + """Get time decorator + returns (return_values, time_of_execution) + + >>> @get_time + >>> def test(): + >>> time.sleep(1) + >>> return "end" + >>> + >>> test() + ('end', 0.999833492421551) + """ + def wrap(*args, **kwargs): + t = time.clock() + res = f(*args, **kwargs) + return res, time.clock() - t + w = wrap + w.__name__ = f.__name__ + return w + + +def print_time(f): + """Print time decorator + prints name of method and time of execution + + >>> @print_time + >>> def test(): + >>> time.sleep(1) + >>> + >>> test() + test 1.000s + """ + def wrap(*args, **kwargs): + t = time.time() + res = f(*args, **kwargs) + print ("%-12s\t%.3fs" % (f.__name__, time.time() - t)) + return res + w = wrap + w.__name__ = f.__name__ + return w + + +cum_time = {} +def print_cum_time(f): + """Print cumulated time decorator + prints name of method and cumulated time of execution + + >>> @print_cum_time + >>> def test(): + >>> time.sleep(1) + >>> + >>> test() + test 0001 calls, 1.000000s, 1.000000s pr. call' + >>> test() + test 0002 calls, 2.000000s, 1.000000s pr. call' + """ + if f not in cum_time: + cum_time[f] = (0, 0) + + def wrap(*args, **kwargs): + t = time.time() + res = f(*args, **kwargs) + ct = cum_time[f][1] + time.time() - t + n = cum_time[f][0] + 1 + cum_time[f] = (n, ct) + print ("%-12s\t%.4d calls, %03fs, %fs pr. call'" % (f.__name__, n, ct, ct / n)) + return res + w = wrap + w.__name__ = f.__name__ + return w + +def print_line_time(f): + """Execute one line at the time and prints the time of execution. + Only for non-branching and non-looping code + + prints: time_of_line, cumulated_time, code_line + + + >>> @print_line_time + >>> def test(): + >>> time.sleep(.3) + >>> time.sleep(.5) + >>> + >>> test() + 0.300s 0.300s time.sleep(.3) + 0.510s 0.810s time.sleep(.51) + + """ + def wrap(*args, **kwargs): + arg_names, varargs, varkw, defaults = inspect.getargspec(f) + kwargs[varargs] = args[len(arg_names):] + kwargs[varkw] = {} + for k, v in kwargs.items(): + if k not in tuple(arg_names) + (varargs, varkw): + kwargs.pop(k) + kwargs[varkw][k] = v + if defaults: + kwargs.update(dict(zip(arg_names[::-1], defaults[::-1]))) + kwargs.update(dict(zip(arg_names, args))) + + + lines = inspect.getsourcelines(f)[0][2:] + tcum = time.clock() + locals = kwargs + gl = f.__globals__ + + for l in lines: + tline = time.clock() + exec(l.strip(), locals, gl) #res = f(*args, **kwargs) + print ("%.3fs\t%.3fs\t%s" % (time.clock() - tline, time.clock() - tcum, l.strip())) + w = wrap + w.__name__ = f.__name__ + return w