Skip to content

Commit 78ce14a

Browse files
authored
Merge pull request #66 from wind-python/concat_without_sorting
Delete sort parameter
2 parents a71c9ef + 90c4737 commit 78ce14a

File tree

8 files changed

+118
-18
lines changed

8 files changed

+118
-18
lines changed

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def read(fname):
2020
long_description=read('README.rst'),
2121
long_description_content_type='text/x-rst',
2222
zip_safe=False,
23-
install_requires=['pandas >= 0.19.1, < 0.25',
23+
install_requires=['pandas >= 0.20.0, < 0.26',
2424
'requests < 3.0'],
2525
extras_require={
2626
'dev': ['pytest', 'jupyter', 'sphinx_rtd_theme', 'nbformat',

tests/test_modelchain.py

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ def setup_class(self):
2121
"""Setup default values"""
2222
self.test_turbine = {'hub_height': 100,
2323
'turbine_type': 'E-126/4200',
24-
'power_curve': True}
24+
'power_curve': pd.DataFrame(
25+
data={'value': [0.0, 4200 * 1000],
26+
'wind_speed': [0.0, 25.0]})}
2527

2628
temperature_2m = np.array([[267], [268]])
2729
temperature_10m = np.array([[267], [266]])
@@ -303,3 +305,40 @@ def test_missing_p_values(self):
303305
test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine),
304306
**test_modelchain)
305307
test_mc.run_model(self.weather_df)
308+
309+
def test_modelchain_with_power_curve_as_dict(self):
310+
"""Test power curves as dict"""
311+
my_turbine = {'nominal_power': 3e6, 'hub_height': 105,
312+
'rotor_diameter': 70,
313+
'power_curve': {
314+
'value': [p * 1000 for p in [
315+
0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]],
316+
'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]},
317+
'power_coefficient_curve': {
318+
'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03],
319+
'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}}
320+
power_output_exp = pd.Series(data=[919055.54840,
321+
1541786.60559],
322+
name='feedin_power_plant')
323+
test_mc = mc.ModelChain(wt.WindTurbine(**my_turbine))
324+
test_mc.run_model(self.weather_df)
325+
assert_series_equal(test_mc.power_output, power_output_exp)
326+
327+
def test_modelchain_with_power_coefficient_curve_as_dict(self):
328+
"""Test power coefficient curves as dict"""
329+
my_turbine = {'nominal_power': 3e6, 'hub_height': 105,
330+
'rotor_diameter': 70,
331+
'power_curve': {
332+
'value': [p * 1000 for p in [
333+
0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]],
334+
'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]},
335+
'power_coefficient_curve': {
336+
'value': [0.0, 0.43, 0.45, 0.35, 0.12, 0.03],
337+
'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}}
338+
power_output_exp = pd.Series(data=[469518.35104,
339+
901794.28532],
340+
name='feedin_power_plant')
341+
test_mc = mc.ModelChain(wt.WindTurbine(**my_turbine),
342+
power_output_model='power_coefficient_curve')
343+
test_mc.run_model(self.weather_df)
344+
assert_series_equal(test_mc.power_output, power_output_exp)

tests/test_turbine_cluster_modelchain.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,7 @@ def setup_class(self):
4040
self.test_turbine_2 = {'hub_height': 90,
4141
'rotor_diameter': 60,
4242
'turbine_type': 'V90/2000',
43-
'nominal_power': 2000000.0
44-
}
43+
'nominal_power': 2000000.0}
4544
self.test_farm = {'wind_turbine_fleet': [
4645
{'wind_turbine':
4746
wt.WindTurbine(**self.test_turbine),
@@ -191,17 +190,18 @@ def test_error_raising(self):
191190

192191
# Raise ValueError when aggregated wind farm power curve needs to be
193192
# calculated but turbine does not have a power curve
194-
test_turbine = {
193+
test_turbine_data = {
195194
'hub_height': 100,
196195
'rotor_diameter': 98,
197-
'turbine_type': 'V90/2000',
198-
'power_curve': True}
196+
'turbine_type': 'V90/2000'}
197+
test_turbine = wt.WindTurbine(**test_turbine_data)
198+
test_turbine.power_curve = True
199199
test_farm = {'wind_turbine_fleet':
200200
[{'wind_turbine':
201201
wt.WindTurbine(**self.test_turbine),
202202
'number_of_turbines': 3},
203203
{'wind_turbine':
204-
wt.WindTurbine(**test_turbine),
204+
test_turbine,
205205
'number_of_turbines': 3}]}
206206
test_tc_mc = tc_mc.TurbineClusterModelChain(
207207
power_plant=wf.WindFarm(**test_farm))
@@ -244,3 +244,26 @@ def test_wind_turbine_cluster_repr_without_name(self):
244244
wf.WindFarm(**self.test_farm_2)]}
245245
assert 'Wind turbine cluster with:' in repr(
246246
wtc.WindTurbineCluster(**test_cluster))
247+
248+
def test_tc_modelchain_with_power_curve_as_dict(self):
249+
"""Test power curves as dict in TurbineClusterModelChain.run_model()"""
250+
my_turbine = {'nominal_power': 3e6, 'hub_height': 105,
251+
'power_curve': {
252+
'value': [p * 1000 for p in [
253+
0.0, 26.0, 180.0, 1500.0, 3000.0, 3000.0]],
254+
'wind_speed': [0.0, 3.0, 5.0, 10.0, 15.0, 25.0]}}
255+
my_farm = {'wind_turbine_fleet':
256+
[{'wind_turbine': wt.WindTurbine(**my_turbine),
257+
'number_of_turbines': 3},
258+
{'wind_turbine': wt.WindTurbine(**self.test_turbine),
259+
'number_of_turbines': 3}]}
260+
my_cluster = {'wind_farms': [wf.WindFarm(**my_farm),
261+
wf.WindFarm(**self.test_farm)]}
262+
power_output_exp = pd.Series(data=[10853277.966972714,
263+
21731814.593688786],
264+
name='feedin_power_plant')
265+
# run model with my_cluster
266+
test_tc_mc = tc_mc.TurbineClusterModelChain(
267+
power_plant=wtc.WindTurbineCluster(**my_cluster))
268+
test_tc_mc.run_model(self.weather_df)
269+
assert_series_equal(test_tc_mc.power_output, power_output_exp)

tests/test_wind_turbine.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,29 @@ def test_get_turbine_types(self, capsys):
4242

4343
def test_wrong_url_load_turbine_data(self):
4444
"""Load turbine data from oedb."""
45-
4645
with pytest.raises(ConnectionError,
4746
match="Database connection not successful"):
4847
load_turbine_data_from_oedb('wrong_schema')
4948

5049
@pytest.mark.filterwarnings("ignore:The WindTurbine")
5150
def test_string_representation_of_wind_turbine(self):
5251
assert "Wind turbine: ['hub height=120 m'" in repr(WindTurbine(120))
52+
53+
def test_power_curve_is_of_wrong_type(self):
54+
"""Error raising due to wrong type of WindTurbine.power_curve."""
55+
test_turbine_data = {'hub_height': 100,
56+
'rotor_diameter': 80,
57+
'turbine_type': 'test_type',
58+
'power_curve': 'string'}
59+
with pytest.raises(TypeError):
60+
WindTurbine(**test_turbine_data)
61+
62+
def test_power_coefficient_curve_is_of_wrong_type(self):
63+
"""Error raising due to wrong type of
64+
WindTurbine.power_coefficient_curve."""
65+
test_turbine_data = {'hub_height': 100,
66+
'rotor_diameter': 80,
67+
'turbine_type': 'test_type',
68+
'power_coefficient_curve': 'string'}
69+
with pytest.raises(TypeError):
70+
WindTurbine(**test_turbine_data)

windpowerlib/modelchain.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@ class ModelChain(object):
127127
>>> enerconE126 = {
128128
... 'hub_height': 135,
129129
... 'rotor_diameter': 127,
130-
... 'turbine_type': 'E-126/4200',
131-
... 'power_curve': True}
130+
... 'turbine_type': 'E-126/4200'}
132131
>>> e126 = wind_turbine.WindTurbine(**enerconE126)
133132
>>> modelchain_data = {'density_model': 'ideal_gas'}
134133
>>> e126_mc = modelchain.ModelChain(e126, **modelchain_data)

windpowerlib/wind_farm.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -362,14 +362,13 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency',
362362
power_curve = pd.concat(
363363
[pd.DataFrame(data={
364364
'value': [0.0], 'wind_speed': [0.0]}),
365-
power_curve], sort=True)
365+
power_curve], join='inner')
366366
if power_curve.iloc[-1]['value'] != 0.0:
367367
power_curve = pd.concat(
368368
[power_curve, pd.DataFrame(data={
369-
'value': [0.0], 'wind_speed': [
370-
power_curve['wind_speed'].loc[
371-
power_curve.index[-1]] + 0.5]})],
372-
sort=True)
369+
'wind_speed': [power_curve['wind_speed'].loc[
370+
power_curve.index[-1]] + 0.5],
371+
'value': [0.0]})], join='inner')
373372
# Add power curves of all turbine types to data frame
374373
# (multiplied by turbine amount)
375374
df = pd.concat(
@@ -379,7 +378,7 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency',
379378
wind_farm_power_curve = pd.DataFrame(
380379
df.interpolate(method='index').sum(axis=1))
381380
wind_farm_power_curve.columns = ['value']
382-
wind_farm_power_curve.reset_index('wind_speed', inplace=True)
381+
wind_farm_power_curve.reset_index(inplace=True)
383382
# Apply power curve smoothing and consideration of wake losses
384383
# after the summation
385384
if smoothing and smoothing_order == 'wind_farm_power_curves':

windpowerlib/wind_turbine.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,28 @@ def __init__(self, hub_height, nominal_power=None, path='oedb',
172172
" Check if the turbine type {0} is in your database file"
173173
" or if you passed a valid curve.")
174174
warnings.warn(msg.format(turbine_type), WindpowerlibUserWarning)
175+
else:
176+
# power (coefficient) curve to pd.DataFrame in case of being dict
177+
if isinstance(self.power_curve, dict):
178+
self.power_curve = pd.DataFrame(self.power_curve)
179+
if isinstance(self.power_coefficient_curve, dict):
180+
self.power_coefficient_curve = pd.DataFrame(
181+
self.power_coefficient_curve)
182+
# sort power (coefficient) curve by wind speed
183+
if isinstance(self.power_curve, pd.DataFrame):
184+
self.power_curve.sort_values(by='wind_speed')
185+
elif self.power_curve is not None:
186+
msg = "Type of power curve of {} is {} but should be " \
187+
"pd.DataFrame or dict."
188+
raise TypeError(msg.format(self.__repr__(),
189+
type(self.power_curve)))
190+
if isinstance(self.power_coefficient_curve, pd.DataFrame):
191+
self.power_coefficient_curve.sort_values(by='wind_speed')
192+
elif self.power_coefficient_curve is not None:
193+
msg = "Type of power coefficient curve of {} is {} but " \
194+
"should be pd.DataFrame or dict."
195+
raise TypeError(msg.format(self.__repr__(),
196+
type(self.power_coefficient_curve)))
175197

176198
def __repr__(self):
177199
info = []

windpowerlib/wind_turbine_cluster.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,6 @@ def assign_power_curve(self, wake_losses_model='wind_farm_efficiency',
222222
df.interpolate(method='index').sum(axis=1))
223223
cluster_power_curve.columns = ['value']
224224
# Return wind speed (index) to a column of the data frame
225-
cluster_power_curve.reset_index('wind_speed', inplace=True)
225+
cluster_power_curve.reset_index(inplace=True)
226226
self.power_curve = cluster_power_curve
227227
return self

0 commit comments

Comments
 (0)