pvlib 0.11.1__py3-none-any.whl → 0.12.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 (149) hide show
  1. pvlib/__init__.py +1 -0
  2. pvlib/_deprecation.py +73 -0
  3. pvlib/atmosphere.py +77 -7
  4. pvlib/bifacial/infinite_sheds.py +4 -3
  5. pvlib/bifacial/utils.py +2 -1
  6. pvlib/clearsky.py +35 -22
  7. pvlib/iam.py +4 -4
  8. pvlib/iotools/midc.py +1 -1
  9. pvlib/iotools/psm3.py +1 -1
  10. pvlib/iotools/pvgis.py +10 -12
  11. pvlib/iotools/tmy.py +3 -69
  12. pvlib/irradiance.py +112 -55
  13. pvlib/ivtools/sdm.py +75 -52
  14. pvlib/location.py +73 -33
  15. pvlib/modelchain.py +18 -35
  16. pvlib/pvsystem.py +139 -94
  17. pvlib/snow.py +64 -28
  18. pvlib/solarposition.py +46 -30
  19. pvlib/spa.py +4 -2
  20. pvlib/spectrum/__init__.py +0 -1
  21. pvlib/spectrum/irradiance.py +2 -64
  22. pvlib/spectrum/mismatch.py +3 -3
  23. pvlib/spectrum/spectrl2.py +2 -1
  24. pvlib/temperature.py +49 -3
  25. pvlib/tools.py +6 -5
  26. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/METADATA +14 -11
  27. pvlib-0.12.0.dist-info/RECORD +75 -0
  28. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/WHEEL +1 -1
  29. pvlib/data/BIRD_08_16_2012.csv +0 -8761
  30. pvlib/data/BIRD_08_16_2012_patm.csv +0 -8761
  31. pvlib/data/Burlington, United States SolarAnywhere Time Series 2021 Lat_44_465 Lon_-73_205 TMY3 format.csv +0 -8762
  32. pvlib/data/Burlington, United States SolarAnywhere Time Series 20210101 to 20210103 Lat_44_4675 Lon_-73_2075 SA format.csv +0 -578
  33. pvlib/data/Burlington, United States SolarAnywhere Typical GHI Year Lat_44_465 Lon_-73_205 SA format.csv +0 -74
  34. pvlib/data/CPS SCH275KTL-DO-US-800-250kW_275kVA_1.OND +0 -146
  35. pvlib/data/CRNS0101-05-2019-AZ_Tucson_11_W.txt +0 -4
  36. pvlib/data/CRN_with_problems.txt +0 -3
  37. pvlib/data/ET-M772BH550GL.PAN +0 -75
  38. pvlib/data/NLD_Amsterdam062400_IWEC.epw +0 -8768
  39. pvlib/data/PVsyst_demo.csv +0 -10757
  40. pvlib/data/PVsyst_demo_model.csv +0 -3588
  41. pvlib/data/SRML-day-EUPO1801.txt +0 -1441
  42. pvlib/data/abq19056.dat +0 -6
  43. pvlib/data/aod550_tcwv_20121101_test.nc +0 -0
  44. pvlib/data/bishop88_numerical_precision.csv +0 -101
  45. pvlib/data/bsrn-lr0100-pay0616.dat +0 -86901
  46. pvlib/data/bsrn-pay0616.dat.gz +0 -0
  47. pvlib/data/cams_mcclear_1min_verbose.csv +0 -60
  48. pvlib/data/cams_mcclear_monthly.csv +0 -42
  49. pvlib/data/cams_radiation_1min_verbose.csv +0 -72
  50. pvlib/data/cams_radiation_monthly.csv +0 -47
  51. pvlib/data/detect_clearsky_data.csv +0 -35
  52. pvlib/data/detect_clearsky_threshold_data.csv +0 -126
  53. pvlib/data/greensboro_kimber_soil_manwash.dat +0 -8761
  54. pvlib/data/greensboro_kimber_soil_nowash.dat +0 -8761
  55. pvlib/data/inverter_fit_snl_meas.csv +0 -127
  56. pvlib/data/inverter_fit_snl_sim.csv +0 -19
  57. pvlib/data/ivtools_numdiff.csv +0 -52
  58. pvlib/data/midc_20181014.txt +0 -1441
  59. pvlib/data/midc_raw_20181018.txt +0 -1441
  60. pvlib/data/midc_raw_short_header_20191115.txt +0 -1441
  61. pvlib/data/msn19056.dat +0 -6
  62. pvlib/data/precise_iv_curves1.json +0 -10251
  63. pvlib/data/precise_iv_curves2.json +0 -10251
  64. pvlib/data/precise_iv_curves_parameter_sets1.csv +0 -33
  65. pvlib/data/precise_iv_curves_parameter_sets2.csv +0 -33
  66. pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA2_10kWp_CIS_5_2a_2013_2014.json +0 -1
  67. pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA_30deg_0deg_2016_2016.csv +0 -35
  68. pvlib/data/pvgis_tmy_meta.json +0 -32
  69. pvlib/data/pvgis_tmy_test.dat +0 -8761
  70. pvlib/data/pvwatts_8760_rackmount.csv +0 -8779
  71. pvlib/data/pvwatts_8760_roofmount.csv +0 -8779
  72. pvlib/data/singleaxis_tracker_wslope.csv +0 -8761
  73. pvlib/data/spectrl2_example_spectra.csv +0 -123
  74. pvlib/data/surfrad-slv16001.dat +0 -1442
  75. pvlib/data/test_psm3_2017.csv +0 -17521
  76. pvlib/data/test_psm3_2019_5min.csv +0 -289
  77. pvlib/data/test_psm3_tmy-2017.csv +0 -8761
  78. pvlib/data/test_read_psm3.csv +0 -17523
  79. pvlib/data/test_read_pvgis_horizon.csv +0 -49
  80. pvlib/data/tmy_45.000_8.000_2005_2020.csv +0 -8789
  81. pvlib/data/tmy_45.000_8.000_2005_2020.epw +0 -8768
  82. pvlib/data/tmy_45.000_8.000_2005_2020.json +0 -1
  83. pvlib/data/tmy_45.000_8.000_2005_2020.txt +0 -8761
  84. pvlib/data/tmy_45.000_8.000_userhorizon.json +0 -1
  85. pvlib/data/variables_style_rules.csv +0 -56
  86. pvlib/spa_c_files/README.md +0 -81
  87. pvlib/spa_c_files/cspa_py.pxd +0 -43
  88. pvlib/spa_c_files/spa_py.pyx +0 -30
  89. pvlib/tests/__init__.py +0 -0
  90. pvlib/tests/bifacial/__init__.py +0 -0
  91. pvlib/tests/bifacial/test_infinite_sheds.py +0 -317
  92. pvlib/tests/bifacial/test_losses_models.py +0 -54
  93. pvlib/tests/bifacial/test_pvfactors.py +0 -82
  94. pvlib/tests/bifacial/test_utils.py +0 -192
  95. pvlib/tests/conftest.py +0 -476
  96. pvlib/tests/iotools/__init__.py +0 -0
  97. pvlib/tests/iotools/test_acis.py +0 -213
  98. pvlib/tests/iotools/test_bsrn.py +0 -131
  99. pvlib/tests/iotools/test_crn.py +0 -95
  100. pvlib/tests/iotools/test_epw.py +0 -23
  101. pvlib/tests/iotools/test_midc.py +0 -89
  102. pvlib/tests/iotools/test_panond.py +0 -32
  103. pvlib/tests/iotools/test_psm3.py +0 -198
  104. pvlib/tests/iotools/test_pvgis.py +0 -644
  105. pvlib/tests/iotools/test_sodapro.py +0 -298
  106. pvlib/tests/iotools/test_solaranywhere.py +0 -287
  107. pvlib/tests/iotools/test_solargis.py +0 -68
  108. pvlib/tests/iotools/test_solcast.py +0 -324
  109. pvlib/tests/iotools/test_solrad.py +0 -152
  110. pvlib/tests/iotools/test_srml.py +0 -124
  111. pvlib/tests/iotools/test_surfrad.py +0 -75
  112. pvlib/tests/iotools/test_tmy.py +0 -133
  113. pvlib/tests/ivtools/__init__.py +0 -0
  114. pvlib/tests/ivtools/test_sde.py +0 -230
  115. pvlib/tests/ivtools/test_sdm.py +0 -407
  116. pvlib/tests/ivtools/test_utils.py +0 -173
  117. pvlib/tests/spectrum/__init__.py +0 -0
  118. pvlib/tests/spectrum/conftest.py +0 -40
  119. pvlib/tests/spectrum/test_irradiance.py +0 -138
  120. pvlib/tests/spectrum/test_mismatch.py +0 -304
  121. pvlib/tests/spectrum/test_response.py +0 -124
  122. pvlib/tests/spectrum/test_spectrl2.py +0 -72
  123. pvlib/tests/test_albedo.py +0 -84
  124. pvlib/tests/test_atmosphere.py +0 -204
  125. pvlib/tests/test_clearsky.py +0 -878
  126. pvlib/tests/test_conftest.py +0 -81
  127. pvlib/tests/test_iam.py +0 -555
  128. pvlib/tests/test_inverter.py +0 -213
  129. pvlib/tests/test_irradiance.py +0 -1441
  130. pvlib/tests/test_location.py +0 -356
  131. pvlib/tests/test_modelchain.py +0 -2020
  132. pvlib/tests/test_numerical_precision.py +0 -124
  133. pvlib/tests/test_pvarray.py +0 -71
  134. pvlib/tests/test_pvsystem.py +0 -2495
  135. pvlib/tests/test_scaling.py +0 -207
  136. pvlib/tests/test_shading.py +0 -391
  137. pvlib/tests/test_singlediode.py +0 -608
  138. pvlib/tests/test_snow.py +0 -212
  139. pvlib/tests/test_soiling.py +0 -230
  140. pvlib/tests/test_solarposition.py +0 -933
  141. pvlib/tests/test_spa.py +0 -425
  142. pvlib/tests/test_temperature.py +0 -470
  143. pvlib/tests/test_tools.py +0 -146
  144. pvlib/tests/test_tracking.py +0 -474
  145. pvlib/tests/test_transformer.py +0 -60
  146. pvlib-0.11.1.dist-info/RECORD +0 -192
  147. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/AUTHORS.md +0 -0
  148. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/LICENSE +0 -0
  149. {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/top_level.txt +0 -0
@@ -1,298 +0,0 @@
1
- """
2
- test iotools for sodapro
3
- """
4
-
5
- import pandas as pd
6
- import numpy as np
7
- import requests
8
- import pytest
9
-
10
- from pvlib.iotools import sodapro
11
- from ..conftest import DATA_DIR, assert_frame_equal
12
-
13
-
14
- testfile_mcclear_verbose = DATA_DIR / 'cams_mcclear_1min_verbose.csv'
15
- testfile_mcclear_monthly = DATA_DIR / 'cams_mcclear_monthly.csv'
16
- testfile_radiation_verbose = DATA_DIR / 'cams_radiation_1min_verbose.csv'
17
- testfile_radiation_monthly = DATA_DIR / 'cams_radiation_monthly.csv'
18
-
19
-
20
- index_verbose = pd.date_range('2020-06-01 12', periods=4, freq='1min',
21
- tz='UTC')
22
- index_monthly = pd.date_range('2020-01-01', periods=4, freq='1M')
23
-
24
-
25
- dtypes_mcclear_verbose = [
26
- 'object', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64',
27
- 'float64', 'float64', 'float64', 'float64', 'float64', 'float64',
28
- 'float64', 'float64', 'float64', 'float64', 'float64', 'int64', 'float64',
29
- 'float64', 'float64', 'float64']
30
-
31
- dtypes_mcclear = [
32
- 'object', 'float64', 'float64', 'float64', 'float64', 'float64']
33
-
34
- dtypes_radiation_verbose = [
35
- 'object', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64',
36
- 'float64', 'float64', 'float64', 'float64', 'float64', 'float64',
37
- 'float64', 'float64', 'float64', 'float64', 'float64', 'float64',
38
- 'float64', 'float64', 'float64', 'float64', 'int64', 'float64', 'float64',
39
- 'float64', 'float64', 'float64', 'int64', 'int64', 'float64', 'float64',
40
- 'float64', 'float64']
41
-
42
- dtypes_radiation = [
43
- 'object', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64',
44
- 'float64', 'float64', 'float64', 'float64']
45
-
46
-
47
- columns_mcclear_verbose = [
48
- 'Observation period', 'ghi_extra', 'ghi_clear', 'bhi_clear',
49
- 'dhi_clear', 'dni_clear', 'solar_zenith', 'summer/winter split', 'tco3',
50
- 'tcwv', 'AOD BC', 'AOD DU', 'AOD SS', 'AOD OR', 'AOD SU', 'AOD NI',
51
- 'AOD AM', 'alpha', 'Aerosol type', 'fiso', 'fvol', 'fgeo', 'albedo']
52
-
53
- columns_mcclear = [
54
- 'Observation period', 'ghi_extra', 'ghi_clear', 'bhi_clear', 'dhi_clear',
55
- 'dni_clear']
56
-
57
- columns_radiation_verbose = [
58
- 'Observation period', 'ghi_extra', 'ghi_clear', 'bhi_clear', 'dhi_clear',
59
- 'dni_clear', 'ghi', 'bhi', 'dhi', 'dni', 'Reliability', 'solar_zenith',
60
- 'summer/winter split', 'tco3', 'tcwv', 'AOD BC', 'AOD DU', 'AOD SS',
61
- 'AOD OR', 'AOD SU', 'AOD NI', 'AOD AM', 'alpha', 'Aerosol type', 'fiso',
62
- 'fvol', 'fgeo', 'albedo', 'Cloud optical depth', 'Cloud coverage',
63
- 'Cloud type', 'GHI no corr', 'BHI no corr', 'DHI no corr', 'BNI no corr']
64
-
65
- columns_radiation_verbose_unmapped = [
66
- 'Observation period', 'TOA', 'Clear sky GHI', 'Clear sky BHI',
67
- 'Clear sky DHI', 'Clear sky BNI', 'GHI', 'BHI', 'DHI', 'BNI',
68
- 'Reliability', 'sza', 'summer/winter split', 'tco3', 'tcwv', 'AOD BC',
69
- 'AOD DU', 'AOD SS', 'AOD OR', 'AOD SU', 'AOD NI', 'AOD AM', 'alpha',
70
- 'Aerosol type', 'fiso', 'fvol', 'fgeo', 'albedo', 'Cloud optical depth',
71
- 'Cloud coverage', 'Cloud type', 'GHI no corr', 'BHI no corr',
72
- 'DHI no corr', 'BNI no corr']
73
-
74
- columns_radiation = [
75
- 'Observation period', 'ghi_extra', 'ghi_clear', 'bhi_clear', 'dhi_clear',
76
- 'dni_clear', 'ghi', 'bhi', 'dhi', 'dni', 'Reliability']
77
-
78
-
79
- values_mcclear_verbose = np.array([
80
- ['2020-06-01T12:00:00.0/2020-06-01T12:01:00.0', 1084.194, 848.5020,
81
- 753.564, 94.938, 920.28, 35.0308, 0.9723, 341.0221, 17.7962, 0.0065,
82
- 0.0067, 0.0008, 0.0215, 0.0252, 0.0087, 0.0022, np.nan, -1, 0.1668,
83
- 0.0912, 0.0267, 0.1359],
84
- ['2020-06-01T12:01:00.0/2020-06-01T12:02:00.0', 1083.504, 847.866, 752.904,
85
- 94.962, 920.058, 35.0828, 0.9723, 341.0223, 17.802, 0.0065, 0.0067,
86
- 0.0008, 0.0215, 0.0253, 0.0087, 0.0022, np.nan, -1, 0.1668, 0.0912,
87
- 0.0267, 0.1359],
88
- ['2020-06-01T12:02:00.0/2020-06-01T12:03:00.0', 1082.802, 847.224, 752.232,
89
- 94.986, 919.836, 35.1357, 0.9723, 341.0224, 17.8079, 0.0065, 0.0067,
90
- 0.0008, 0.0216, 0.0253, 0.0087, 0.0022, np.nan, -1, 0.1668, 0.0912,
91
- 0.0267, 0.1359],
92
- ['2020-06-01T12:03:00.0/2020-06-01T12:04:00.0', 1082.088, 846.564, 751.554,
93
- 95.01, 919.614, 35.1896, 0.9723, 341.0226, 17.8137, 0.0065, 0.0067,
94
- 0.0008, 0.0217, 0.0253, 0.0087, 0.0022, np.nan, -1, 0.1668, 0.0912,
95
- 0.0267, 0.1359]])
96
-
97
- values_mcclear_monthly = np.array([
98
- ['2020-01-01T00:00:00.0/2020-02-01T00:00:00.0', 67.4314, 39.5494,
99
- 26.1998, 13.3496, 142.1562],
100
- ['2020-02-01T00:00:00.0/2020-03-01T00:00:00.0', 131.2335, 84.7849,
101
- 58.3855, 26.3994, 202.4865],
102
- ['2020-03-01T00:00:00.0/2020-04-01T00:00:00.0', 232.3323, 163.176,
103
- 125.1675, 38.0085, 307.5254],
104
- ['2020-04-01T00:00:00.0/2020-05-01T00:00:00.0', 344.7431, 250.7585,
105
- 197.8757, 52.8829, 387.6707]])
106
-
107
- values_radiation_verbose = np.array([
108
- ['2020-06-01T12:00:00.0/2020-06-01T12:01:00.0', 1084.194, 848.502, 753.564,
109
- 94.938, 920.28, 815.358, 702.342, 113.022, 857.724, 1.0, 35.0308, 0.9723,
110
- 341.0221, 17.7962, 0.0065, 0.0067, 0.0008, 0.0215, 0.0252, 0.0087, 0.0022,
111
- np.nan, -1, 0.1668, 0.0912, 0.0267, 0.1359, 0.0, 0, 5, 848.502, 753.564,
112
- 94.938, 920.28],
113
- ['2020-06-01T12:01:00.0/2020-06-01T12:02:00.0', 1083.504, 847.866, 752.904,
114
- 94.962, 920.058, 814.806, 701.73, 113.076, 857.52, 1.0, 35.0828, 0.9723,
115
- 341.0223, 17.802, 0.0065, 0.0067, 0.0008, 0.0215, 0.0253, 0.0087, 0.0022,
116
- np.nan, -1, 0.1668, 0.0912, 0.0267, 0.1359, 0.0, 0, 5, 847.866, 752.904,
117
- 94.962, 920.058],
118
- ['2020-06-01T12:02:00.0/2020-06-01T12:03:00.0', 1082.802, 847.224, 752.232,
119
- 94.986, 919.836, 814.182, 701.094, 113.088, 857.298, 1.0, 35.1357, 0.9723,
120
- 341.0224, 17.8079, 0.0065, 0.0067, 0.0008, 0.0216, 0.0253, 0.0087, 0.0022,
121
- np.nan, -1, 0.1668, 0.0912, 0.0267, 0.1359, 0.0, 0, 5, 847.224, 752.232,
122
- 94.986, 919.836],
123
- ['2020-06-01T12:03:00.0/2020-06-01T12:04:00.0', 1082.088, 846.564, 751.554,
124
- 95.01, 919.614, 813.612, 700.464, 113.148, 857.094, 1.0, 35.1896, 0.9723,
125
- 341.0226, 17.8137, 0.0065, 0.0067, 0.0008, 0.0217, 0.0253, 0.0087, 0.0022,
126
- np.nan, -1, 0.1668, 0.0912, 0.0267, 0.1359, 0.0, 0, 5, 846.564, 751.554,
127
- 95.01, 919.614]])
128
-
129
- values_radiation_verbose_integrated = np.copy(values_radiation_verbose)
130
- values_radiation_verbose_integrated[:, 1:10] = \
131
- values_radiation_verbose_integrated[:, 1:10].astype(float)/60
132
- values_radiation_verbose_integrated[:, 31:35] = \
133
- values_radiation_verbose_integrated[:, 31:35].astype(float)/60
134
-
135
- values_radiation_monthly = np.array([
136
- ['2020-01-01T00:00:00.0/2020-02-01T00:00:00.0', 67.4317, 39.5496,
137
- 26.2, 13.3496, 142.1567, 20.8763, 3.4526, 17.4357, 16.7595, 0.997],
138
- ['2020-02-01T00:00:00.0/2020-03-01T00:00:00.0', 131.2338, 84.7852,
139
- 58.3858, 26.3994, 202.4871, 47.5197, 13.984, 33.5512, 47.8541, 0.9956],
140
- ['2020-03-01T00:00:00.0/2020-04-01T00:00:00.0', 232.3325, 163.1762,
141
- 125.1677, 38.0085, 307.5256, 120.1659, 69.6217, 50.5653, 159.576, 0.9949],
142
- ['2020-04-01T00:00:00.0/2020-05-01T00:00:00.0', 344.7433, 250.7587,
143
- 197.8758, 52.8829, 387.6709, 196.7015, 123.2593, 73.5152, 233.9675,
144
- 0.9897]])
145
-
146
-
147
- # @pytest.fixture
148
- def generate_expected_dataframe(values, columns, index, dtypes):
149
- """Create dataframe from arrays of values, columns and index, in order to
150
- use this dataframe to compare to.
151
- """
152
- expected = pd.DataFrame(values, columns=columns, index=index)
153
- expected.index.freq = None
154
- for (col, _dtype) in zip(expected.columns, dtypes):
155
- expected[col] = expected[col].astype(_dtype)
156
- return expected
157
-
158
-
159
- @pytest.mark.parametrize('testfile,index,columns,values,dtypes', [
160
- (testfile_mcclear_verbose, index_verbose, columns_mcclear_verbose,
161
- values_mcclear_verbose, dtypes_mcclear_verbose),
162
- (testfile_mcclear_monthly, index_monthly, columns_mcclear,
163
- values_mcclear_monthly, dtypes_mcclear),
164
- (testfile_radiation_verbose, index_verbose, columns_radiation_verbose,
165
- values_radiation_verbose, dtypes_radiation_verbose),
166
- (testfile_radiation_monthly, index_monthly, columns_radiation,
167
- values_radiation_monthly, dtypes_radiation)])
168
- def test_read_cams(testfile, index, columns, values, dtypes):
169
- expected = generate_expected_dataframe(values, columns, index, dtypes)
170
- out, metadata = sodapro.read_cams(testfile, integrated=False,
171
- map_variables=True)
172
- assert_frame_equal(out, expected, check_less_precise=True)
173
-
174
-
175
- def test_read_cams_integrated_unmapped_label():
176
- # Default label is 'left' for 1 minute time resolution, hence 1 minute is
177
- # added for label='right'
178
- expected = generate_expected_dataframe(
179
- values_radiation_verbose_integrated,
180
- columns_radiation_verbose_unmapped,
181
- index_verbose+pd.Timedelta(minutes=1), dtypes=dtypes_radiation_verbose)
182
- out, metadata = sodapro.read_cams(testfile_radiation_verbose,
183
- integrated=True, label='right',
184
- map_variables=False)
185
- assert_frame_equal(out, expected, check_less_precise=True)
186
-
187
-
188
- def test_read_cams_metadata():
189
- _, metadata = sodapro.read_cams(testfile_mcclear_monthly, integrated=False)
190
- assert metadata['Time reference'] == 'Universal time (UT)'
191
- assert metadata['noValue'] == 'nan'
192
- assert metadata['latitude'] == 55.7906
193
- assert metadata['longitude'] == 12.5251
194
- assert metadata['altitude'] == 39.0
195
- assert metadata['radiation_unit'] == 'W/m^2'
196
- assert metadata['time_step'] == '1M'
197
-
198
-
199
- @pytest.mark.parametrize('testfile,index,columns,values,dtypes,identifier', [
200
- (testfile_mcclear_monthly, index_monthly, columns_mcclear,
201
- values_mcclear_monthly, dtypes_mcclear, 'mcclear'),
202
- (testfile_radiation_monthly, index_monthly, columns_radiation,
203
- values_radiation_monthly, dtypes_radiation, 'cams_radiation')])
204
- def test_get_cams(requests_mock, testfile, index, columns, values, dtypes,
205
- identifier):
206
- """Test that get_cams generates the correct URI request and that parse_cams
207
- is being called correctly"""
208
- # Open local test file containing McClear mothly data
209
- with open(testfile, 'r') as test_file:
210
- mock_response = test_file.read()
211
- # Specify the full URI of a specific example, this ensures that all of the
212
- # inputs are passing on correctly
213
- 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
214
-
215
- requests_mock.get(url_test_cams, text=mock_response,
216
- headers={'Content-Type': 'application/csv'})
217
-
218
- # Make API call - an error is raised if requested URI does not match
219
- out, metadata = sodapro.get_cams(
220
- start=pd.Timestamp('2020-01-01'),
221
- end=pd.Timestamp('2020-05-04'),
222
- latitude=55.7906,
223
- longitude=12.5251,
224
- email='pvlib-admin@googlegroups.com',
225
- identifier=identifier,
226
- altitude=80,
227
- time_step='1M',
228
- verbose=False,
229
- integrated=False)
230
- expected = generate_expected_dataframe(values, columns, index, dtypes)
231
- assert_frame_equal(out, expected, check_less_precise=True)
232
-
233
- # Test if Warning is raised if verbose mode is True and time_step != '1min'
234
- with pytest.warns(UserWarning, match='Verbose mode only supports'):
235
- _ = sodapro.get_cams(
236
- start=pd.Timestamp('2020-01-01'),
237
- end=pd.Timestamp('2020-05-04'),
238
- latitude=55.7906,
239
- longitude=12.5251,
240
- email='pvlib-admin@googlegroups.com',
241
- identifier=identifier,
242
- altitude=80,
243
- time_step='1M',
244
- verbose=True)
245
-
246
-
247
- def test_get_cams_bad_request(requests_mock):
248
- """Test that a the correct errors/warnings ares raised for invalid
249
- requests inputs. Also tests if the specified server url gets used"""
250
-
251
- # Subset of an xml file returned for errornous requests
252
- mock_response_bad_text = """<?xml version="1.0" encoding="utf-8"?>
253
- <ows:Exception exceptionCode="NoApplicableCode" locator="None">
254
- <ows:ExceptionText>Failed to execute WPS process [get_mcclear]:
255
- Please, register yourself at www.soda-pro.com
256
- </ows:ExceptionText>"""
257
-
258
- url_cams_bad_request = 'https://pro.soda-is.com/service/wps?DataInputs=latitude=55.7906;longitude=12.5251;altitude=-999;date_begin=2020-01-01;date_end=2020-05-04;time_ref=TST;summarization=PT01H;username=test%2540test.com;verbose=false&Service=WPS&Request=Execute&Identifier=get_mcclear&version=1.0.0&RawDataOutput=irradiation' # noqa: E501
259
-
260
- requests_mock.get(url_cams_bad_request, status_code=400,
261
- text=mock_response_bad_text)
262
-
263
- # Test if HTTPError is raised if incorrect input is specified
264
- # In the below example a non-registrered email is specified
265
- with pytest.raises(requests.exceptions.HTTPError,
266
- match='Failed to execute WPS process'):
267
- _ = sodapro.get_cams(
268
- start=pd.Timestamp('2020-01-01'),
269
- end=pd.Timestamp('2020-05-04'),
270
- latitude=55.7906,
271
- longitude=12.5251,
272
- email='test@test.com', # a non-registrered email
273
- identifier='mcclear',
274
- time_ref='TST',
275
- verbose=False,
276
- time_step='1h',
277
- server='pro.soda-is.com')
278
- # Test if value error is raised if incorrect identifier is specified
279
- with pytest.raises(ValueError, match='Identifier must be either'):
280
- _ = sodapro.get_cams(
281
- start=pd.Timestamp('2020-01-01'),
282
- end=pd.Timestamp('2020-05-04'),
283
- latitude=55.7906,
284
- longitude=12.5251,
285
- email='test@test.com',
286
- identifier='test', # incorrect identifier
287
- server='pro.soda-is.com')
288
- # Test if value error is raised if incorrect time step is specified
289
- with pytest.raises(ValueError, match='Time step not recognized'):
290
- _ = sodapro.get_cams(
291
- start=pd.Timestamp('2020-01-01'),
292
- end=pd.Timestamp('2020-05-04'),
293
- latitude=55.7906,
294
- longitude=12.5251,
295
- email='test@test.com',
296
- identifier='mcclear',
297
- time_step='test', # incorrect time step
298
- server='pro.soda-is.com')
@@ -1,287 +0,0 @@
1
- import pandas as pd
2
- import pytest
3
- import pvlib
4
- import os
5
- from ..conftest import (DATA_DIR, RERUNS, RERUNS_DELAY,
6
- requires_solaranywhere_credentials)
7
-
8
- # High spatial resolution and 5-min data, true dynamics enabled
9
- TESTFILE_HIGH_RESOLUTION = DATA_DIR / 'Burlington, United States SolarAnywhere Time Series 20210101 to 20210103 Lat_44_4675 Lon_-73_2075 SA format.csv' # noqa: E501
10
- # TGY test file (v3.6) containing GHI/DHI and temperature.
11
- # Note, the test file only contains the first three days.
12
- TESTFILE_TMY = DATA_DIR / 'Burlington, United States SolarAnywhere Typical GHI Year Lat_44_465 Lon_-73_205 SA format.csv' # noqa: E501
13
-
14
-
15
- @pytest.fixture(scope="module")
16
- def solaranywhere_api_key():
17
- """Supplies the pvlib's SolarAnywhere API key for testing purposes.
18
- Users can freely register for an API key."""
19
- solaranywhere_api_key = os.environ["SOLARANYWHERE_API_KEY"]
20
- return solaranywhere_api_key
21
-
22
-
23
- @pytest.fixture
24
- def high_resolution_index():
25
- index = pd.date_range(start='2021-01-01 00:05-0500',
26
- end='2021-01-03 00:00-0500', freq='5min')
27
- index.name = 'ObservationTime'
28
- return index
29
-
30
-
31
- @pytest.fixture
32
- def tmy_index():
33
- index = pd.date_range(
34
- start='2000-01-01 01:00-0500', periods=3*24, freq='1h')
35
- index.name = 'ObservationTime'
36
- index.freq = None
37
- return index
38
-
39
-
40
- @pytest.fixture
41
- def tmy_ghi_series(tmy_index):
42
- ghi = [
43
- 0, 0, 0, 0, 0, 0, 0, 3, 50, 171, 234, 220, 202, 122, 141, 65, 2, 0, 0,
44
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 48, 105, 161, 135, 108, 72, 58,
45
- 33, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 47, 124, 99, 116,
46
- 130, 165, 110, 36, 1, 0, 0, 0, 0, 0, 0, 0
47
- ]
48
- return pd.Series(data=ghi, index=tmy_index, name='ghi')
49
-
50
-
51
- def test_read_solaranywhere_high_resolution(high_resolution_index):
52
- data, meta = pvlib.iotools.read_solaranywhere(TESTFILE_HIGH_RESOLUTION,
53
- map_variables=False)
54
- # Check that metadata is parsed correctly
55
- assert meta['latitude'] == 44.4675
56
- assert meta['longitude'] == -73.2075
57
- assert meta['altitude'] == 41.0
58
- assert meta['name'] == 'Burlington United States'
59
- assert meta['TZ'] == -5.0
60
- assert meta['Data Version'] == '3.6'
61
- assert meta['LatLon Resolution'] == 0.005
62
- # Check that columns are parsed correctly
63
- assert 'Albedo' in data.columns
64
- assert 'Global Horizontal Irradiance (GHI) W/m2' in data.columns
65
- assert 'Direct Normal Irradiance (DNI) W/m2' in data.columns
66
- assert 'WindSpeed (m/s)' in data.columns
67
- assert 'WindSpeedObservationType' in data.columns
68
- assert 'Particulate Matter 10 (µg/m3)' in data.columns
69
- # Check that data is parsed correctly
70
- assert data.loc['2021-01-01 07:00:00-05:00', 'Albedo'] == 0.6
71
- assert data.loc['2021-01-01 07:00:00-05:00', 'WindSpeed (m/s)'] == 0
72
- # Assert that the index is parsed correctly
73
- pd.testing.assert_index_equal(data.index, high_resolution_index)
74
-
75
-
76
- def test_read_solaranywhere_map_variables():
77
- # Check that variables are mapped by default to pvlib names
78
- data, meta = pvlib.iotools.read_solaranywhere(TESTFILE_HIGH_RESOLUTION)
79
- mapped_column_names = ['ghi', 'dni', 'dhi', 'temp_air', 'wind_speed',
80
- 'relative_humidity', 'ghi_clear', 'dni_clear',
81
- 'dhi_clear', 'albedo']
82
- for c in mapped_column_names:
83
- assert c in data.columns
84
- assert meta['latitude'] == 44.4675
85
- assert meta['longitude'] == -73.2075
86
- assert meta['altitude'] == 41.0
87
-
88
-
89
- def test_read_solaranywhere_tmy(tmy_index, tmy_ghi_series):
90
- # Check that TMY files are correctly parsed
91
- data, meta = pvlib.iotools.read_solaranywhere(TESTFILE_TMY)
92
- # Check that columns names are correct and mapped to pvlib names
93
- assert 'ghi' in data.columns
94
- assert 'dni' in data.columns
95
- assert 'dhi' in data.columns
96
- assert 'temp_air' in data.columns
97
- # Check that metadata is parsed correctly
98
- assert meta['latitude'] == 44.465
99
- assert meta['longitude'] == -73.205
100
- assert meta['altitude'] == 41.0
101
- assert meta['name'] == 'Burlington United States'
102
- assert meta['TZ'] == -5.0
103
- assert meta['Data Version'] == '3.6'
104
- assert meta['LatLon Resolution'] == 0.010
105
- assert meta['Time Resolution'] == '60 minutes'
106
- # Assert that the index is parsed correctly
107
- pd.testing.assert_index_equal(data.index, tmy_index)
108
- # Test one column
109
- pd.testing.assert_series_equal(data['ghi'], tmy_ghi_series)
110
-
111
-
112
- @pytest.mark.remote_data
113
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
114
- def test_get_solaranywhere_bad_probability_of_exceedance():
115
- # Test if ValueError is raised if probability_of_exceedance is not integer
116
- with pytest.raises(ValueError, match="must be an integer"):
117
- pvlib.iotools.get_solaranywhere(
118
- latitude=44, longitude=-73, api_key='empty',
119
- source='SolarAnywherePOELatest', probability_of_exceedance=0.5)
120
-
121
-
122
- @pytest.mark.remote_data
123
- @requires_solaranywhere_credentials
124
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
125
- def test_get_solaranywhere_missing_start_end(solaranywhere_api_key):
126
- # Test if ValueError is raised if start/end is missing for non-TMY request
127
- with pytest.raises(ValueError, match="simulation start and end time"):
128
- pvlib.iotools.get_solaranywhere(
129
- latitude=44, longitude=-73, api_key=solaranywhere_api_key,
130
- source='SolarAnywhereLatest')
131
-
132
-
133
- @pytest.fixture
134
- def time_series_index():
135
- index = pd.date_range(start='2019-12-31 19:02:30-05:00', periods=288,
136
- freq='5min')
137
- index.name = 'ObservationTime'
138
- index.freq = None
139
- return index
140
-
141
-
142
- @pytest.fixture
143
- def timeseries_temp_air(time_series_index):
144
- temp_air = [
145
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
146
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
147
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
148
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
149
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
150
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
151
- 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
152
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2,
153
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
154
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
155
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
156
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
157
- ]
158
- return pd.Series(data=temp_air, index=time_series_index, name='temp_air')
159
-
160
-
161
- @requires_solaranywhere_credentials
162
- @pytest.mark.remote_data
163
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
164
- def test_get_solaranywhere_no_timezone(
165
- solaranywhere_api_key, time_series_index, timeseries_temp_air):
166
- # Test if data can be retrieved. This test only retrieves one day of data
167
- # to minimize the request time.
168
- data, meta = pvlib.iotools.get_solaranywhere(
169
- latitude=44.4675, longitude=-73.2075, api_key=solaranywhere_api_key,
170
- # specify start/end without timezone information
171
- start=pd.Timestamp(2020, 1, 1), end=pd.Timestamp(2020, 1, 2),
172
- # test specific version of SolarAnywhere
173
- source='SolarAnywhere3_6',
174
- spatial_resolution=0.005, time_resolution=5, true_dynamics=True)
175
-
176
- # Check metadata, including that true-dynamics is set
177
- assert meta['WeatherSiteName'] == 'SolarAnywhere3_6'
178
- assert meta['ApplyTrueDynamics'] is True
179
- assert meta['time_resolution'] == 5
180
- assert meta['spatial_resolution'] == 0.005
181
- assert meta['latitude'] == 44.4675
182
- assert meta['longitude'] == -73.2075
183
- assert meta['altitude'] == 41.0
184
-
185
- # Check that variables have been mapped (default convention)
186
- assert 'StartTime' in data.columns
187
- assert 'ObservationTime' in data.columns
188
- assert 'EndTime' in data.columns
189
- assert 'ghi' in data.columns
190
- assert 'dni' in data.columns
191
- assert 'dhi' in data.columns
192
- assert 'temp_air' in data.columns
193
- assert 'wind_speed' in data.columns
194
- assert 'albedo' in data.columns
195
- assert 'DataVersion' in data.columns
196
-
197
- # Assert index (checks that time resolution is 5 min)
198
- pd.testing.assert_index_equal(data.index, time_series_index)
199
- # Test one column
200
- pd.testing.assert_series_equal(data['temp_air'], timeseries_temp_air)
201
-
202
-
203
- @requires_solaranywhere_credentials
204
- @pytest.mark.remote_data
205
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
206
- def test_get_solaranywhere_other_options(
207
- solaranywhere_api_key, time_series_index, timeseries_temp_air):
208
- # Test if data can be retrieved. This test only retrieves one day of data
209
- # to minimize the request time.
210
- data, meta = pvlib.iotools.get_solaranywhere(
211
- latitude=44.4675, longitude=-73.2075, api_key=solaranywhere_api_key,
212
- # specify start/end as str with timezone information
213
- start='2020-01-01 00:00:00+0000',
214
- end='2020-01-02 00:00:00+0000',
215
- # test specific version of SolarAnywhere
216
- source='SolarAnywhere3_7',
217
- # test fewer variables
218
- variables=[
219
- 'ObservationTime',
220
- 'GlobalHorizontalIrradiance_WattsPerMeterSquared',
221
- ],
222
- map_variables=False)
223
-
224
- # Check metadata
225
- assert meta['WeatherSiteName'] == 'SolarAnywhere3_7'
226
- assert meta['ApplyTrueDynamics'] is False # default setting
227
- assert meta['time_resolution'] == 60 # default resolution
228
- assert meta['spatial_resolution'] == 0.01 # default resolution
229
- assert meta['latitude'] == 44.4675
230
- assert meta['longitude'] == -73.2075
231
- assert meta['altitude'] == 41.0
232
-
233
- # Check that variables have been mapped (default convention)
234
- assert 'StartTime' not in data.columns
235
- assert 'ObservationTime' in data.columns
236
- assert 'EndTime' not in data.columns
237
- # Check that ghi is not mapped
238
- assert 'ghi' not in data.columns
239
- assert 'GlobalHorizontalIrradiance_WattsPerMeterSquared' in data.columns
240
- assert 'dni' not in data.columns
241
- assert 'dhi' not in data.columns
242
- assert 'temp_air' not in data.columns
243
- assert 'wind_speed' not in data.columns
244
- assert 'albedo' not in data.columns
245
- assert 'DataVersion' not in data.columns
246
-
247
-
248
- @requires_solaranywhere_credentials
249
- @pytest.mark.remote_data
250
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
251
- def test_get_solaranywhere_probability_exceedance_error(solaranywhere_api_key):
252
- # Test if ValueError is raised when passing start/end to typical year
253
- with pytest.raises(ValueError, match="start and end time must be null"):
254
- data, meta = pvlib.iotools.get_solaranywhere(
255
- latitude=44.4675, longitude=-73.2075,
256
- api_key=solaranywhere_api_key,
257
- # Probabiliy of exceedance year should not have start/end specified
258
- start=pd.Timestamp('2020-01-01 00:00:00+0000'),
259
- end=pd.Timestamp('2020-01-05 12:00:00+0000'),
260
- source='SolarAnywherePOELatest',
261
- probability_of_exceedance=20)
262
-
263
-
264
- @requires_solaranywhere_credentials
265
- @pytest.mark.remote_data
266
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
267
- def test_get_solaranywhere_timeout_tgy(solaranywhere_api_key):
268
- # Test if the service times out when the timeout parameter is close to zero
269
- with pytest.raises(TimeoutError, match="Time exceeded"):
270
- pvlib.iotools.get_solaranywhere(
271
- latitude=44.4675, longitude=-73.2075,
272
- api_key=solaranywhere_api_key,
273
- source='SolarAnywhereTGYLatest',
274
- timeout=0.00001)
275
-
276
-
277
- @requires_solaranywhere_credentials
278
- @pytest.mark.remote_data
279
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
280
- def test_get_solaranywhere_not_available(solaranywhere_api_key):
281
- # Test if RuntimeError is raised if location in the ocean is requested
282
- with pytest.raises(RuntimeError, match="Tile is outside of our coverage"):
283
- pvlib.iotools.get_solaranywhere(
284
- latitude=40, longitude=-70,
285
- api_key=solaranywhere_api_key,
286
- start=pd.Timestamp('2020-01-01 00:00:00+0000'),
287
- end=pd.Timestamp('2020-01-05 12:00:00+0000'))
@@ -1,68 +0,0 @@
1
- import pandas as pd
2
- import pytest
3
- import pvlib
4
- import requests
5
- from ..conftest import (RERUNS, RERUNS_DELAY, assert_frame_equal,
6
- assert_index_equal)
7
-
8
-
9
- @pytest.fixture
10
- def hourly_index():
11
- hourly_index = pd.date_range(start='2022-01-01 00:30+01:00', freq='60min',
12
- periods=24, name='dateTime')
13
- hourly_index.freq = None
14
- return hourly_index
15
-
16
-
17
- @pytest.fixture
18
- def hourly_index_start_utc():
19
- hourly_index_left_utc = pd.date_range(
20
- start='2023-01-01 00:00+00:00', freq='30min', periods=24*2,
21
- name='dateTime')
22
- hourly_index_left_utc.freq = None
23
- return hourly_index_left_utc
24
-
25
-
26
- @pytest.fixture
27
- def hourly_dataframe(hourly_index):
28
- ghi = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 5.0, 73.0, 152.0, 141.0, 105.0,
29
- 62.0, 65.0, 62.0, 11.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
30
- dni = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 30.0, 233.0, 301.0, 136.0, 32.0,
31
- 0.0, 3.0, 77.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
32
- return pd.DataFrame(data={'ghi': ghi, 'dni': dni}, index=hourly_index)
33
-
34
-
35
- @pytest.mark.remote_data
36
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
37
- def test_get_solargis(hourly_dataframe):
38
- data, meta = pvlib.iotools.get_solargis(
39
- latitude=48.61259, longitude=20.827079,
40
- start='2022-01-01', end='2022-01-01',
41
- tz='GMT+01', variables=['GHI', 'DNI'],
42
- time_resolution='HOURLY', api_key='demo')
43
- assert_frame_equal(data, hourly_dataframe)
44
-
45
-
46
- @pytest.mark.remote_data
47
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
48
- def test_get_solargis_utc_start_timestamp(hourly_index_start_utc):
49
- data, meta = pvlib.iotools.get_solargis(
50
- latitude=48.61259, longitude=20.827079,
51
- start='2023-01-01', end='2023-01-01',
52
- variables=['GTI'],
53
- timestamp_type='start',
54
- time_resolution='MIN_30',
55
- map_variables=False, api_key='demo')
56
- assert 'GTI' in data.columns # assert that variables aren't mapped
57
- assert_index_equal(data.index, hourly_index_start_utc)
58
-
59
-
60
- @pytest.mark.remote_data
61
- @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY)
62
- def test_get_solargis_http_error():
63
- # Test if HTTPError is raised if date outside range is specified
64
- with pytest.raises(requests.HTTPError, match="data coverage"):
65
- _, _ = pvlib.iotools.get_solargis(
66
- latitude=48.61259, longitude=20.827079,
67
- start='1920-01-01', end='1920-01-01', # date outside range
68
- variables=['GHI', 'DNI'], time_resolution='HOURLY', api_key='demo')