Skip to content

Commit a234e0e

Browse files
authored
Merge pull request #96 from wind-python/features/add_warning_if_nan_values_in_weather_data
Raise a warning if there are nan values in the weather data set
2 parents a930785 + 5c7b7c6 commit a234e0e

File tree

4 files changed

+79
-26
lines changed

4 files changed

+79
-26
lines changed

tests/test_modelchain.py

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111

1212
import windpowerlib.wind_turbine as wt
1313
import windpowerlib.modelchain as mc
14+
from windpowerlib.tools import WindpowerlibUserWarning
1415

1516

1617
class TestModelChain:
1718
@classmethod
18-
def setup_class(self):
19+
def setup_class(cls):
1920
"""Setup default values"""
20-
self.test_turbine = {
21+
cls.test_turbine = {
2122
"hub_height": 100,
2223
"turbine_type": "E-126/4200",
2324
"power_curve": pd.DataFrame(
@@ -31,7 +32,7 @@ def setup_class(self):
3132
wind_speed_8m = np.array([[4.0], [5.0]])
3233
wind_speed_10m = np.array([[5.0], [6.5]])
3334
roughness_length = np.array([[0.15], [0.15]])
34-
self.weather_df = pd.DataFrame(
35+
cls.weather_df = pd.DataFrame(
3536
np.hstack(
3637
(
3738
temperature_2m,
@@ -434,23 +435,54 @@ def test_modelchain_with_power_coefficient_curve_as_dict(self):
434435

435436
def test_heigths_as_string(self):
436437
"""Test run_model if data heights are of type string."""
437-
test_turbine = {'hub_height': 100,
438-
'rotor_diameter': 80,
439-
'turbine_type': 'E-126/4200'}
438+
test_turbine = {
439+
"hub_height": 100,
440+
"rotor_diameter": 80,
441+
"turbine_type": "E-126/4200",
442+
}
440443

441444
# Convert data heights to str
442445
string_weather = self.weather_df.copy()
443-
string_weather.columns = pd.MultiIndex.from_arrays([
444-
string_weather.columns.get_level_values(0),
445-
string_weather.columns.get_level_values(1).astype(str)])
446+
string_weather.columns = pd.MultiIndex.from_arrays(
447+
[
448+
string_weather.columns.get_level_values(0),
449+
string_weather.columns.get_level_values(1).astype(str),
450+
]
451+
)
446452

447453
# Heights in the original DataFrame are of type np.int64
448-
assert isinstance(self.weather_df.columns.get_level_values(1)[0],
449-
np.int64)
454+
assert isinstance(
455+
self.weather_df.columns.get_level_values(1)[0], np.int64
456+
)
450457
assert isinstance(string_weather.columns.get_level_values(1)[0], str)
451458

452-
test_modelchain = {'power_output_model': 'power_curve',
453-
'density_corr': True}
454-
test_mc = mc.ModelChain(wt.WindTurbine(**test_turbine),
455-
**test_modelchain)
459+
test_modelchain = {
460+
"power_output_model": "power_curve",
461+
"density_corr": True,
462+
}
463+
test_mc = mc.ModelChain(
464+
wt.WindTurbine(**test_turbine), **test_modelchain
465+
)
456466
test_mc.run_model(string_weather)
467+
468+
def test_weather_with_nan_values(self, recwarn):
469+
"""Test warning if weather data contain nan values."""
470+
test_turbine = {
471+
"hub_height": 100,
472+
"rotor_diameter": 80,
473+
"turbine_type": "E-126/4200",
474+
}
475+
nan_weather = self.weather_df.copy()
476+
nan_weather.loc[1, ("temperature", 10)] = np.nan
477+
test_modelchain = {
478+
"power_output_model": "power_curve",
479+
"density_corr": True,
480+
}
481+
test_mc = mc.ModelChain(
482+
wt.WindTurbine(**test_turbine), **test_modelchain
483+
)
484+
msg = "'temperature', 10"
485+
with pytest.warns(WindpowerlibUserWarning, match=msg):
486+
test_mc.run_model(nan_weather)
487+
test_mc.run_model(self.weather_df)
488+
assert len(recwarn) == 0

windpowerlib/modelchain.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
"""
99
import logging
1010
import pandas as pd
11-
from windpowerlib import (wind_speed, density, temperature, power_output,
12-
tools)
11+
from windpowerlib import wind_speed, density, temperature, power_output, tools
1312

1413

1514
class ModelChain(object):
@@ -511,10 +510,7 @@ def run_model(self, weather_df):
511510
'wind_speed'
512511
513512
"""
514-
# Convert data heights to integer. In some case they are strings.
515-
weather_df.columns = pd.MultiIndex.from_arrays([
516-
weather_df.columns.get_level_values(0),
517-
pd.to_numeric(weather_df.columns.get_level_values(1))])
513+
weather_df = tools.check_weather_data(weather_df)
518514

519515
wind_speed_hub = self.wind_speed_hub(weather_df)
520516
density_hub = (

windpowerlib/tools.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"""
88
import numpy as np
99
import warnings
10+
import pandas as pd
1011

1112

1213
class WindpowerlibUserWarning(UserWarning):
@@ -221,3 +222,30 @@ def estimate_turbulence_intensity(height, roughness_length):
221222
222223
"""
223224
return 1 / (np.log(height / roughness_length))
225+
226+
227+
def check_weather_data(weather_df):
228+
"""
229+
Check weather Data Frame.
230+
231+
- Raise warning if there are nan values.
232+
- Convert columns if heights are string and not numeric.
233+
234+
"""
235+
# Convert data heights to integer. In some case they are strings.
236+
weather_df.columns = pd.MultiIndex.from_arrays(
237+
[
238+
weather_df.columns.get_level_values(0),
239+
pd.to_numeric(weather_df.columns.get_level_values(1)),
240+
]
241+
)
242+
243+
# check for nan values
244+
if weather_df.isnull().any().any():
245+
nan_columns = list(weather_df.columns[weather_df.isnull().any()])
246+
msg = (
247+
"The following columns of the weather data contain invalid "
248+
"values like 'nan': {0}"
249+
)
250+
warnings.warn(msg.format(nan_columns), WindpowerlibUserWarning)
251+
return weather_df

windpowerlib/turbine_cluster_modelchain.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import logging
1111
import pandas as pd
1212
from windpowerlib import wake_losses
13-
from windpowerlib.modelchain import ModelChain
13+
from windpowerlib.modelchain import ModelChain, tools
1414

1515

1616
class TurbineClusterModelChain(ModelChain):
@@ -289,10 +289,7 @@ def run_model(self, weather_df):
289289
'wind_speed'
290290
291291
"""
292-
# Convert data heights to integer. In some case they are strings.
293-
weather_df.columns = pd.MultiIndex.from_arrays([
294-
weather_df.columns.get_level_values(0),
295-
pd.to_numeric(weather_df.columns.get_level_values(1))])
292+
weather_df = tools.check_weather_data(weather_df)
296293

297294
self.assign_power_curve(weather_df)
298295
self.power_plant.mean_hub_height()

0 commit comments

Comments
 (0)