diff --git a/README.md b/README.md index 206e86e20ba7074d34ab42f772243fd6f40e10a8..eb3daa37a259a0d20f58b34d10260ddad6f15987 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ - [wind](#wind) - [dlc](#dlc) - [fast](#fast) -- [functions](#functions) +- [utils](#utils) ------------------------------------------------------------------------------------ ### [hawc2](wetb/hawc2) @@ -41,9 +41,9 @@ Module for working with "Design load cases" (Code independent) Tools for working with NREL's FAST code (An aeroelastic computer-aided engineering (CAE) tool for horizontal axis wind turbines) - [fast_io](wetb/fast/fast_io.py): Read binary and ascii result files -### [functions](wetb/functions) +### [utils](wetb/utils) Other functions -- [geometry](wetb/functions/geometry.py): Different kind of geometry conversion functions -- [process_exec](wetb/functions/process_exec.py): Run system command in subprocess -- [timing](wetb/functions/timing.py): Decorators for evaluating execution time of functions -- [caching](wetb/functions/caching.py): Decorators to create cached (calculate once) functions and properties \ No newline at end of file +- [geometry](wetb/utils/geometry.py): Different kind of geometry conversion functions +- [process_exec](wetb/utils/process_exec.py): Run system command in subprocess +- [timing](wetb/utils/timing.py): Decorators for evaluating execution time of functions +- [caching](wetb/utils/caching.py): Decorators to create cached (calculate once) functions and properties \ No newline at end of file diff --git a/wetb/dlc/high_level.py b/wetb/dlc/high_level.py index d405e3504c3aa77bf3d6e8d449e3665d3cce18b5..fab7c19f2f2dda9ae9aaae9bb89ff4a62fc3d3b5 100644 --- a/wetb/dlc/high_level.py +++ b/wetb/dlc/high_level.py @@ -11,7 +11,7 @@ import os import functools from wetb.hawc2.sel_file import SelFile -from wetb.functions.caching import cache_function +from wetb.utils.caching import cache_function from collections import OrderedDict HOURS_PR_20YEAR = 20 * 365 * 24 diff --git a/wetb/functions/__init__.py b/wetb/functions/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/wetb/functions/caching.py b/wetb/functions/caching.py deleted file mode 100644 index 184825ede0a2fd20bb3714856223ad96ac595647..0000000000000000000000000000000000000000 --- a/wetb/functions/caching.py +++ /dev/null @@ -1,80 +0,0 @@ -''' -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/functions/geometry.py b/wetb/functions/geometry.py deleted file mode 100644 index 586ad401e0b514fa234d33c11424700ec1497141..0000000000000000000000000000000000000000 --- a/wetb/functions/geometry.py +++ /dev/null @@ -1,198 +0,0 @@ -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/functions/process_exec.py b/wetb/functions/process_exec.py deleted file mode 100644 index caeb49750b88a33e96961aec34bef5eacc9f6c7f..0000000000000000000000000000000000000000 --- a/wetb/functions/process_exec.py +++ /dev/null @@ -1,54 +0,0 @@ -''' -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/functions/tests/__init__.py b/wetb/functions/tests/__init__.py deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/wetb/functions/tests/test_caching.py b/wetb/functions/tests/test_caching.py deleted file mode 100644 index 9df8902ef69a630aa9cdb48193eae99666d8dbbc..0000000000000000000000000000000000000000 --- a/wetb/functions/tests/test_caching.py +++ /dev/null @@ -1,71 +0,0 @@ -''' -Created on 08/11/2013 - -@author: mmpe -''' -import multiprocessing -import time -import unittest - - -from wetb.functions.timing import get_time -from wetb.functions.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/functions/tests/test_files/SonicDataset.hdf5 b/wetb/functions/tests/test_files/SonicDataset.hdf5 deleted file mode 100644 index d254a8104ca5e420db2f44f45a9ce05ad4c4c4fe..0000000000000000000000000000000000000000 Binary files a/wetb/functions/tests/test_files/SonicDataset.hdf5 and /dev/null differ diff --git a/wetb/functions/tests/test_geometry.py b/wetb/functions/tests/test_geometry.py deleted file mode 100644 index 1309bebd952834648920b85b4716bd5ffb387a0a..0000000000000000000000000000000000000000 --- a/wetb/functions/tests/test_geometry.py +++ /dev/null @@ -1,113 +0,0 @@ -''' -Created on 15/01/2014 - -@author: MMPE -''' -import unittest - -import wetb.gtsdf -import numpy as np -from wetb.functions.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/functions/timing.py b/wetb/functions/timing.py deleted file mode 100644 index f3aea9a345a8725e7e75ffc1f8b3f33c92106679..0000000000000000000000000000000000000000 --- a/wetb/functions/timing.py +++ /dev/null @@ -1,116 +0,0 @@ -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 diff --git a/wetb/hawc2/htc_file.py b/wetb/hawc2/htc_file.py index d1c7d4cb91d8dd8f428b564b5f338ec89f708a8d..cb61a875d669a813eeea769845c8aabd1a5a18a8 100644 --- a/wetb/hawc2/htc_file.py +++ b/wetb/hawc2/htc_file.py @@ -14,22 +14,25 @@ import os class HTCFile(HTCContents, HTCDefaults): + filename = None + htc_inputfiles = [] level = 0 - + modelpath = "../" initial_comments = None - def __init__(self, filename=None): + def __init__(self, filename=None, modelpath="../"): + self.modelpath = modelpath self.contents = OrderedDict() self.initial_comments = [] - + self.htc_inputfiles = [] if filename is None: self.filename = 'empty.htc' self.lines = self.empty_htc.split("\n") else: self.filename = filename - - with open(filename) as fid: - self.lines = fid.readlines() + self.lines = self.readlines(filename) +# with open(filename) as fid: +# self.lines = fid.readlines() self.lines = [l.strip() for l in self.lines] lines = self.lines.copy() @@ -44,6 +47,20 @@ class HTCFile(HTCContents, HTCDefaults): if line.name_ == "exit": break + def readlines(self, filename): + self.htc_inputfiles.append(filename) + htc_lines = [] + with open(filename) as fid: + lines = fid.readlines() + for l in lines: + if l.lower().lstrip().startswith('continue_in_file'): + filename = l.lstrip().split(";")[0][len("continue_in_file"):].strip() + filename = os.path.join(os.path.dirname(self.filename), self.modelpath, filename) + htc_lines.extend(self.readlines(filename)) + else: + htc_lines.append(l) + return htc_lines + def __setitem__(self, key, value): self.contents[key] = value @@ -65,7 +82,7 @@ class HTCFile(HTCContents, HTCDefaults): self.output.filename = "./res/%s" % name def input_files(self): - files = [self.filename] + files = self.htc_inputfiles for mb in [self.new_htc_structure[mb] for mb in self.new_htc_structure.keys() if mb.startswith('main_body')]: if "timoschenko_input" in mb: files.append(mb.timoschenko_input.filename[0]) diff --git a/wetb/hawc2/log_file.py b/wetb/hawc2/log_file.py index fe9b250341612fb98ffb9bea941d03f13d2e66c6..77b3b22fca2bac92517c5f1b7e3766add0c4396b 100644 --- a/wetb/hawc2/log_file.py +++ b/wetb/hawc2/log_file.py @@ -32,6 +32,7 @@ class LogFile(object): def __init__(self, log_filename, time_stop): self.filename = log_filename self.time_stop = time_stop + self.hawc2version = "Unknown" self.reset() self.update_status() @@ -94,17 +95,20 @@ class LogFile(object): self.lastline = (txt.strip()[max(0, txt.strip().rfind("\n")):]).strip() if self.status == INITIALIZATION: init_txt, *rest = txt.split("Starting simulation") + if self.hawc2version == "Unknown" and "Version ID" in init_txt: + self.hawc2version = txt.split("Version ID : ")[1].split("\n", 1)[0].strip() if "*** ERROR ***" in init_txt: self.errors.extend([l.strip() for l in init_txt.strip().split("\n") if "error" in l.lower()]) if rest: txt = rest[0] self.status = SIMULATING - if not 'Elapsed time' in self.lastline: - i1 = txt.rfind("Global time") - if i1 > -1: - self.start_time = (self.extract_time(txt[i1:]), time.time()) if self.status == SIMULATING: + if self.start_time is None and not 'Elapsed time' in self.lastline: + i1 = txt.rfind("Global time") + if i1 > -1: + self.start_time = (self.extract_time(txt[i1:]), time.time()) + simulation_txt, *rest = txt.split('Elapsed time') if "*** ERROR ***" in simulation_txt: self.errors.extend([l.strip() for l in simulation_txt.strip().split("\n") if "error" in l.lower()]) @@ -141,10 +145,6 @@ class LogFile(object): else: return "--:--" - def add_HAWC2_errors(self, errors): - if errors: - self.status = ERROR - self.errors.extend(errors) diff --git a/wetb/hawc2/shear_file.py b/wetb/hawc2/shear_file.py index 882d83e78c7c33196268765a918cd0b2e6571cac..b0e8126233f2102cd0822a71d9d158fac6e5bb81 100644 --- a/wetb/hawc2/shear_file.py +++ b/wetb/hawc2/shear_file.py @@ -6,7 +6,6 @@ Created on 24/04/2014 import numpy as np import os -from wetb.functions.make_dirs import make_dirs def save(filename, y_coordinates, z_coordinates, u=None, v=None, w=None): """ @@ -44,7 +43,7 @@ def save(filename, y_coordinates, z_coordinates, u=None, v=None, w=None): assert vuw[i].shape == shape, (i, vuw[i].shape, shape) - make_dirs(filename) + os.makedirs(os.path.dirname(filename), exist_ok=True) with open(filename, 'w') as fid: fid.write(" # autogenerated shear file\n") fid.write(" %d %d\n" % (len(y_coordinates), len(z_coordinates))) diff --git a/wetb/hawc2/simulation.py b/wetb/hawc2/simulation.py index 9f3d2a8daa296d165e0402f1e0c4c2d02e50860f..d8498be2689c50f669ecb01ae35a1c405b2dac13 100644 --- a/wetb/hawc2/simulation.py +++ b/wetb/hawc2/simulation.py @@ -5,7 +5,7 @@ from threading import Timer, Thread import sys from multiprocessing.process import Process import psutil -from wetb.functions.process_exec import process, exec_process +from wetb.utils.process_exec import process, exec_process import subprocess import shutil import json @@ -94,6 +94,11 @@ class Simulation(object): dst = os.path.join(self.tmp_modelpath, os.path.relpath(src_file, self.modelpath)) os.makedirs(os.path.dirname(dst), exist_ok=True) shutil.copy(src_file, dst) + if not os.path.isfile(dst) or os.stat(dst).st_size != os.stat(src_file).st_size: + print ("error copy ", dst) + else: + #print (dst) + pass self.logFile.filename = os.path.join(self.tmp_modelpath, self.log_filename) @@ -124,8 +129,8 @@ class Simulation(object): shutil.rmtree(self.tmp_modelpath) except (PermissionError, OSError) as e: raise Warning(str(e)) - - self.status = CLEANED + if self.status != ERROR: + self.status = CLEANED @@ -158,7 +163,10 @@ class Simulation(object): def stop(self): self.timer.stop() self.simulationThread.process.kill() - self.finish_simulation() + try: + self.finish_simulation() + except: + pass if self.logFile.status not in [log_file.DONE]: self.logFile.status = ABORTED diff --git a/wetb/hawc2/tests/test_htc_file.py b/wetb/hawc2/tests/test_htc_file.py index 489cadac8533ec9cedb098628dacf540f8d6193a..c72af981d7c89c86ea35484c1c16adc466b4cb5b 100644 --- a/wetb/hawc2/tests/test_htc_file.py +++ b/wetb/hawc2/tests/test_htc_file.py @@ -190,6 +190,13 @@ class Test(unittest.TestCase): raise ValueError(f + " is not in list") self.assertFalse(input_files) + def test_continue_in_files(self): + htcfile = HTCFile(self.testfilepath + "continue_in_file.htc", ".") + self.assertIn('main_body__31', htcfile.new_htc_structure.keys()) + self.assertIn('tests/test_files/htcfiles\\.\\./orientation.dat', htcfile.input_files()) + self.assertIn('tests/test_files/htcfiles\\.\\./orientation.dat', htcfile.input_files()) + self.assertIn('./data/NREL_5MW_st1.txt', htcfile.input_files()) + if __name__ == "__main__": #import sys;sys.argv = ['', 'Test.testName'] diff --git a/wetb/hawc2/tests/test_logfile.py b/wetb/hawc2/tests/test_logfile.py index 2a084e43814ad6f3ed583106ebcb99eb703f64f3..e67cfed88544961c5b950b5ba23814b22e8ed7b0 100644 --- a/wetb/hawc2/tests/test_logfile.py +++ b/wetb/hawc2/tests/test_logfile.py @@ -4,9 +4,8 @@ Created on 18/11/2015 @author: MMPE ''' import unittest -from wetb.hawc2.log_file import LogFile, is_file_open, INITIALIZATION_ERROR, \ - INITIALIZATION, SIMULATING, DONE, SIMULATION_ERROR, \ - PENDING, ERROR +from wetb.hawc2.log_file import LogFile, is_file_open, \ + INITIALIZATION, SIMULATING, DONE, PENDING import time from wetb.hawc2 import log_file import threading @@ -94,6 +93,11 @@ class Test(unittest.TestCase): self.assertEqual(logfile.errors, []) self.assertEqual(logfile.elapsed_time, 0.8062344) + def test_HAWC2Version(self): + f = 'test_files/logfiles/finish.log' + logfile = LogFile(f, 200) + self.assertEqual(logfile.hawc2version, "HAWC2MB 11.8") + def test_simulation_error(self): f = 'test_files/logfiles/simulation_error.log' @@ -195,14 +199,6 @@ class Test(unittest.TestCase): logfile.remaining_time = 3600 + 120 + 5 self.assertEqual(logfile.remaining_time_str(), "1:02:05") - def test_add_hawc2errors(self): - f = 'test_files/logfiles/simulating.log' - logfile = LogFile(f, 2) - logfile.update_status() - logfile.add_HAWC2_errors(['program error']) - self.assertEqual(logfile.pct, 25) - self.assertEqual(logfile.status, ERROR) - self.assertEqual(logfile.errors, ['program error']) diff --git a/wetb/wind/tests/test_Shear.py b/wetb/wind/tests/test_Shear.py index 4969b776e0dc5a509cb64e7f67480203c7cc2ab8..6db0f46513e72fc7a452ab424e1b5c824bd217d1 100644 --- a/wetb/wind/tests/test_Shear.py +++ b/wetb/wind/tests/test_Shear.py @@ -4,7 +4,7 @@ Created on 05/06/2012 @author: Mads ''' import os -from wetb.functions.geometry import xyz2uvw +from wetb.utils.geometry import xyz2uvw import wetb.gtsdf from wetb.wind.shear import power_shear, fit_power_shear, fit_power_shear_ref, \ log_shear, fit_log_shear, stability_term