Skip to content

Commit acbdafa

Browse files
committed
Add first round of tests
1 parent a42e68f commit acbdafa

File tree

1 file changed

+213
-0
lines changed

1 file changed

+213
-0
lines changed

tests/iotools/test_meteonorm.py

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
import pandas as pd
2+
import numpy as np
3+
import pytest
4+
import pvlib
5+
from tests.conftest import RERUNS, RERUNS_DELAY
6+
7+
8+
@pytest.fixture
9+
def demo_api_key():
10+
# Demo locations:
11+
# lat=50, lon=10 (Germany)
12+
# lat=21, lon=79 (India)
13+
# lat=-3, lon=-60 (Brazil)
14+
# lat=51, lon=-114 (Canada)
15+
# lat=24, lon=33 (Egypt)
16+
return 'demo0000-0000-0000-0000-000000000000'
17+
18+
19+
@pytest.fixture
20+
def demo_url():
21+
return 'https://demo.meteonorm.com/v1/'
22+
23+
24+
@pytest.fixture
25+
def expected_meta():
26+
meta = {
27+
'altitude': 290,
28+
'frequency': '1_hour',
29+
'parameters': [
30+
{'aggregation_method': 'average',
31+
'description': 'Diffuse horizontal irradiance',
32+
'name': 'diffuse_horizontal_irradiance',
33+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
34+
{'aggregation_method': 'average',
35+
'description': 'Diffuse horizontal irradiance with shading taken into account',
36+
'name': 'diffuse_horizontal_irradiance_with_shading',
37+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
38+
{'aggregation_method': 'average',
39+
'description': 'Diffuse tilted irradiance',
40+
'name': 'diffuse_tilted_irradiance',
41+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
42+
{'aggregation_method': 'average',
43+
'description': 'Diffuse tilted irradiance with shading taken into account',
44+
'name': 'diffuse_tilted_irradiance_with_shading',
45+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
46+
{'aggregation_method': 'average',
47+
'description': 'Direct horizontal irradiance',
48+
'name': 'direct_horizontal_irradiance',
49+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
50+
{'aggregation_method': 'average',
51+
'description': 'Direct horizontal irradiance with shading taken into account',
52+
'name': 'direct_horizontal_irradiance_with_shading',
53+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
54+
{'aggregation_method': 'average',
55+
'description': 'Direct normal irradiance',
56+
'name': 'direct_normal_irradiance',
57+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
58+
{'aggregation_method': 'average',
59+
'description': 'Direct normal irradiance with shading taken into account',
60+
'name': 'direct_normal_irradiance_with_shading',
61+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
62+
{'aggregation_method': 'average',
63+
'description': 'Direct tilted irradiance',
64+
'name': 'direct_tilted_irradiance',
65+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
66+
{'aggregation_method': 'average',
67+
'description': 'Direct tilted irradiance with shading taken into account',
68+
'name': 'direct_tilted_irradiance_with_shading',
69+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
70+
{'aggregation_method': 'average',
71+
'description': 'Global horizontal clear sky irradiance',
72+
'name': 'global_clear_sky_irradiance',
73+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
74+
{'aggregation_method': 'average',
75+
'description': 'Global horizontal irradiance',
76+
'name': 'global_horizontal_irradiance',
77+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
78+
{'aggregation_method': 'average',
79+
'description': 'Global horizontal irradiance with shading taken into account',
80+
'name': 'global_horizontal_irradiance_with_shading',
81+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
82+
{'aggregation_method': 'average',
83+
'description': 'Global tilted irradiance',
84+
'name': 'global_tilted_irradiance',
85+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
86+
{'aggregation_method': 'average',
87+
'description': 'Global tilted irradiance with shading taken into account',
88+
'name': 'global_tilted_irradiance_with_shading',
89+
'unit': {'description': 'Watt per square meter', 'name': 'W/m**2'}},
90+
{'aggregation_method': 'average',
91+
'description': 'Power output per kWp installed',
92+
'name': 'pv_production',
93+
'unit': {'description': 'Watts per kilowatt peak', 'name': 'W/kWp'}},
94+
{'aggregation_method': 'average',
95+
'description': 'Power output per kWp installed, with shading taken into account',
96+
'name': 'pv_production_with_shading',
97+
'unit': {'description': 'Watts per kilowatt peak', 'name': 'W/kWp'}},
98+
{'aggregation_method': 'average',
99+
'description': 'Snow depth',
100+
'name': 'snow_depth',
101+
'unit': {'description': 'millimeters', 'name': 'mm'}},
102+
{'aggregation_method': 'average',
103+
'description': 'Air temperature, 2 m above ground.',
104+
'name': 'temperature',
105+
'unit': {'description': 'degrees Celsius', 'name': '°C'}}],
106+
'surface_azimuth': 180,
107+
'surface_tilt': 0,
108+
'time_zone': 0,
109+
'latitude': 50,
110+
'longitude': 10,
111+
}
112+
return meta
113+
114+
115+
@pytest.fixture
116+
def expected_meteonorm_index():
117+
expected_meteonorm_index = \
118+
pd.date_range('2023-01-01', '2024-12-31 23:59', freq='1h', tz='UTC')
119+
expected_meteonorm_index.freq = None
120+
return expected_meteonorm_index
121+
122+
123+
@pytest.fixture
124+
def expected_metenorm_data():
125+
# The first 12 rows of data
126+
columns = ['dhi', 'diffuse_horizontal_irradiance_with_shading', 'poa_diffuse',
127+
'diffuse_tilted_irradiance_with_shading', 'bhi',
128+
'direct_horizontal_irradiance_with_shading', 'dni',
129+
'direct_normal_irradiance_with_shading', 'poa_direct',
130+
'direct_tilted_irradiance_with_shading', 'ghi_clear', 'ghi',
131+
'global_horizontal_irradiance_with_shading', 'poa',
132+
'global_tilted_irradiance_with_shading', 'pv_production',
133+
'pv_production_with_shading', 'snow_depth', 'temp_air']
134+
expected = [
135+
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 12.25],
136+
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 11.75],
137+
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 11.75],
138+
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 11.5],
139+
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 11.25],
140+
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 11.],
141+
[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 11.],
142+
[2.5, 2.68309898, 2.67538201, 2.68309898, 0., 0., 0., 0., 0., 0., 0., 2.5,
143+
2.68309898, 2.67538201, 2.68309898, 2.34649978, 2.35326557, 0., 11.],
144+
[40.43632435, 40.41304027, 40.43632435, 40.41304027, 37.06367565, 37.06367565,
145+
288.7781947, 288.7781947, 37.06367565, 37.06367565, 98.10113439, 77.5,
146+
77.47671591, 77.5, 77.47671591, 67.02141875, 67.00150474, 0., 11.75],
147+
[60.52591348, 60.51498257, 60.52591348, 60.51498257, 104.47408652, 104.47408652,
148+
478.10101591, 478.10101591, 104.47408652, 104.47408652, 191.27910925, 165.,
149+
164.98906908, 165., 164.98906908, 140.23845, 140.22938131, 0., 12.75],
150+
[71.90169306, 71.89757085, 71.90169306, 71.89757085, 138.84830694, 138.84830694,
151+
508.02986044, 508.02986044, 138.84830694, 138.84830694, 253.85597777, 210.75,
152+
210.7458778, 210.75, 210.7458778, 177.07272956, 177.06937293, 0., 13.75],
153+
[78.20403711, 78.19681926, 78.20403711, 78.19681926, 142.79596289, 142.79596289,
154+
494.06576548, 494.06576548, 142.79596289, 142.79596289, 272.34275335, 221.,
155+
220.99278214, 221., 220.99278214, 185.179657, 185.17380523, 0., 14.],
156+
]
157+
index = pd.date_range('2023-01-01', periods=12, freq='1h', tz='UTC')
158+
index.freq = None
159+
expected = pd.DataFrame(expected, index=index, columns=columns)
160+
expected['snow_depth'] = expected['snow_depth'].astype(np.int64)
161+
return expected
162+
163+
164+
@pytest.mark.remote_data
165+
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
166+
def test_get_meteonorm_training(
167+
demo_api_key, demo_url, expected_meta, expected_meteonorm_index,
168+
expected_metenorm_data):
169+
data, meta = pvlib.iotools.get_meteonorm(
170+
latitude=50, longitude=10,
171+
start='2023-01-01', end='2025-01-01',
172+
api_key=demo_api_key,
173+
endpoint='observation/training',
174+
time_step='1h',
175+
url=demo_url)
176+
177+
assert meta == expected_meta
178+
pd.testing.assert_index_equal(data.index, expected_meteonorm_index)
179+
pd.testing.assert_frame_equal(data.iloc[:12], expected_metenorm_data)
180+
181+
182+
@pytest.mark.remote_data
183+
@pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
184+
def test_get_meteonorm_realtime(
185+
demo_api_key, demo_url, expected_meta, expected_meteonorm_index,
186+
expected_metenorm_data):
187+
data, meta = pvlib.iotools.get_meteonorm(
188+
latitude=21, longitude=79,
189+
start=pd.Timestamp.now(tz='UTC') - pd.Timedelta(hours=5),
190+
end=pd.Timestamp.now(tz='UTC') - pd.Timedelta(hours=1),
191+
surface_tilt=20, surface_azimuth=10,
192+
parameters=['ghi', 'global_horizontal_irradiance_with_shading'],
193+
api_key=demo_api_key,
194+
endpoint='/observation/realtime',
195+
time_step='1min',
196+
horizon='flat',
197+
map_variables=False,
198+
interval_index=True,
199+
url=demo_url,
200+
)
201+
assert meta['frequency'] == '1_minute'
202+
assert meta['lat'] == 21
203+
assert meta['lon'] == 79
204+
assert meta['surface_tilt'] == 20
205+
assert meta['surface_azimuth'] == 10
206+
207+
assert all(data.columns == pd.Index([
208+
'global_horizontal_irradiance',
209+
'global_horizontal_irradiance_with_shading']))
210+
assert data.shape == (241, 2)
211+
# can't test the specific index as it varies due to the
212+
# use of pd.Timestamp.now
213+
assert type(data.index) is pd.core.indexes.interval.IntervalIndex

0 commit comments

Comments
 (0)