From 51db49041a6d06d389ab023d644e53d7be882f96 Mon Sep 17 00:00:00 2001 From: SabineH Date: Wed, 16 Jan 2019 15:33:33 +0100 Subject: [PATCH 01/12] Remove obsolete restructure_data function and split to two functions --- windpowerlib/wind_turbine.py | 121 +++++++++++++---------------------- 1 file changed, 46 insertions(+), 75 deletions(-) diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index a3844aeb..29e2f18e 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -168,87 +168,37 @@ def fetch_turbine_data(self, fetch_curve, data_source): ... 'fetch_curve': 'power_coefficient_curve', ... 'data_source': 'oedb'} >>> e126 = wind_turbine.WindTurbine(**enerconE126) - >>> print(e126.power_coefficient_curve['power coefficient'][5]) + >>> print(e126.power_coefficient_curve['power_coefficient'][5]) 0.44 >>> print(e126.nominal_power) 4200000.0 """ - - def restructure_data(): - r""" - Restructures data fetched from oedb or read from a csv file. - - Method creates a two-dimensional DataFrame containing the power - coefficient curve or power curve of the requested wind turbine. - - Returns - ------- - Tuple (pandas.DataFrame, float) - Power curve or power coefficient curve (pandas.DataFrame) - and nominal power (float). - Power (coefficient) curve DataFrame contains power coefficient - curve values (dimensionless) or power curve values in W with - the corresponding wind speeds in m/s. - - """ - - if data_source == 'oedb': - df = load_turbine_data_from_oedb() - df.set_index('turbine_type', inplace=True) - # Set `curve` depending on `fetch_curve` to match names in oedb - curve = ('cp_curve' if fetch_curve == 'power_coefficient_curve' - else fetch_curve) - data = df.loc[self.name][curve] - nominal_power = df.loc[self.name][ - 'installed_capacity_kw'] * 1000 - else: - df = read_turbine_data(data_source) - wpp_df = df[df.turbine_id == self.name] - # if turbine not in data file - if wpp_df.shape[0] == 0: - pd.set_option('display.max_rows', len(df)) - logging.info('Possible types: \n{0}'.format(df.turbine_id)) - pd.reset_option('display.max_rows') - sys.exit('Cannot find the wind converter type: {0}'.format( - self.name)) - # if turbine in data file write power (coefficient) curve - # values to 'data' array - ncols = ['turbine_id', 'p_nom', 'source', - 'modificationtimestamp'] - data = np.array([0, 0]) - for col in wpp_df.keys(): - if col not in ncols: - if wpp_df[col].iloc[0] is not None and not np.isnan( - float(wpp_df[col].iloc[0])): - data = np.vstack((data, np.array( - [float(col), float(wpp_df[col])]))) - data = np.delete(data, 0, 0) - nominal_power = wpp_df['p_nom'].iloc[0] - if fetch_curve == 'power_curve': - df = pd.DataFrame(data, columns=['wind_speed', 'power']) - if data_source == 'oedb': - # power values in W - df['power'] = df['power'] * 1000 - if fetch_curve == 'power_coefficient_curve': - df = pd.DataFrame(data, columns=['wind_speed', - 'power coefficient']) - return df, nominal_power - + if data_source == 'oedb': + curve_df, nominal_power = get_turbine_data_from_oedb( + turbine_type=self.name, fetch_curve=fetch_curve) + else: + curve_df, nominal_power = read_turbine_data(turbine_type=self.name, + file_=data_source) if fetch_curve == 'power_curve': - self.power_curve, p_nom = restructure_data() + curve_df.columns = ['wind_speed', 'power'] + if data_source == 'oedb': + # power values in W + curve_df['power'] = curve_df['power'] * 1000 + self.power_curve = curve_df elif fetch_curve == 'power_coefficient_curve': - self.power_coefficient_curve, p_nom = restructure_data() + curve_df.columns = ['wind_speed', 'power_coefficient'] + self.power_coefficient_curve = curve_df else: raise ValueError("'{0}' is an invalid value. ".format( fetch_curve) + "`fetch_curve` must be " + "'power_curve' or 'power_coefficient_curve'.") if self.nominal_power is None: - self.nominal_power = p_nom + self.nominal_power = nominal_power return self -def read_turbine_data(file_): +def read_turbine_data(turbine_type, file_): r""" Fetches power (coefficient) curves from a or a file. Turbine data is provided by the Open Energy Database (oedb) or can be @@ -257,7 +207,7 @@ def read_turbine_data(file_): Parameters ---------- - file_ : string + file_ : string # todo adapt Specifies the source of the turbine data. See the example below for how to use the example data. @@ -292,16 +242,30 @@ def read_turbine_data(file_): df = pd.read_csv(file_, index_col=0) except FileNotFoundError: raise FileNotFoundError("The file '{}' was not found.".format(file_)) - return df - - -def load_turbine_data_from_oedb(): + wpp_df = df[df.turbine_id == turbine_type] + # if turbine not in data file + if wpp_df.shape[0] == 0: + pd.set_option('display.max_rows', len(df)) + logging.info('Possible types: \n{0}'.format(df.turbine_id)) + pd.reset_option('display.max_rows') + sys.exit('Cannot find the wind converter type: {0}'.format( + turbine_type)) + # if turbine in data file drop nans + data = wpp_df.loc[:, wpp_df.columns != 'turbine_id'].dropna( + axis=1) + data.drop(['p_nom'], inplace=True, axis=1) + df = data.transpose().reset_index() + nominal_power = wpp_df['p_nom'].iloc[0] + return df, nominal_power + + +def get_turbine_data_from_oedb(turbine_type, fetch_curve): r""" - Loads turbine data from the Open Energy Database (oedb). + Loads and restructures turbine data from the Open Energy Database (oedb). - Returns + Returns # todo paratmeter ------- - turbine_data : pd.DataFrame + # todo adapt : pd.DataFrame Contains turbine data of different turbine types like 'manufacturer', 'turbine_type', nominal power ('installed_capacity_kw'), ' @@ -324,11 +288,18 @@ def load_turbine_data_from_oedb(): "Error: ".format(result.status_code)) # extract data turbine_data = pd.DataFrame(result.json()) + turbine_data.set_index('turbine_type', inplace=True) + # Set `curve` depending on `fetch_curve` to match names in oedb + curve = ('cp_curve' if fetch_curve == 'power_coefficient_curve' + else fetch_curve) + df = pd.DataFrame(turbine_data.loc[turbine_type][curve]) + nominal_power = turbine_data.loc[turbine_type][ + 'installed_capacity_kw'] * 1000 else: raise ImportError('If you want to load turbine data from the oedb' + 'you have to install the requests package.' + 'see https://pypi.org/project/requests/') - return turbine_data + return df, nominal_power def get_turbine_types(print_out=True): From a68fe763a0f21df9631bf328e97f85bad64d740d Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 11:07:05 +0100 Subject: [PATCH 02/12] Bug fixes --- windpowerlib/modelchain.py | 2 +- windpowerlib/wind_turbine.py | 29 ++++++++++++++++------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/windpowerlib/modelchain.py b/windpowerlib/modelchain.py index 5beec1e1..9aaf5be5 100644 --- a/windpowerlib/modelchain.py +++ b/windpowerlib/modelchain.py @@ -358,7 +358,7 @@ def calculate_power_output(self, wind_speed_hub, density_hub): self.power_plant.power_coefficient_curve[ 'wind_speed'], self.power_plant.power_coefficient_curve[ - 'power coefficient'], + 'power_coefficient'], self.power_plant.rotor_diameter, density_hub)) else: raise ValueError("'{0}' is an invalid value. ".format( diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index 29e2f18e..2019e86c 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -198,9 +198,9 @@ def fetch_turbine_data(self, fetch_curve, data_source): return self -def read_turbine_data(turbine_type, file_): +def read_turbine_data(turbine_type, file_): # todo: rename get_turbine_data_from_file r""" - Fetches power (coefficient) curves from a or a file. + Fetches power (coefficient) curves from a csv file. Turbine data is provided by the Open Energy Database (oedb) or can be provided by the user via a file. In the directory windpowerlib/data example files are provided. @@ -255,11 +255,12 @@ def read_turbine_data(turbine_type, file_): axis=1) data.drop(['p_nom'], inplace=True, axis=1) df = data.transpose().reset_index() + df['index'] = df['index'].apply(lambda x: float(x)) nominal_power = wpp_df['p_nom'].iloc[0] return df, nominal_power -def get_turbine_data_from_oedb(turbine_type, fetch_curve): +def get_turbine_data_from_oedb(turbine_type=None, fetch_curve=None): r""" Loads and restructures turbine data from the Open Energy Database (oedb). @@ -286,15 +287,17 @@ def get_turbine_data_from_oedb(turbine_type, fetch_curve): else: raise ConnectionError("Data base connection not successful. " + "Error: ".format(result.status_code)) - # extract data - turbine_data = pd.DataFrame(result.json()) - turbine_data.set_index('turbine_type', inplace=True) - # Set `curve` depending on `fetch_curve` to match names in oedb - curve = ('cp_curve' if fetch_curve == 'power_coefficient_curve' - else fetch_curve) - df = pd.DataFrame(turbine_data.loc[turbine_type][curve]) - nominal_power = turbine_data.loc[turbine_type][ - 'installed_capacity_kw'] * 1000 + + if (turbine_type is not None and fetch_curve is not None): + # extract data + turbine_data = pd.DataFrame(result.json()) + turbine_data.set_index('turbine_type', inplace=True) + # Set `curve` depending on `fetch_curve` to match names in oedb + curve = ('cp_curve' if fetch_curve == 'power_coefficient_curve' + else fetch_curve) + df = pd.DataFrame(turbine_data.loc[turbine_type][curve]) + nominal_power = turbine_data.loc[turbine_type][ + 'installed_capacity_kw'] * 1000 else: raise ImportError('If you want to load turbine data from the oedb' + 'you have to install the requests package.' + @@ -333,7 +336,7 @@ def get_turbine_types(print_out=True): """ - df = load_turbine_data_from_oedb() + df = get_turbine_data_from_oedb() cp_curves_df = df.iloc[df.loc[df['has_cp_curve'] == True].index][ ['manufacturer', 'turbine_type', 'has_cp_curve']] p_curves_df = df.iloc[df.loc[df['has_power_curve'] == True].index][ From bf10d9c63a9a3e0c37a31a5a413dd9581d398761 Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 11:22:38 +0100 Subject: [PATCH 03/12] Make read_turbine_data() more generic this way several columns can be added in the csv --- windpowerlib/wind_turbine.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index 2019e86c..1cfe8c38 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -238,6 +238,13 @@ def read_turbine_data(turbine_type, file_): # todo: rename get_turbine_data_from 150000 """ + def isfloat(x): + try: + float(x) + return x + except: + return False + try: df = pd.read_csv(file_, index_col=0) except FileNotFoundError: @@ -250,11 +257,11 @@ def read_turbine_data(turbine_type, file_): # todo: rename get_turbine_data_from pd.reset_option('display.max_rows') sys.exit('Cannot find the wind converter type: {0}'.format( turbine_type)) - # if turbine in data file drop nans - data = wpp_df.loc[:, wpp_df.columns != 'turbine_id'].dropna( - axis=1) - data.drop(['p_nom'], inplace=True, axis=1) - df = data.transpose().reset_index() + # if turbine in data file select power (coefficient) curve columns and + # drop nans + cols = [_ for _ in wpp_df.columns if isfloat(_)] + curve_data = wpp_df[cols].dropna(axis=1) + df = curve_data.transpose().reset_index() df['index'] = df['index'].apply(lambda x: float(x)) nominal_power = wpp_df['p_nom'].iloc[0] return df, nominal_power From 337bc05bf745241bd11b494c382215b164875e86 Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 11:58:51 +0100 Subject: [PATCH 04/12] Adapt example --- example/modelchain_example.ipynb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/example/modelchain_example.ipynb b/example/modelchain_example.ipynb index 675f3bdb..9467aa02 100644 --- a/example/modelchain_example.ipynb +++ b/example/modelchain_example.ipynb @@ -188,7 +188,8 @@ "12 Enercon E-82/2350 True True\n", "13 Enercon E-82/3000 True True\n", "14 Enercon E-92/2350 True True\n", - "15 Enercon E48/800 True True\n" + "15 Enercon E/126/7500 True False\n", + "16 Enercon E48/800 True True\n" ] } ], @@ -256,7 +257,7 @@ "DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): oep.iks.cs.ovgu.de:80\n", "DEBUG:urllib3.connectionpool:http://oep.iks.cs.ovgu.de:80 \"GET //api/v0/schema/model_draft/tables/openfred_windpower_powercurve/rows/ HTTP/1.1\" 301 438\n", "DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): openenergy-platform.org:80\n", - "DEBUG:urllib3.connectionpool:http://openenergy-platform.org:80 \"GET /api/v0/schema/model_draft/tables/openfred_windpower_powercurve/rows/ HTTP/1.1\" 200 149329\n", + "DEBUG:urllib3.connectionpool:http://openenergy-platform.org:80 \"GET /api/v0/schema/model_draft/tables/openfred_windpower_powercurve/rows/ HTTP/1.1\" 200 150623\n", "INFO:root:Data base connection successful.\n" ] } @@ -284,12 +285,13 @@ "source": [ "# specification of wind turbine where power coefficient curve is provided\n", "# by a csv file\n", + "source = 'data/example_coefficient_curves.csv'\n", "dummy_turbine = {\n", " 'name': 'DUMMY 1', # turbine type as in file #\n", " 'hub_height': 100, # in m\n", " 'rotor_diameter': 70, # in m\n", " 'fetch_curve': 'power_coefficient_curve', # fetch cp curve #\n", - " 'data_source': 'example_power_coefficient_curves.csv' # data source\n", + " 'data_source': source # data source\n", "}\n", "# initialize WindTurbine object\n", "dummy_turbine = WindTurbine(**dummy_turbine)" From 6949bb827c9b7f1251174e07933cfff836c9db65 Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 12:00:22 +0100 Subject: [PATCH 05/12] Rename function --- windpowerlib/wind_turbine.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index 1cfe8c38..e44c890f 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -178,8 +178,8 @@ def fetch_turbine_data(self, fetch_curve, data_source): curve_df, nominal_power = get_turbine_data_from_oedb( turbine_type=self.name, fetch_curve=fetch_curve) else: - curve_df, nominal_power = read_turbine_data(turbine_type=self.name, - file_=data_source) + curve_df, nominal_power = get_turbine_data_from_file( + turbine_type=self.name, file_=data_source) if fetch_curve == 'power_curve': curve_df.columns = ['wind_speed', 'power'] if data_source == 'oedb': @@ -198,7 +198,7 @@ def fetch_turbine_data(self, fetch_curve, data_source): return self -def read_turbine_data(turbine_type, file_): # todo: rename get_turbine_data_from_file +def get_turbine_data_from_file(turbine_type, file_): r""" Fetches power (coefficient) curves from a csv file. Turbine data is provided by the Open Energy Database (oedb) or can be From 5cb970cbe7515b319334f9443ee1eb0061f72e5d Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 12:01:06 +0100 Subject: [PATCH 06/12] Seperate database connection from curve restructuring --- windpowerlib/wind_turbine.py | 43 +++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index e44c890f..58bf68f2 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -267,9 +267,9 @@ def isfloat(x): return df, nominal_power -def get_turbine_data_from_oedb(turbine_type=None, fetch_curve=None): +def get_turbine_data_from_oedb(turbine_type, fetch_curve): r""" - Loads and restructures turbine data from the Open Energy Database (oedb). + Gets turbine data from the Open Energy Database (oedb). Returns # todo paratmeter ------- @@ -278,6 +278,28 @@ def get_turbine_data_from_oedb(turbine_type=None, fetch_curve=None): 'turbine_type', nominal power ('installed_capacity_kw'), ' """ + # extract data + turbine_data = load_turbine_data_from_oedb() + turbine_data.set_index('turbine_type', inplace=True) + # Set `curve` depending on `fetch_curve` to match names in oedb + curve = ('cp_curve' if fetch_curve == 'power_coefficient_curve' + else fetch_curve) + df = pd.DataFrame(turbine_data.loc[turbine_type][curve]) + nominal_power = turbine_data.loc[turbine_type][ + 'installed_capacity_kw'] * 1000 + return df, nominal_power + + +def load_turbine_data_from_oedb(): + r""" + Loads turbine data from the Open Energy Database (oedb). + + Returns + ------- + turbine_data : pd.DataFrame + Contains turbine data of different turbine types like 'manufacturer', + 'turbine_type', nominal power ('installed_capacity_kw'), ' + """ if rq: # url of Open Energy Platform that contains the oedb @@ -294,22 +316,13 @@ def get_turbine_data_from_oedb(turbine_type=None, fetch_curve=None): else: raise ConnectionError("Data base connection not successful. " + "Error: ".format(result.status_code)) - - if (turbine_type is not None and fetch_curve is not None): - # extract data - turbine_data = pd.DataFrame(result.json()) - turbine_data.set_index('turbine_type', inplace=True) - # Set `curve` depending on `fetch_curve` to match names in oedb - curve = ('cp_curve' if fetch_curve == 'power_coefficient_curve' - else fetch_curve) - df = pd.DataFrame(turbine_data.loc[turbine_type][curve]) - nominal_power = turbine_data.loc[turbine_type][ - 'installed_capacity_kw'] * 1000 + # extract data + turbine_data = pd.DataFrame(result.json()) else: raise ImportError('If you want to load turbine data from the oedb' + 'you have to install the requests package.' + 'see https://pypi.org/project/requests/') - return df, nominal_power + return turbine_data def get_turbine_types(print_out=True): @@ -343,7 +356,7 @@ def get_turbine_types(print_out=True): """ - df = get_turbine_data_from_oedb() + df = load_turbine_data_from_oedb() cp_curves_df = df.iloc[df.loc[df['has_cp_curve'] == True].index][ ['manufacturer', 'turbine_type', 'has_cp_curve']] p_curves_df = df.iloc[df.loc[df['has_power_curve'] == True].index][ From 7f1e1045d57037bc7699831c658e7b41dd14a647 Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 12:10:05 +0100 Subject: [PATCH 07/12] delete unnecessary import --- windpowerlib/wind_turbine.py | 1 - 1 file changed, 1 deletion(-) diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index 58bf68f2..69e57d54 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -12,7 +12,6 @@ import logging import sys import os -import numpy as np try: import requests as rq From edab4de354471c60cafac017393b8805f107a472 Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 12:10:26 +0100 Subject: [PATCH 08/12] Adapt docstrings --- windpowerlib/wind_turbine.py | 86 ++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index 69e57d54..04190d1d 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -32,7 +32,7 @@ class WindTurbine(object): hub_height : float Hub height of the wind turbine in m. rotor_diameter : None or float - Diameter of the rotor in m. + Diameter of the rotor in m. Default: None. power_coefficient_curve : None, pandas.DataFrame or dictionary Power coefficient curve of the wind turbine. DataFrame/dictionary must have 'wind_speed' and 'power_coefficient' columns/keys with wind speeds @@ -42,7 +42,7 @@ class WindTurbine(object): 'wind_speed' and 'power' columns/keys with wind speeds in m/s and the corresponding power curve value in W. Default: None. nominal_power : None or float - The nominal output of the wind turbine in W. + The nominal output of the wind turbine in W. Default: None. fetch_curve : string Parameter to specify whether a power or power coefficient curve should be retrieved from the provided turbine data. Valid options are @@ -53,9 +53,10 @@ class WindTurbine(object): data_source : string Specifies whether turbine data (f.e. nominal power, power curve, power coefficient curve) is loaded from the Open Energy Database ('oedb') or - from a csv file (''). See - `example_power_curves.csv' and `example_power_coefficient_curves.csv` - in example/data for the required form of a csv file. Default: 'oedb'. + from a csv file (''). Default: 'oedb'. + See `example_power_curves.csv' and + `example_power_coefficient_curves.csv` in example/data for the required + form of a csv file (more columns can be added). Attributes ---------- @@ -66,7 +67,7 @@ class WindTurbine(object): hub_height : float Hub height of the wind turbine in m. rotor_diameter : None or float - Diameter of the rotor in m. + Diameter of the rotor in m. Default: None. power_coefficient_curve : None, pandas.DataFrame or dictionary Power coefficient curve of the wind turbine. DataFrame/dictionary must have 'wind_speed' and 'power coefficient' columns/keys with wind speeds @@ -76,12 +77,12 @@ class WindTurbine(object): 'wind_speed' and 'power' columns/keys with wind speeds in m/s and the corresponding power curve value in W. Default: None. nominal_power : None or float - The nominal output of the wind turbine in W. + The nominal output of the wind turbine in W. Default: None. coordinates : list or None List of coordinates [lat, lon] of location for loading data. Default: None. power_output : pandas.Series - The calculated power output of the wind turbine. + The calculated power output of the wind turbine. Default: None. Notes ------ @@ -132,10 +133,15 @@ def fetch_turbine_data(self, fetch_curve, data_source): Method fetches nominal power as well as power coefficient curve or power curve from a data set provided in the Open Energy Database (oedb). You can also use this function to import your own power - (coefficient) curves. For that the wind speeds in m/s have to be in the - first row and the corresponding power coefficient curve values or power - curve values in W in a row where the first column contains the turbine - name (see directory windpowerlib/data as reference). + (coefficient) curves from a file. For that the wind speeds in m/s have + to be in the first row and the corresponding power coefficient curve + values or power curve values in W in a row where the first column + contains the turbine name. + See `example_power_curves.csv' and + `example_power_coefficient_curves.csv` in example/data for the required + form of a csv file (more columns can be added). See + :py:func:`~.get_turbine_data_from_file` for an example reading data + from a csv file. Parameters ---------- @@ -146,12 +152,8 @@ def fetch_turbine_data(self, fetch_curve, data_source): data_source : string Specifies whether turbine data (f.e. nominal power, power curve, power coefficient curve) is loaded from the Open Energy Database - ('oedb') or from a csv file (''). See - `example_power_curves.csv' and - `example_power_coefficient_curves.csv` in example/data for the - required form of a csv file. Default: 'oedb'. - See :py:func:`~.read_turbine_data` for an example reading data from - a csv file. + ('oedb') or from a csv file (''). + Default: 'oedb'. Returns ------- @@ -199,24 +201,29 @@ def fetch_turbine_data(self, fetch_curve, data_source): def get_turbine_data_from_file(turbine_type, file_): r""" - Fetches power (coefficient) curves from a csv file. - Turbine data is provided by the Open Energy Database (oedb) or can be - provided by the user via a file. In the directory windpowerlib/data example - files are provided. + Fetches power (coefficient) curve data from a csv file. + + See `example_power_curves.csv' and `example_power_coefficient_curves.csv` + in example/data for the required form of a csv file + (more columns can be added). Parameters ---------- - file_ : string # todo adapt + turbine_type : string + Specifies the turbine type of which data is fetched. + Use :py:func:`~.get_turbine_types` to see a table of all wind turbines + for which power (coefficient) curve data is provided. + file_ : string Specifies the source of the turbine data. See the example below for how to use the example data. Returns ------- - pandas.DataFrame - Power coefficient curve values (dimensionless) or power curve values - in kW with corresponding wind speeds in m/s of all available wind - turbines with turbine name in column 'turbine_type', turbine nominal - power in column 'p_nom'. + Tuple (pandas.DataFrame, float) + Power curve or power coefficient curve (pandas.DataFrame) and nominal + power (float). Power (coefficient) curve DataFrame contains power + coefficient curve values (dimensionless) or power curve values in W + with the corresponding wind speeds in m/s. Examples -------- @@ -270,11 +277,24 @@ def get_turbine_data_from_oedb(turbine_type, fetch_curve): r""" Gets turbine data from the Open Energy Database (oedb). - Returns # todo paratmeter + Parameters + ---------- + turbine_type : string + Specifies the turbine type of which data is fetched. + Use :py:func:`~.get_turbine_types` to see a table of all wind turbines + for which power (coefficient) curve data is provided. + fetch_curve : string + Parameter to specify whether a power or power coefficient curve + should be retrieved from the provided turbine data. Valid options are + 'power_curve' and 'power_coefficient_curve'. Default: None. + + Returns ------- - # todo adapt : pd.DataFrame - Contains turbine data of different turbine types like 'manufacturer', - 'turbine_type', nominal power ('installed_capacity_kw'), ' + Tuple (pandas.DataFrame, float) + Power curve or power coefficient curve (pandas.DataFrame) and nominal + power (float). Power (coefficient) curve DataFrame contains power + coefficient curve values (dimensionless) or power curve values in W + with the corresponding wind speeds in m/s. """ # extract data @@ -298,8 +318,8 @@ def load_turbine_data_from_oedb(): turbine_data : pd.DataFrame Contains turbine data of different turbine types like 'manufacturer', 'turbine_type', nominal power ('installed_capacity_kw'), ' - """ + """ if rq: # url of Open Energy Platform that contains the oedb oep_url = 'http://oep.iks.cs.ovgu.de/' From c6fe129bf046a8efbac5acc28af767b45dceed48 Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 12:19:50 +0100 Subject: [PATCH 09/12] Add KeyError raising if turbine type not in oedb --- windpowerlib/wind_turbine.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/windpowerlib/wind_turbine.py b/windpowerlib/wind_turbine.py index 04190d1d..8633ca26 100644 --- a/windpowerlib/wind_turbine.py +++ b/windpowerlib/wind_turbine.py @@ -297,13 +297,19 @@ def get_turbine_data_from_oedb(turbine_type, fetch_curve): with the corresponding wind speeds in m/s. """ - # extract data + # Extract data turbine_data = load_turbine_data_from_oedb() turbine_data.set_index('turbine_type', inplace=True) # Set `curve` depending on `fetch_curve` to match names in oedb curve = ('cp_curve' if fetch_curve == 'power_coefficient_curve' else fetch_curve) - df = pd.DataFrame(turbine_data.loc[turbine_type][curve]) + # Select curve and nominal power of turbine type + try: + df = pd.DataFrame(turbine_data.loc[turbine_type][curve]) + except KeyError: + raise KeyError("Turbine type '{}' not in database. ".format( + turbine_type) + "Use 'get_turbine_types()' to see a table of " + + "possible wind turbine types.") nominal_power = turbine_data.loc[turbine_type][ 'installed_capacity_kw'] * 1000 return df, nominal_power From e180b2f5d7abb9cd4d60b06bcae74755ff517a91 Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 12:19:58 +0100 Subject: [PATCH 10/12] Adapt and add tests --- tests/test_wind_turbine.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/tests/test_wind_turbine.py b/tests/test_wind_turbine.py index d6b49e6c..86af8c2b 100644 --- a/tests/test_wind_turbine.py +++ b/tests/test_wind_turbine.py @@ -1,18 +1,20 @@ -import pandas as pd -from pandas.util.testing import assert_series_equal import pytest +import os -from windpowerlib.wind_turbine import read_turbine_data, WindTurbine +from windpowerlib.wind_turbine import (get_turbine_data_from_file, WindTurbine, + get_turbine_types) class TestWindTurbine: def test_error_raising(self): + source = os.path.join(os.path.dirname(__file__), '../example/data', + 'example_power_curves.csv') self.test_turbine_data = {'hub_height': 100, 'rotor_diameter': 80, 'name': 'turbine_not_in_file', 'fetch_curve': 'power_curve', - 'data_source': 'example_power_curves.csv'} - # Raise system exit + 'data_source': source} + # Raise system exit due to turbine type not in file with pytest.raises(SystemExit): test_turbine = WindTurbine(**self.test_turbine_data) @@ -22,8 +24,17 @@ def test_error_raising(self): with pytest.raises(ValueError): test_turbine = WindTurbine(**self.test_turbine_data) + # Raise KeyError due to turbine type not in oedb + self.test_turbine_data['fetch_curve'] = 'power_curve' + self.test_turbine_data['data_source'] = 'oedb' + with pytest.raises(KeyError): + test_turbine = WindTurbine(**self.test_turbine_data) + + def test_read_turbine_data(self): # Raise FileNotFoundError due to missing with pytest.raises(FileNotFoundError): - read_turbine_data(filename='not_existent') + get_turbine_data_from_file(turbine_type='...', file_='not_existent') # todo test turbine type not found? + def test_get_turbine_types(self): + get_turbine_types(print_out=False) From f6bb0f4e2e138cdd8d0b9475a6385e468c4bb5ef Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 12:25:57 +0100 Subject: [PATCH 11/12] Fix notebooks --- doc/modelchain_example_notebook.ipynb | 8 +++++--- example/modelchain_example.ipynb | 2 +- example/modelchain_example.py | 1 - 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/modelchain_example_notebook.ipynb b/doc/modelchain_example_notebook.ipynb index 675f3bdb..752d0856 100644 --- a/doc/modelchain_example_notebook.ipynb +++ b/doc/modelchain_example_notebook.ipynb @@ -188,7 +188,8 @@ "12 Enercon E-82/2350 True True\n", "13 Enercon E-82/3000 True True\n", "14 Enercon E-92/2350 True True\n", - "15 Enercon E48/800 True True\n" + "15 Enercon E/126/7500 True False\n", + "16 Enercon E48/800 True True\n" ] } ], @@ -256,7 +257,7 @@ "DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): oep.iks.cs.ovgu.de:80\n", "DEBUG:urllib3.connectionpool:http://oep.iks.cs.ovgu.de:80 \"GET //api/v0/schema/model_draft/tables/openfred_windpower_powercurve/rows/ HTTP/1.1\" 301 438\n", "DEBUG:urllib3.connectionpool:Starting new HTTP connection (1): openenergy-platform.org:80\n", - "DEBUG:urllib3.connectionpool:http://openenergy-platform.org:80 \"GET /api/v0/schema/model_draft/tables/openfred_windpower_powercurve/rows/ HTTP/1.1\" 200 149329\n", + "DEBUG:urllib3.connectionpool:http://openenergy-platform.org:80 \"GET /api/v0/schema/model_draft/tables/openfred_windpower_powercurve/rows/ HTTP/1.1\" 200 150623\n", "INFO:root:Data base connection successful.\n" ] } @@ -284,12 +285,13 @@ "source": [ "# specification of wind turbine where power coefficient curve is provided\n", "# by a csv file\n", + "source = 'data/example_power_coefficient_curves.csv'\n", "dummy_turbine = {\n", " 'name': 'DUMMY 1', # turbine type as in file #\n", " 'hub_height': 100, # in m\n", " 'rotor_diameter': 70, # in m\n", " 'fetch_curve': 'power_coefficient_curve', # fetch cp curve #\n", - " 'data_source': 'example_power_coefficient_curves.csv' # data source\n", + " 'data_source': source # data source\n", "}\n", "# initialize WindTurbine object\n", "dummy_turbine = WindTurbine(**dummy_turbine)" diff --git a/example/modelchain_example.ipynb b/example/modelchain_example.ipynb index 9467aa02..752d0856 100644 --- a/example/modelchain_example.ipynb +++ b/example/modelchain_example.ipynb @@ -285,7 +285,7 @@ "source": [ "# specification of wind turbine where power coefficient curve is provided\n", "# by a csv file\n", - "source = 'data/example_coefficient_curves.csv'\n", + "source = 'data/example_power_coefficient_curves.csv'\n", "dummy_turbine = {\n", " 'name': 'DUMMY 1', # turbine type as in file #\n", " 'hub_height': 100, # in m\n", diff --git a/example/modelchain_example.py b/example/modelchain_example.py index 4443d7dc..89975cd9 100644 --- a/example/modelchain_example.py +++ b/example/modelchain_example.py @@ -135,7 +135,6 @@ def initialize_wind_turbines(): # by a csv file csv_file = os.path.join(os.path.dirname(__file__), 'data', 'example_power_coefficient_curves.csv') - # todo adapt in jupyter notebook!!! dummy_turbine = { 'name': 'DUMMY 1', # turbine type as in file # 'hub_height': 100, # in m From 870ef0920427eb44821408e490dbe02b6d5c254b Mon Sep 17 00:00:00 2001 From: SabineH Date: Thu, 17 Jan 2019 13:35:25 +0100 Subject: [PATCH 12/12] Adapt test --- tests/test_wind_turbine.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_wind_turbine.py b/tests/test_wind_turbine.py index 86af8c2b..a8156600 100644 --- a/tests/test_wind_turbine.py +++ b/tests/test_wind_turbine.py @@ -31,10 +31,10 @@ def test_error_raising(self): test_turbine = WindTurbine(**self.test_turbine_data) - def test_read_turbine_data(self): + def test_get_turbine_data_from_file(self): # Raise FileNotFoundError due to missing with pytest.raises(FileNotFoundError): - get_turbine_data_from_file(turbine_type='...', file_='not_existent') # todo test turbine type not found? + get_turbine_data_from_file(turbine_type='...', file_='not_existent') def test_get_turbine_types(self): get_turbine_types(print_out=False)