diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c64b0da6d41da5f89a4c50e478644de73d370f07..520db657d549175feb23856dc0a8f1008c8c8e47 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,8 +3,8 @@ before_script: # uncomment first time #- rm -rf TestFiles #- git submodule update --init - - git submodule sync - - git submodule update + #- git submodule sync + #- git submodule update test-3.4: @@ -12,6 +12,7 @@ test-3.4: script: #- python3 setup.py test - pip3 install pytest + - pip3 install mock - python3 -m pytest --cov=wetb tags: - python diff --git a/requirements.txt b/requirements.txt index 270f82f988f5d487fea5e0254aa94e285e2aedc4..458306efad3e123f6c3326b9edb34d72456bd4b1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -19,4 +19,5 @@ PyScaffold pytest-cov sshtunnel xlsxwriter +mock diff --git a/wetb/hawc2/ae_file.py b/wetb/hawc2/ae_file.py index 4557bb037a3e9183c14d03e33dd6cfb1b82a866e..63209c6412d552c484016b2621dbd12c8692ddfe 100644 --- a/wetb/hawc2/ae_file.py +++ b/wetb/hawc2/ae_file.py @@ -1,8 +1,3 @@ -''' -Created on 24/04/2014 - -@author: MMPE -''' from __future__ import print_function from __future__ import unicode_literals from __future__ import division @@ -11,42 +6,54 @@ from io import open from builtins import range from builtins import int from future import standard_library +import os standard_library.install_aliases() - import numpy as np + class AEFile(object): - """Read HAWC2 AE (aerodynamic blade layout) file + + """Read and write the HAWC2 AE (aerodynamic blade layout) file examples -------- >>> aefile = AEFile(r"tests/test_files/NREL_5MW_ae.txt") - >>> print (aefile.thickness(36)) # Interpolated thickness at radius 36 + >>> aefile.thickness(36) # Interpolated thickness at radius 36 23.78048780487805 - >>> print (aefile.chord(36)) # Interpolated chord at radius 36 + >>> aefile.chord(36) # Interpolated chord at radius 36 3.673 - >>> print (aefile.pc_set_nr(36)) # pc set number at radius 36 + >>> aefile.pc_set_nr(36) # pc set number at radius 36 1 + >>> ae= AEFile() + ae.add_set(radius=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], + chord=[1.1, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1], + thickness=[100.0, 100.0, 90.0, 80.0, 70.0, 60.0, 50.0, 40.0, 30.0, 20.0, 10.0], + pc_set_id=[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]) + >>> str(ae) + 1 r[m] Chord[m] T/C[%] Set no. + 1 11 + 0.00000000000000000e+00 1.10000000000000009e+00 1.00000000000000000e+02 1 + 1.00000000000000006e-01 1.00000000000000000e+00 1.00000000000000000e+02 1 + 2.00000000000000011e-01 9.00000000000000022e-01 9.00000000000000000e+01 1 + 2.99999999999999989e-01 8.00000000000000044e-01 8.00000000000000000e+01 1 + 4.00000000000000022e-01 6.99999999999999956e-01 7.00000000000000000e+01 1 + 5.00000000000000000e-01 5.99999999999999978e-01 6.00000000000000000e+01 1 + 5.99999999999999978e-01 5.00000000000000000e-01 5.00000000000000000e+01 1 + 6.99999999999999956e-01 4.00000000000000022e-01 4.00000000000000000e+01 1 + 8.00000000000000044e-01 2.99999999999999989e-01 3.00000000000000000e+01 1 + 9.00000000000000022e-01 2.00000000000000011e-01 2.00000000000000000e+01 1 + 1.00000000000000000e+00 1.00000000000000006e-01 1.00000000000000000e+01 1 """ - def __init__(self, filename): - with open (filename) as fid: - lines = fid.readlines() - nsets = int(lines[0].split()[0]) - lptr = 1 - self.ae_sets = {} - for _ in range(1, nsets + 1): - for _ in range(nsets): - set_nr, n_rows = [int(v) for v in lines[lptr ].split()[:2]] - lptr += 1 - data = np.array([[float(v) for v in l.split()[:4]] for l in lines[lptr:lptr + n_rows]]) - self.ae_sets[set_nr] = data - lptr += n_rows + def __init__(self, filename=None): + self.ae_sets = {} + if filename is not None: + self._read_file(filename) def _value(self, radius, column, set_nr=1): ae_data = self.ae_sets[set_nr] if radius is None: - return ae_data[:,column] + return ae_data[:, column] else: return np.interp(radius, ae_data[:, 0], ae_data[:, column]) @@ -55,14 +62,14 @@ class AEFile(object): def thickness(self, radius=None, set_nr=1): return self._value(radius, 2, set_nr) - + def radius_ae(self, radius=None, set_nr=1): - radii = self.ae_sets[set_nr][:,0] + radii = self.ae_sets[set_nr][:, 0] if radius: - return radii[np.argmin(np.abs(radii-radius))] + return radii[np.argmin(np.abs(radii - radius))] else: return radii - + def pc_set_nr(self, radius, set_nr=1): ae_data = self.ae_sets[set_nr] index = np.searchsorted(ae_data[:, 0], radius) @@ -72,13 +79,59 @@ class AEFile(object): raise NotImplementedError return setnrs[0] + def add_set(self, radius, chord, thickness, pc_set_id, set_id=None): + '''This method will add another set to the ae data''' + if set_id is None: + set_id = 1 + while set_id in self.ae_sets.keys(): + set_id += 1 + self.ae_sets[set_id] = np.array([radius, chord, thickness, pc_set_id]).T + return set_id + + def __str__(self): + '''This method will create a string that is formatted like an ae file with the data in this class''' + n_sets = len(self.ae_sets) + retval = str(n_sets) + ' r[m] Chord[m] T/C[%] Set no.\n' + for st_idx, st in self.ae_sets.items(): + retval += str(st_idx) + ' ' + str(len(st)) + '\n' + for line in st: + retval += '%25.17e %25.17e %25.17e %5d\n' % (line[0], line[1], line[2], line[3]) + return retval + + def save(self, filename): + if not os.path.isdir(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + with open(filename, 'w') as fid: + fid.write(str(self)) + + def _read_file(self, filename): + ''' This method will read in the ae data from a HAWC2 ae file''' + with open(filename) as fid: + lines = fid.readlines() + nsets = int(lines[0].split()[0]) + lptr = 1 + self.ae_sets = {} + for _ in range(1, nsets + 1): + for _ in range(nsets): + set_nr, n_rows = [int(v) for v in lines[lptr].split()[:2]] + lptr += 1 + data = np.array([[float(v) for v in l.split()[:4]] for l in lines[lptr:lptr + n_rows]]) + self.ae_sets[set_nr] = data + lptr += n_rows +def main(): + if __name__ == "__main__": + ae = AEFile(os.path.dirname(__file__) + "/tests/test_files/NREL_5MW_ae.txt") + print(ae.radius_ae(36)) + print(ae.thickness()) + print(ae.chord(36)) + print(ae.pc_set_nr(36)) + ae.add_set(radius=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], + chord=[1.1, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1], + thickness=[100.0, 100.0, 90.0, 80.0, 70.0, 60.0, 50.0, 40.0, 30.0, 20.0, 10.0], + pc_set_id=[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]) + print(str(ae)) -if __name__ == "__main__": - ae = AEFile(r"tests/test_files/NREL_5MW_ae.txt") - print (ae.radius_ae(36)) - print (ae.thickness()) - print (ae.chord(36)) - print (ae.pc_set_nr(36)) +main() diff --git a/wetb/hawc2/tests/test_ae_file.py b/wetb/hawc2/tests/test_ae_file.py index 4e57189110f99d4f914a352f9805d32971532b73..af1d5f0769465d47b6d5c60535db2f589b35a9dc 100644 --- a/wetb/hawc2/tests/test_ae_file.py +++ b/wetb/hawc2/tests/test_ae_file.py @@ -3,20 +3,28 @@ Created on 05/11/2015 @author: MMPE ''' -from __future__ import unicode_literals -from __future__ import print_function -from __future__ import division from __future__ import absolute_import -from future import standard_library -standard_library.install_aliases() +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + +import os import unittest + +from future import standard_library +import mock + +from wetb.hawc2 import ae_file from wetb.hawc2.ae_file import AEFile -import os +import numpy as np + +standard_library.install_aliases() testfilepath = os.path.join(os.path.dirname(__file__), 'test_files/') # test file path -class TestAEFile(unittest.TestCase): +class TestAEFile(unittest.TestCase): + def test_aefile(self): ae = AEFile(testfilepath + "NREL_5MW_ae.txt") self.assertEqual(ae.thickness(38.950), 21) @@ -29,7 +37,52 @@ class TestAEFile(unittest.TestCase): self.assertEqual(ae.chord(32), 3.673) self.assertEqual(ae.pc_set_nr(32), 1) + def test_ae_file_main(self): + def no_print(s): + pass + with mock.patch.object(ae_file, "__name__", "__main__"): + with mock.patch.object(ae_file, "print", no_print): + getattr(ae_file, 'main')() + + def test_add_set(self): + ae = AEFile(testfilepath + "NREL_5MW_ae.txt") + + ae.add_set(radius=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], + chord=[1.1, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1], + thickness=[100.0, 100.0, 90.0, 80.0, 70.0, 60.0, 50.0, 40.0, 30.0, 20.0, 10.0], + pc_set_id=[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]) + + ae.add_set(radius=[0.0, 0.1], + chord=[1.1, 1.0], + thickness=[100.0, 100.0], + pc_set_id=[1.0, 1.0], + set_id=4) + + self.assertEqual(ae.thickness(38.950), 21) + self.assertEqual(ae.chord(38.950), 3.256) + self.assertEqual(ae.pc_set_nr(38.950), 1) + np.testing.assert_array_equal(ae.chord(None, 2), [1.1, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1]) + np.testing.assert_array_equal(ae.ae_sets[2][:2], ae.ae_sets[4]) + + def test_str(self): + ae = AEFile(testfilepath + "NREL_5MW_ae.txt") + ref = """1 r[m] Chord[m] T/C[%] Set no. +1 19 + 0.00000000000000000e+00 3.54199999999999982e+00 1.00000000000000000e+02 1""" + + self.assertEqual(str(ae)[:len(ref)], ref) + + def test_save(self): + ae = AEFile() + ae.add_set(radius=[0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], + chord=[1.1, 1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4, 0.3, 0.2, 0.1], + thickness=[100.0, 100.0, 90.0, 80.0, 70.0, 60.0, 50.0, 40.0, 30.0, 20.0, 10.0], + pc_set_id=[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]) + fn = testfilepath + "tmp/ae_file.txt" + ae.save(fn) + ae2 = AEFile(fn) + assert str(ae) == str(ae2) if __name__ == "__main__":