pvlib 0.9.5__py3-none-any.whl → 0.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. pvlib/__init__.py +3 -2
  2. pvlib/atmosphere.py +6 -171
  3. pvlib/bifacial/infinite_sheds.py +30 -267
  4. pvlib/bifacial/utils.py +225 -5
  5. pvlib/data/test_psm3_2017.csv +17521 -17521
  6. pvlib/data/test_read_psm3.csv +17522 -17522
  7. pvlib/data/test_read_pvgis_horizon.csv +49 -0
  8. pvlib/data/variables_style_rules.csv +3 -0
  9. pvlib/iam.py +17 -4
  10. pvlib/inverter.py +6 -1
  11. pvlib/iotools/__init__.py +7 -2
  12. pvlib/iotools/acis.py +516 -0
  13. pvlib/iotools/midc.py +4 -4
  14. pvlib/iotools/psm3.py +32 -31
  15. pvlib/iotools/pvgis.py +84 -28
  16. pvlib/iotools/sodapro.py +8 -6
  17. pvlib/iotools/srml.py +121 -18
  18. pvlib/iotools/surfrad.py +2 -2
  19. pvlib/iotools/tmy.py +146 -102
  20. pvlib/irradiance.py +151 -0
  21. pvlib/ivtools/sde.py +11 -7
  22. pvlib/ivtools/sdm.py +16 -10
  23. pvlib/ivtools/utils.py +6 -6
  24. pvlib/location.py +3 -2
  25. pvlib/modelchain.py +67 -70
  26. pvlib/pvsystem.py +160 -532
  27. pvlib/shading.py +41 -0
  28. pvlib/singlediode.py +215 -65
  29. pvlib/soiling.py +3 -3
  30. pvlib/spa.py +327 -368
  31. pvlib/spectrum/__init__.py +8 -2
  32. pvlib/spectrum/mismatch.py +335 -0
  33. pvlib/temperature.py +1 -8
  34. pvlib/tests/bifacial/test_infinite_sheds.py +0 -111
  35. pvlib/tests/bifacial/test_utils.py +101 -4
  36. pvlib/tests/conftest.py +0 -31
  37. pvlib/tests/iotools/test_acis.py +213 -0
  38. pvlib/tests/iotools/test_midc.py +6 -6
  39. pvlib/tests/iotools/test_psm3.py +3 -3
  40. pvlib/tests/iotools/test_pvgis.py +21 -14
  41. pvlib/tests/iotools/test_sodapro.py +1 -1
  42. pvlib/tests/iotools/test_srml.py +71 -6
  43. pvlib/tests/iotools/test_tmy.py +43 -8
  44. pvlib/tests/ivtools/test_sde.py +19 -17
  45. pvlib/tests/ivtools/test_sdm.py +9 -4
  46. pvlib/tests/test_atmosphere.py +6 -62
  47. pvlib/tests/test_iam.py +12 -0
  48. pvlib/tests/test_irradiance.py +40 -2
  49. pvlib/tests/test_location.py +1 -1
  50. pvlib/tests/test_modelchain.py +33 -76
  51. pvlib/tests/test_pvsystem.py +366 -201
  52. pvlib/tests/test_shading.py +28 -0
  53. pvlib/tests/test_singlediode.py +166 -30
  54. pvlib/tests/test_soiling.py +8 -7
  55. pvlib/tests/test_spa.py +6 -7
  56. pvlib/tests/test_spectrum.py +145 -1
  57. pvlib/tests/test_temperature.py +0 -7
  58. pvlib/tests/test_tools.py +25 -0
  59. pvlib/tests/test_tracking.py +0 -149
  60. pvlib/tools.py +26 -1
  61. pvlib/tracking.py +1 -269
  62. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/METADATA +1 -9
  63. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/RECORD +67 -68
  64. pvlib/forecast.py +0 -1211
  65. pvlib/iotools/ecmwf_macc.py +0 -312
  66. pvlib/tests/iotools/test_ecmwf_macc.py +0 -162
  67. pvlib/tests/test_forecast.py +0 -228
  68. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/AUTHORS.md +0 -0
  69. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/LICENSE +0 -0
  70. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/WHEEL +0 -0
  71. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,213 @@
1
+ """
2
+ tests for :mod:`pvlib.iotools.acis`
3
+ """
4
+
5
+ import pandas as pd
6
+ import numpy as np
7
+ import pytest
8
+ from pvlib.iotools import (
9
+ get_acis_prism, get_acis_nrcc, get_acis_mpe,
10
+ get_acis_station_data, get_acis_available_stations
11
+ )
12
+ from ..conftest import RERUNS, RERUNS_DELAY, assert_frame_equal
13
+ from requests import HTTPError
14
+
15
+
16
+ @pytest.mark.remote_data
17
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
18
+ def test_get_acis_prism():
19
+ # map_variables=True
20
+ df, meta = get_acis_prism(40.001, -80.001, '2020-01-01', '2020-01-02')
21
+ expected = pd.DataFrame(
22
+ [
23
+ [0.5, 5, 0, 2.5, 0, 62, 0],
24
+ [0, 5, -3, 1, 0, 64, 0]
25
+ ],
26
+ columns=['precipitation', 'temp_air_max', 'temp_air_min',
27
+ 'temp_air_average', 'cooling_degree_days',
28
+ 'heating_degree_days', 'growing_degree_days'],
29
+ index=pd.to_datetime(['2020-01-01', '2020-01-02']),
30
+ )
31
+ assert_frame_equal(df, expected)
32
+ expected_meta = {'latitude': 40, 'longitude': -80, 'altitude': 298.0944}
33
+ assert meta == expected_meta
34
+
35
+ # map_variables=False
36
+ df, meta = get_acis_prism(40.001, -80.001, '2020-01-01', '2020-01-02',
37
+ map_variables=False)
38
+ expected.columns = ['pcpn', 'maxt', 'mint', 'avgt', 'cdd', 'hdd', 'gdd']
39
+ assert_frame_equal(df, expected)
40
+ expected_meta = {'lat': 40, 'lon': -80, 'elev': 298.0944}
41
+ assert meta == expected_meta
42
+
43
+
44
+ @pytest.mark.remote_data
45
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
46
+ @pytest.mark.parametrize('grid, expected', [
47
+ (1, [[0.51, 5, 0, 2.5, 0, 62, 0]]),
48
+ (3, [[0.51, 5, -1, 2.0, 0, 63, 0]])
49
+ ])
50
+ def test_get_acis_nrcc(grid, expected):
51
+ # map_variables=True
52
+ df, meta = get_acis_nrcc(40.001, -80.001, '2020-01-01', '2020-01-01', grid)
53
+ expected = pd.DataFrame(
54
+ expected,
55
+ columns=['precipitation', 'temp_air_max', 'temp_air_min',
56
+ 'temp_air_average', 'cooling_degree_days',
57
+ 'heating_degree_days', 'growing_degree_days'],
58
+ index=pd.to_datetime(['2020-01-01']),
59
+ )
60
+ assert_frame_equal(df, expected)
61
+ expected_meta = {'latitude': 40., 'longitude': -80., 'altitude': 356.9208}
62
+ assert meta == pytest.approx(expected_meta)
63
+
64
+ # map_variables=False
65
+ df, meta = get_acis_nrcc(40.001, -80.001, '2020-01-01', '2020-01-01', grid,
66
+ map_variables=False)
67
+ expected.columns = ['pcpn', 'maxt', 'mint', 'avgt', 'cdd', 'hdd', 'gdd']
68
+ assert_frame_equal(df, expected)
69
+ expected_meta = {'lat': 40., 'lon': -80., 'elev': 356.9208}
70
+ assert meta == pytest.approx(expected_meta)
71
+
72
+
73
+ @pytest.mark.remote_data
74
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
75
+ def test_get_acis_nrcc_error():
76
+ with pytest.raises(HTTPError, match='invalid grid'):
77
+ # 50 is not a valid dataset (or "grid", in ACIS lingo)
78
+ _ = get_acis_nrcc(40, -80, '2012-01-01', '2012-01-01', 50)
79
+
80
+
81
+ @pytest.mark.remote_data
82
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
83
+ def test_get_acis_mpe():
84
+ # map_variables=True
85
+ df, meta = get_acis_mpe(40.001, -80.001, '2020-01-01', '2020-01-02')
86
+ expected = pd.DataFrame(
87
+ {'precipitation': [0.4, 0.0]},
88
+ index=pd.to_datetime(['2020-01-01', '2020-01-02']),
89
+ )
90
+ assert_frame_equal(df, expected)
91
+ expected_meta = {'latitude': 40.0083, 'longitude': -79.9653}
92
+ assert meta == expected_meta
93
+
94
+ # map_variables=False
95
+ df, meta = get_acis_mpe(40.001, -80.001, '2020-01-01', '2020-01-02',
96
+ map_variables=False)
97
+ expected.columns = ['pcpn']
98
+ assert_frame_equal(df, expected)
99
+ expected_meta = {'lat': 40.0083, 'lon': -79.9653}
100
+ assert meta == expected_meta
101
+
102
+
103
+ @pytest.mark.remote_data
104
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
105
+ def test_get_acis_station_data():
106
+ # map_variables=True
107
+ df, meta = get_acis_station_data('ORD', '2020-01-10', '2020-01-12',
108
+ trace_val=-99)
109
+ expected = pd.DataFrame(
110
+ [[10., 2., 6., np.nan, 21.34, 0., 0., 0., 59., 0.],
111
+ [3., -4., -0.5, np.nan, 9.4, 5.3, 0., 0., 65., 0.],
112
+ [-1., -5., -3., np.nan, -99, -99, 5., 0., 68., 0.]],
113
+ columns=['temp_air_max', 'temp_air_min', 'temp_air_average',
114
+ 'temp_air_observation', 'precipitation', 'snowfall',
115
+ 'snowdepth', 'cooling_degree_days',
116
+ 'heating_degree_days', 'growing_degree_days'],
117
+ index=pd.to_datetime(['2020-01-10', '2020-01-11', '2020-01-12']),
118
+ )
119
+ assert_frame_equal(df, expected)
120
+ expected_meta = {
121
+ 'uid': 48,
122
+ 'state': 'IL',
123
+ 'name': 'CHICAGO OHARE INTL AP',
124
+ 'altitude': 204.8256,
125
+ 'latitude': 41.96017,
126
+ 'longitude': -87.93164
127
+ }
128
+ expected_meta = {
129
+ 'valid_daterange': [
130
+ ['1958-11-01', '2023-06-15'],
131
+ ['1958-11-01', '2023-06-15'],
132
+ ['1958-11-01', '2023-06-15'],
133
+ [],
134
+ ['1958-11-01', '2023-06-15'],
135
+ ['1958-11-01', '2023-06-15'],
136
+ ['1958-11-01', '2023-06-15'],
137
+ ['1958-11-01', '2023-06-15'],
138
+ ['1958-11-01', '2023-06-15'],
139
+ ['1958-11-01', '2023-06-15']
140
+ ],
141
+ 'name': 'CHICAGO OHARE INTL AP',
142
+ 'sids': ['94846 1', '111549 2', 'ORD 3', '72530 4', 'KORD 5',
143
+ 'USW00094846 6', 'ORD 7', 'USW00094846 32'],
144
+ 'county': '17031',
145
+ 'state': 'IL',
146
+ 'climdiv': 'IL02',
147
+ 'uid': 48,
148
+ 'tzo': -6.0,
149
+ 'sid_dates': [
150
+ ['94846 1', '1989-01-19', '9999-12-31'],
151
+ ['94846 1', '1958-10-30', '1989-01-01'],
152
+ ['111549 2', '1989-01-19', '9999-12-31'],
153
+ ['111549 2', '1958-10-30', '1989-01-01'],
154
+ ['ORD 3', '1989-01-19', '9999-12-31'],
155
+ ['ORD 3', '1958-10-30', '1989-01-01'],
156
+ ['72530 4', '1989-01-19', '9999-12-31'],
157
+ ['72530 4', '1958-10-30', '1989-01-01'],
158
+ ['KORD 5', '1989-01-19', '9999-12-31'],
159
+ ['KORD 5', '1958-10-30', '1989-01-01'],
160
+ ['USW00094846 6', '1989-01-19', '9999-12-31'],
161
+ ['USW00094846 6', '1958-10-30', '1989-01-01'],
162
+ ['ORD 7', '1989-01-19', '9999-12-31'],
163
+ ['ORD 7', '1958-10-30', '1989-01-01'],
164
+ ['USW00094846 32', '1989-01-19', '9999-12-31'],
165
+ ['USW00094846 32', '1958-10-30', '1989-01-01']],
166
+ 'altitude': 204.8256,
167
+ 'longitude': -87.93164,
168
+ 'latitude': 41.96017
169
+ }
170
+ # don't check valid dates since they get extended every day
171
+ meta.pop("valid_daterange")
172
+ expected_meta.pop("valid_daterange")
173
+ assert meta == expected_meta
174
+
175
+ # map_variables=False
176
+ df, meta = get_acis_station_data('ORD', '2020-01-10', '2020-01-12',
177
+ trace_val=-99, map_variables=False)
178
+ expected.columns = ['maxt', 'mint', 'avgt', 'obst', 'pcpn', 'snow',
179
+ 'snwd', 'cdd', 'hdd', 'gdd']
180
+ assert_frame_equal(df, expected)
181
+ expected_meta['lat'] = expected_meta.pop('latitude')
182
+ expected_meta['lon'] = expected_meta.pop('longitude')
183
+ expected_meta['elev'] = expected_meta.pop('altitude')
184
+ meta.pop("valid_daterange")
185
+ assert meta == expected_meta
186
+
187
+
188
+ @pytest.mark.remote_data
189
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
190
+ def test_get_acis_available_stations():
191
+ # use a very narrow bounding box to hopefully make this test less likely
192
+ # to fail due to new stations being added in the future
193
+ lat, lon = 39.8986, -80.1656
194
+ stations = get_acis_available_stations([lat - 0.0001, lat + 0.0001],
195
+ [lon - 0.0001, lon + 0.0001])
196
+ assert len(stations) == 1
197
+ station = stations.iloc[0]
198
+
199
+ # test the more relevant values
200
+ assert station['name'] == 'WAYNESBURG 1 E'
201
+ assert station['sids'] == ['369367 2', 'USC00369367 6', 'WYNP1 7']
202
+ assert station['state'] == 'PA'
203
+ assert station['altitude'] == 940.
204
+ assert station['tzo'] == -5.0
205
+ assert station['latitude'] == lat
206
+ assert station['longitude'] == lon
207
+
208
+ # check that start/end work as filters
209
+ stations = get_acis_available_stations([lat - 0.0001, lat + 0.0001],
210
+ [lon - 0.0001, lon + 0.0001],
211
+ start='1900-01-01',
212
+ end='1900-01-02')
213
+ assert stations.empty
@@ -27,9 +27,9 @@ MIDC_RAW_SHORT_HEADER_TESTFILE = (
27
27
  # '?site=UAT&begin=20181018&end=20181019')
28
28
 
29
29
 
30
- def test_midc_format_index():
30
+ def test_midc__format_index():
31
31
  data = pd.read_csv(MIDC_TESTFILE)
32
- data = midc.format_index(data)
32
+ data = midc._format_index(data)
33
33
  start = pd.Timestamp("20181014 00:00")
34
34
  start = start.tz_localize("MST")
35
35
  end = pd.Timestamp("20181014 23:59")
@@ -39,16 +39,16 @@ def test_midc_format_index():
39
39
  assert data.index[-1] == end
40
40
 
41
41
 
42
- def test_midc_format_index_tz_conversion():
42
+ def test_midc__format_index_tz_conversion():
43
43
  data = pd.read_csv(MIDC_TESTFILE)
44
44
  data = data.rename(columns={'MST': 'PST'})
45
- data = midc.format_index(data)
45
+ data = midc._format_index(data)
46
46
  assert data.index[0].tz == pytz.timezone('Etc/GMT+8')
47
47
 
48
48
 
49
- def test_midc_format_index_raw():
49
+ def test_midc__format_index_raw():
50
50
  data = pd.read_csv(MIDC_RAW_TESTFILE)
51
- data = midc.format_index_raw(data)
51
+ data = midc._format_index_raw(data)
52
52
  start = pd.Timestamp('20181018 00:00')
53
53
  start = start.tz_localize('MST')
54
54
  end = pd.Timestamp('20181018 23:59')
@@ -170,11 +170,11 @@ def test_read_psm3():
170
170
  def test_read_psm3_map_variables():
171
171
  """test read_psm3 map_variables=True"""
172
172
  data, metadata = psm3.read_psm3(MANUAL_TEST_DATA, map_variables=True)
173
- columns_mapped = ['Year', 'Month', 'Day', 'Hour', 'Minute', 'dhi', 'dni',
174
- 'ghi', 'dhi_clear', 'dni_clear', 'ghi_clear',
173
+ columns_mapped = ['Year', 'Month', 'Day', 'Hour', 'Minute', 'dhi', 'ghi',
174
+ 'dni', 'ghi_clear', 'dhi_clear', 'dni_clear',
175
175
  'Cloud Type', 'Dew Point', 'solar_zenith',
176
176
  'Fill Flag', 'albedo', 'wind_speed',
177
- 'precipitable_water', 'wind_direction',
177
+ 'wind_direction', 'precipitable_water',
178
178
  'relative_humidity', 'temp_air', 'pressure']
179
179
  data, metadata = psm3.read_psm3(MANUAL_TEST_DATA, map_variables=True)
180
180
  assert_index_equal(data.columns, pd.Index(columns_mapped))
@@ -9,8 +9,9 @@ import pytest
9
9
  import requests
10
10
  from pvlib.iotools import get_pvgis_tmy, read_pvgis_tmy
11
11
  from pvlib.iotools import get_pvgis_hourly, read_pvgis_hourly
12
+ from pvlib.iotools import get_pvgis_horizon
12
13
  from ..conftest import (DATA_DIR, RERUNS, RERUNS_DELAY, assert_frame_equal,
13
- fail_on_pvlib_version)
14
+ fail_on_pvlib_version, assert_series_equal)
14
15
  from pvlib._deprecation import pvlibDeprecationWarning
15
16
 
16
17
 
@@ -206,14 +207,14 @@ def test_read_pvgis_hourly_bad_extension():
206
207
 
207
208
 
208
209
  args_radiation_csv = {
209
- 'surface_tilt': 30, 'surface_azimuth': 0, 'outputformat': 'csv',
210
+ 'surface_tilt': 30, 'surface_azimuth': 180, 'outputformat': 'csv',
210
211
  'usehorizon': False, 'userhorizon': None, 'raddatabase': 'PVGIS-SARAH',
211
212
  'start': 2016, 'end': 2016, 'pvcalculation': False, 'components': True}
212
213
 
213
214
  url_hourly_radiation_csv = 'https://re.jrc.ec.europa.eu/api/seriescalc?lat=45&lon=8&outputformat=csv&angle=30&aspect=0&usehorizon=0&pvtechchoice=crystSi&mountingplace=free&trackingtype=0&components=1&raddatabase=PVGIS-SARAH&startyear=2016&endyear=2016' # noqa: E501
214
215
 
215
216
  args_pv_json = {
216
- 'surface_tilt': 30, 'surface_azimuth': 0, 'outputformat': 'json',
217
+ 'surface_tilt': 30, 'surface_azimuth': 180, 'outputformat': 'json',
217
218
  'usehorizon': True, 'userhorizon': None, 'raddatabase': 'PVGIS-SARAH2',
218
219
  'start': pd.Timestamp(2013, 1, 1), 'end': pd.Timestamp(2014, 5, 1),
219
220
  'pvcalculation': True, 'peakpower': 10, 'pvtechchoice': 'CIS', 'loss': 5,
@@ -364,17 +365,6 @@ def pvgis_tmy_mapped_columns():
364
365
  'wind_speed', 'wind_direction', 'pressure']
365
366
 
366
367
 
367
- @fail_on_pvlib_version('0.10')
368
- @pytest.mark.remote_data
369
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
370
- def test_pvgis_tmy_variable_map_deprecating_warning_0_10():
371
- with pytest.warns(pvlibDeprecationWarning, match='names will be renamed'):
372
- _ = get_pvgis_tmy(45, 8)
373
- with pytest.warns(pvlibDeprecationWarning, match='names will be renamed'):
374
- fn = DATA_DIR / 'tmy_45.000_8.000_2005_2016.epw'
375
- _ = read_pvgis_tmy(fn)
376
-
377
-
378
368
  @pytest.mark.remote_data
379
369
  @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
380
370
  def test_get_pvgis_tmy(expected, month_year_expected, inputs_expected,
@@ -509,6 +499,23 @@ def test_get_pvgis_map_variables(pvgis_tmy_mapped_columns):
509
499
  assert all([c in pvgis_tmy_mapped_columns for c in actual.columns])
510
500
 
511
501
 
502
+ @pytest.mark.remote_data
503
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
504
+ def test_read_pvgis_horizon():
505
+ pvgis_data, _ = get_pvgis_horizon(35.171051, -106.465158)
506
+ horizon_data = pd.read_csv(DATA_DIR / 'test_read_pvgis_horizon.csv',
507
+ index_col=0)
508
+ horizon_data = horizon_data['horizon_elevation']
509
+ assert_series_equal(pvgis_data, horizon_data)
510
+
511
+
512
+ @pytest.mark.remote_data
513
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
514
+ def test_read_pvgis_horizon_invalid_coords():
515
+ with pytest.raises(requests.HTTPError, match='lat: Incorrect value'):
516
+ _, _ = get_pvgis_horizon(100, 50) # unfeasible latitude
517
+
518
+
512
519
  def test_read_pvgis_tmy_map_variables(pvgis_tmy_mapped_columns):
513
520
  fn = DATA_DIR / 'tmy_45.000_8.000_2005_2016.json'
514
521
  actual, _, _, _ = read_pvgis_tmy(fn, map_variables=True)
@@ -209,7 +209,7 @@ def test_get_cams(requests_mock, testfile, index, columns, values, dtypes,
209
209
  mock_response = test_file.read()
210
210
  # Specify the full URI of a specific example, this ensures that all of the
211
211
  # inputs are passing on correctly
212
- url_test_cams = f'https://www.soda-is.com/service/wps?DataInputs=latitude=55.7906;longitude=12.5251;altitude=80;date_begin=2020-01-01;date_end=2020-05-04;time_ref=UT;summarization=P01M;username=pvlib-admin%2540googlegroups.com;verbose=false&Service=WPS&Request=Execute&Identifier=get_{identifier}&version=1.0.0&RawDataOutput=irradiation' # noqa: E501
212
+ url_test_cams = f'https://api.soda-solardata.com/service/wps?DataInputs=latitude=55.7906;longitude=12.5251;altitude=80;date_begin=2020-01-01;date_end=2020-05-04;time_ref=UT;summarization=P01M;username=pvlib-admin%2540googlegroups.com;verbose=false&Service=WPS&Request=Execute&Identifier=get_{identifier}&version=1.0.0&RawDataOutput=irradiation' # noqa: E501
213
213
 
214
214
  requests_mock.get(url_test_cams, text=mock_response,
215
215
  headers={'Content-Type': 'application/csv'})
@@ -3,7 +3,9 @@ import pandas as pd
3
3
  import pytest
4
4
 
5
5
  from pvlib.iotools import srml
6
- from ..conftest import DATA_DIR, RERUNS, RERUNS_DELAY
6
+ from ..conftest import (DATA_DIR, RERUNS, RERUNS_DELAY, assert_index_equal,
7
+ assert_frame_equal, fail_on_pvlib_version)
8
+ from pvlib._deprecation import pvlibDeprecationWarning
7
9
 
8
10
  srml_testfile = DATA_DIR / 'SRML-day-EUPO1801.txt'
9
11
 
@@ -28,6 +30,16 @@ def test_read_srml_columns_exist():
28
30
  assert '7008_flag' in data.columns
29
31
 
30
32
 
33
+ def test_read_srml_map_variables_false():
34
+ data = srml.read_srml(srml_testfile, map_variables=False)
35
+ assert '1000' in data.columns
36
+ assert '1000_flag' in data.columns
37
+ assert '2010' in data.columns
38
+ assert '2010_flag' in data.columns
39
+ assert '7008' in data.columns
40
+ assert '7008_flag' in data.columns
41
+
42
+
31
43
  def test_read_srml_nans_exist():
32
44
  data = srml.read_srml(srml_testfile)
33
45
  assert isnan(data['dni_0'][1119])
@@ -60,23 +72,37 @@ def test_read_srml_dt_index(url, year, month):
60
72
  ('2001', '2001'),
61
73
  ('2017', 'dni_7')
62
74
  ])
63
- def test_map_columns(column, expected):
64
- assert srml.map_columns(column) == expected
75
+ def test__map_columns(column, expected):
76
+ assert srml._map_columns(column) == expected
65
77
 
66
78
 
79
+ @pytest.mark.remote_data
80
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
81
+ def test_get_srml():
82
+ url = 'http://solardat.uoregon.edu/download/Archive/EUPO1801.txt'
83
+ file_data = srml.read_srml(url)
84
+ requested, _ = srml.get_srml(station='EU', start='2018-01-01',
85
+ end='2018-01-31')
86
+ assert_frame_equal(file_data, requested)
87
+
88
+
89
+ @fail_on_pvlib_version('0.11')
67
90
  @pytest.mark.remote_data
68
91
  @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
69
92
  def test_read_srml_month_from_solardat():
70
93
  url = 'http://solardat.uoregon.edu/download/Archive/EUPO1801.txt'
71
94
  file_data = srml.read_srml(url)
72
- requested = srml.read_srml_month_from_solardat('EU', 2018, 1)
95
+ with pytest.warns(pvlibDeprecationWarning, match='get_srml instead'):
96
+ requested = srml.read_srml_month_from_solardat('EU', 2018, 1)
73
97
  assert file_data.equals(requested)
74
98
 
75
99
 
100
+ @fail_on_pvlib_version('0.11')
76
101
  @pytest.mark.remote_data
77
102
  @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
78
103
  def test_15_minute_dt_index():
79
- data = srml.read_srml_month_from_solardat('TW', 2019, 4, 'RQ')
104
+ with pytest.warns(pvlibDeprecationWarning, match='get_srml instead'):
105
+ data = srml.read_srml_month_from_solardat('TW', 2019, 4, 'RQ')
80
106
  start = pd.Timestamp('20190401 00:00')
81
107
  start = start.tz_localize('Etc/GMT+8')
82
108
  end = pd.Timestamp('20190430 23:45')
@@ -86,10 +112,12 @@ def test_15_minute_dt_index():
86
112
  assert (data.index[3::4].minute == 45).all()
87
113
 
88
114
 
115
+ @fail_on_pvlib_version('0.11')
89
116
  @pytest.mark.remote_data
90
117
  @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
91
118
  def test_hourly_dt_index():
92
- data = srml.read_srml_month_from_solardat('CD', 1986, 4, 'PH')
119
+ with pytest.warns(pvlibDeprecationWarning, match='get_srml instead'):
120
+ data = srml.read_srml_month_from_solardat('CD', 1986, 4, 'PH')
93
121
  start = pd.Timestamp('19860401 00:00')
94
122
  start = start.tz_localize('Etc/GMT+8')
95
123
  end = pd.Timestamp('19860430 23:00')
@@ -97,3 +125,40 @@ def test_hourly_dt_index():
97
125
  assert data.index[0] == start
98
126
  assert data.index[-1] == end
99
127
  assert (data.index.minute == 0).all()
128
+
129
+
130
+ @pytest.mark.remote_data
131
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
132
+ def test_get_srml_hourly():
133
+ data, meta = data, meta = srml.get_srml(station='CD', start='1986-04-01',
134
+ end='1986-05-31', filetype='PH')
135
+ expected_index = pd.date_range(start='1986-04-01', end='1986-05-31 23:59',
136
+ freq='1h', tz='Etc/GMT+8')
137
+ assert_index_equal(data.index, expected_index)
138
+
139
+
140
+ @pytest.mark.remote_data
141
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
142
+ def test_get_srml_minute():
143
+ data_read = srml.read_srml(srml_testfile)
144
+ data_get, meta = srml.get_srml(station='EU', start='2018-01-01',
145
+ end='2018-01-31', filetype='PO')
146
+ expected_index = pd.date_range(start='2018-01-01', end='2018-01-31 23:59',
147
+ freq='1min', tz='Etc/GMT+8')
148
+ assert_index_equal(data_get.index, expected_index)
149
+ assert all([c in data_get.columns for c in data_read.columns])
150
+ # Check that all indices in example file are present in remote file
151
+ assert data_read.index.isin(data_get.index).all()
152
+ assert meta['station'] == 'EU'
153
+ assert meta['filetype'] == 'PO'
154
+ assert meta['filenames'] == ['EUPO1801.txt']
155
+
156
+
157
+ @pytest.mark.remote_data
158
+ @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
159
+ def test_get_srml_nonexisting_month_warning():
160
+ with pytest.warns(UserWarning, match='file was not found: EUPO0912.txt'):
161
+ # Request data for a period where not all files exist
162
+ # Eugene (EU) station started reporting 1-minute data in January 2010
163
+ data, meta = data, meta = srml.get_srml(
164
+ station='EU', start='2009-12-01', end='2010-01-31', filetype='PO')
@@ -1,8 +1,10 @@
1
1
  import numpy as np
2
2
  import pandas as pd
3
3
  from pvlib.iotools import tmy
4
+ from pvlib._deprecation import pvlibDeprecationWarning
4
5
  from ..conftest import DATA_DIR
5
6
  import pytest
7
+ import warnings
6
8
 
7
9
  # test the API works
8
10
  from pvlib.iotools import read_tmy3
@@ -16,29 +18,60 @@ TMY3_SOLARANYWHERE = DATA_DIR / 'Burlington, United States SolarAnywhere Time Se
16
18
 
17
19
 
18
20
  def test_read_tmy3():
19
- tmy.read_tmy3(TMY3_TESTFILE)
21
+ tmy.read_tmy3(TMY3_TESTFILE, map_variables=False)
20
22
 
21
23
 
22
24
  def test_read_tmy3_recolumn():
23
- data, meta = tmy.read_tmy3(TMY3_TESTFILE)
25
+ with warnings.catch_warnings():
26
+ warnings.simplefilter("ignore")
27
+ data, meta = tmy.read_tmy3(TMY3_TESTFILE, recolumn=True)
24
28
  assert 'GHISource' in data.columns
25
29
 
26
30
 
27
31
  def test_read_tmy3_norecolumn():
28
- data, _ = tmy.read_tmy3(TMY3_TESTFILE, recolumn=False)
32
+ data, _ = tmy.read_tmy3(TMY3_TESTFILE, map_variables=False)
29
33
  assert 'GHI source' in data.columns
30
34
 
31
35
 
36
+ def test_read_tmy3_raise_valueerror():
37
+ with pytest.raises(ValueError, match='`map_variables` and `recolumn`'):
38
+ _ = tmy.read_tmy3(TMY3_TESTFILE, recolumn=True, map_variables=True)
39
+
40
+
41
+ def test_read_tmy3_map_variables():
42
+ data, meta = tmy.read_tmy3(TMY3_TESTFILE, map_variables=True)
43
+ assert 'ghi' in data.columns
44
+ assert 'dni' in data.columns
45
+ assert 'dhi' in data.columns
46
+ assert 'pressure' in data.columns
47
+ assert 'wind_direction' in data.columns
48
+ assert 'wind_speed' in data.columns
49
+ assert 'temp_air' in data.columns
50
+ assert 'temp_dew' in data.columns
51
+ assert 'relative_humidity' in data.columns
52
+ assert 'albedo' in data.columns
53
+ assert 'ghi_extra' in data.columns
54
+ assert 'dni_extra' in data.columns
55
+ assert 'precipitable_water' in data.columns
56
+
57
+
58
+ def test_read_tmy3_map_variables_deprecating_warning():
59
+ with pytest.warns(pvlibDeprecationWarning, match='names will be renamed'):
60
+ data, meta = tmy.read_tmy3(TMY3_TESTFILE)
61
+
62
+
32
63
  def test_read_tmy3_coerce_year():
33
64
  coerce_year = 1987
34
- data, _ = tmy.read_tmy3(TMY3_TESTFILE, coerce_year=coerce_year)
65
+ data, _ = tmy.read_tmy3(TMY3_TESTFILE, coerce_year=coerce_year,
66
+ map_variables=False)
35
67
  assert (data.index[:-1].year == 1987).all()
36
68
  assert data.index[-1].year == 1988
37
69
 
38
70
 
39
71
  def test_read_tmy3_no_coerce_year():
40
72
  coerce_year = None
41
- data, _ = tmy.read_tmy3(TMY3_TESTFILE, coerce_year=coerce_year)
73
+ data, _ = tmy.read_tmy3(TMY3_TESTFILE, coerce_year=coerce_year,
74
+ map_variables=False)
42
75
  assert 1997 and 1999 in data.index.year
43
76
  assert data.index[-2] == pd.Timestamp('1998-12-31 23:00:00-09:00')
44
77
  assert data.index[-1] == pd.Timestamp('1999-01-01 00:00:00-09:00')
@@ -50,7 +83,7 @@ def test_read_tmy2():
50
83
 
51
84
  def test_gh865_read_tmy3_feb_leapyear_hr24():
52
85
  """correctly parse the 24th hour if the tmy3 file has a leap year in feb"""
53
- data, meta = read_tmy3(TMY3_FEB_LEAPYEAR)
86
+ data, meta = read_tmy3(TMY3_FEB_LEAPYEAR, map_variables=False)
54
87
  # just to be safe, make sure this _IS_ the Greensboro file
55
88
  greensboro = {
56
89
  'USAF': 723170,
@@ -66,7 +99,8 @@ def test_gh865_read_tmy3_feb_leapyear_hr24():
66
99
  assert data.index[1414] == pd.Timestamp('1996-02-28 23:00:00-0500')
67
100
  assert data.index[1415] == pd.Timestamp('1996-03-01 00:00:00-0500')
68
101
  # now check if it parses correctly when we try to coerce the year
69
- data, _ = read_tmy3(TMY3_FEB_LEAPYEAR, coerce_year=1990)
102
+ data, _ = read_tmy3(TMY3_FEB_LEAPYEAR, coerce_year=1990,
103
+ map_variables=False)
70
104
  # if get's here w/o an error, then gh865 is fixed, but let's check anyway
71
105
  assert all(data.index[:-1].year == 1990)
72
106
  assert data.index[-1].year == 1991
@@ -87,7 +121,8 @@ def test_solaranywhere_tmy3(solaranywhere_index):
87
121
  # The SolarAnywhere TMY3 format specifies midnight as 00:00 whereas the
88
122
  # NREL TMY3 format utilizes 24:00. The SolarAnywhere file is therefore
89
123
  # included to test files with 00:00 timestamps are parsed correctly
90
- data, meta = tmy.read_tmy3(TMY3_SOLARANYWHERE)
124
+ data, meta = tmy.read_tmy3(TMY3_SOLARANYWHERE, encoding='iso-8859-1',
125
+ map_variables=False)
91
126
  pd.testing.assert_index_equal(data.index, solaranywhere_index)
92
127
  assert meta['USAF'] == 0
93
128
  assert meta['Name'] == 'Burlington United States'
@@ -2,6 +2,7 @@ import numpy as np
2
2
  import pytest
3
3
  from pvlib import pvsystem
4
4
  from pvlib.ivtools import sde
5
+ from pvlib._deprecation import pvlibDeprecationWarning
5
6
 
6
7
 
7
8
  @pytest.fixture
@@ -11,31 +12,32 @@ def get_test_iv_params():
11
12
 
12
13
  def test_fit_sandia_simple(get_test_iv_params, get_bad_iv_curves):
13
14
  test_params = get_test_iv_params
14
- testcurve = pvsystem.singlediode(photocurrent=test_params['IL'],
15
- saturation_current=test_params['I0'],
16
- resistance_shunt=test_params['Rsh'],
17
- resistance_series=test_params['Rs'],
18
- nNsVth=test_params['nNsVth'],
19
- ivcurve_pnts=300)
20
- expected = tuple(test_params[k] for k in ['IL', 'I0', 'Rs', 'Rsh',
21
- 'nNsVth'])
22
- result = sde.fit_sandia_simple(voltage=testcurve['v'],
23
- current=testcurve['i'])
15
+ test_params = dict(photocurrent=test_params['IL'],
16
+ saturation_current=test_params['I0'],
17
+ resistance_series=test_params['Rs'],
18
+ resistance_shunt=test_params['Rsh'],
19
+ nNsVth=test_params['nNsVth'])
20
+ testcurve = pvsystem.singlediode(**test_params)
21
+ v = np.linspace(0., testcurve['v_oc'], 300)
22
+ i = pvsystem.i_from_v(voltage=v, **test_params)
23
+ expected = tuple(test_params.values())
24
+
25
+ result = sde.fit_sandia_simple(voltage=v, current=i)
24
26
  assert np.allclose(result, expected, rtol=5e-5)
25
- result = sde.fit_sandia_simple(voltage=testcurve['v'],
26
- current=testcurve['i'],
27
+
28
+ result = sde.fit_sandia_simple(voltage=v, current=i,
27
29
  v_oc=testcurve['v_oc'],
28
30
  i_sc=testcurve['i_sc'])
29
31
  assert np.allclose(result, expected, rtol=5e-5)
30
- result = sde.fit_sandia_simple(voltage=testcurve['v'],
31
- current=testcurve['i'],
32
+
33
+ result = sde.fit_sandia_simple(voltage=v, current=i,
32
34
  v_oc=testcurve['v_oc'],
33
35
  i_sc=testcurve['i_sc'],
34
36
  v_mp_i_mp=(testcurve['v_mp'],
35
- testcurve['i_mp']))
37
+ testcurve['i_mp']))
36
38
  assert np.allclose(result, expected, rtol=5e-5)
37
- result = sde.fit_sandia_simple(voltage=testcurve['v'],
38
- current=testcurve['i'], vlim=0.1)
39
+
40
+ result = sde.fit_sandia_simple(voltage=v, current=i, vlim=0.1)
39
41
  assert np.allclose(result, expected, rtol=5e-5)
40
42
 
41
43
 
@@ -6,6 +6,7 @@ from numpy.testing import assert_allclose
6
6
 
7
7
  from pvlib.ivtools import sdm
8
8
  from pvlib import pvsystem
9
+ from pvlib._deprecation import pvlibDeprecationWarning
9
10
 
10
11
  from pvlib.tests.conftest import requires_pysam, requires_statsmodels
11
12
 
@@ -100,11 +101,15 @@ def test_fit_desoto_sandia(cec_params_cansol_cs5p_220p):
100
101
  temp_cell = np.array([15., 25., 35., 45.])
101
102
  ee = np.tile(effective_irradiance, len(temp_cell))
102
103
  tc = np.repeat(temp_cell, len(effective_irradiance))
103
- iph, io, rs, rsh, nnsvth = pvsystem.calcparams_desoto(
104
+ IL, I0, Rs, Rsh, nNsVth = pvsystem.calcparams_desoto(
104
105
  ee, tc, alpha_sc=specs['alpha_sc'], **params)
105
- sim_ivcurves = pvsystem.singlediode(iph, io, rs, rsh, nnsvth, 300)
106
- sim_ivcurves['ee'] = ee
107
- sim_ivcurves['tc'] = tc
106
+ ivcurve_params = dict(photocurrent=IL, saturation_current=I0,
107
+ resistance_series=Rs, resistance_shunt=Rsh,
108
+ nNsVth=nNsVth)
109
+ sim_ivcurves = pvsystem.singlediode(**ivcurve_params).to_dict('series')
110
+ v = np.linspace(0., sim_ivcurves['v_oc'], 300)
111
+ i = pvsystem.i_from_v(voltage=v, **ivcurve_params)
112
+ sim_ivcurves.update(v=v.T, i=i.T, ee=ee, tc=tc)
108
113
 
109
114
  result = sdm.fit_desoto_sandia(sim_ivcurves, specs)
110
115
  modeled = pd.Series(index=params.keys(), data=np.nan)