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,192 +0,0 @@
1
- """
2
- test bifical.utils
3
- """
4
- import numpy as np
5
- import pytest
6
- from pvlib.bifacial import utils
7
- from pvlib.shading import masking_angle, ground_angle
8
- from pvlib.tools import cosd
9
- from scipy.integrate import trapezoid
10
-
11
-
12
- @pytest.fixture
13
- def test_system_fixed_tilt():
14
- syst = {'height': 1.0,
15
- 'pitch': 2.,
16
- 'surface_tilt': 30.,
17
- 'surface_azimuth': 180.,
18
- 'axis_azimuth': None,
19
- 'rotation': -30.}
20
- syst['gcr'] = 1.0 / syst['pitch']
21
- # view factors from 3 points on the ground between rows to the sky
22
- pts = np.linspace(0, 1, num=3)
23
- sqr3 = np.sqrt(3) / 4
24
- # c_i,j = cos(angle from point i to edge of row j), j=0 is row = -1
25
- # c_i,j = cos(angle from point i to edge of row j), j=0 is row = -1
26
- c00 = (-2 - sqr3) / np.sqrt(1.25**2 + (2 + sqr3)**2) # right edge row -1
27
- c01 = -sqr3 / np.sqrt(1.25**2 + sqr3**2) # right edge row 0
28
- c02 = sqr3 / np.sqrt(0.75**2 + sqr3**2) # left edge of row 0
29
- c03 = (2 - sqr3) / np.sqrt(1.25**2 + (2 - sqr3)**2) # right edge of row 1
30
- vf_0 = 0.5 * (c03 - c02 + c01 - c00) # vf at point 0
31
- c10 = (-3 - sqr3) / np.sqrt(1.25**2 + (3 + sqr3)**2) # right edge row -1
32
- c11 = (-1 - sqr3) / np.sqrt(1.25**2 + (1 + sqr3)**2) # right edge row 0
33
- c12 = (-1 + sqr3) / np.sqrt(0.75**2 + (-1 + sqr3)**2) # left edge row 0
34
- c13 = (1 - sqr3) / np.sqrt(1.25**2 + (1 - sqr3)**2) # right edge row
35
- vf_1 = 0.5 * (c13 - c12 + c11 - c10) # vf at point 1
36
- c20 = -(4 + sqr3) / np.sqrt(1.25**2 + (4 + sqr3)**2) # right edge row -1
37
- c21 = (-2 + sqr3) / np.sqrt(0.75**2 + (-2 + sqr3)**2) # left edge row 0
38
- c22 = (-2 - sqr3) / np.sqrt(1.25**2 + (2 + sqr3)**2) # right edge row 0
39
- c23 = (0 - sqr3) / np.sqrt(1.25**2 + (0 - sqr3)**2) # right edge row 1
40
- vf_2 = 0.5 * (c23 - c22 + c21 - c20) # vf at point 1
41
- vfs_ground_sky = np.array([[vf_0], [vf_1], [vf_2]])
42
- return syst, pts, vfs_ground_sky
43
-
44
-
45
- def test__solar_projection_tangent():
46
- tan_phi_f = utils._solar_projection_tangent(
47
- 30, 150, 180)
48
- tan_phi_b = utils._solar_projection_tangent(
49
- 30, 150, 0)
50
- assert np.allclose(tan_phi_f, 0.5)
51
- assert np.allclose(tan_phi_b, -0.5)
52
- assert np.allclose(tan_phi_f, -tan_phi_b)
53
-
54
-
55
- @pytest.mark.parametrize(
56
- "gcr,surface_tilt,surface_azimuth,solar_zenith,solar_azimuth,expected",
57
- [(0.5, 0., 180., 0., 180., 0.5),
58
- (1.0, 0., 180., 0., 180., 0.0),
59
- (1.0, 90., 180., 0., 180., 1.0),
60
- (0.5, 45., 180., 45., 270., 1.0 - np.sqrt(2) / 4),
61
- (0.5, 45., 180., 90., 180., 0.),
62
- (np.sqrt(2) / 2, 45, 180, 0, 180, 0.5),
63
- (np.sqrt(2) / 2, 45, 180, 45, 180, 0.0),
64
- (np.sqrt(2) / 2, 45, 180, 45, 90, 0.5),
65
- (np.sqrt(2) / 2, 45, 180, 45, 0, 1.0),
66
- (np.sqrt(2) / 2, 45, 180, 45, 135, 0.5 * (1 - np.sqrt(2) / 2)),
67
- ])
68
- def test__unshaded_ground_fraction(
69
- surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, gcr,
70
- expected):
71
- # frontside, same for both sides
72
- f_sky_beam_f = utils._unshaded_ground_fraction(
73
- surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, gcr)
74
- assert np.allclose(f_sky_beam_f, expected)
75
- # backside, should be the same as frontside
76
- f_sky_beam_b = utils._unshaded_ground_fraction(
77
- 180. - surface_tilt, surface_azimuth - 180., solar_zenith,
78
- solar_azimuth, gcr)
79
- assert np.allclose(f_sky_beam_b, expected)
80
-
81
-
82
- def test__vf_ground_sky_2d(test_system_fixed_tilt):
83
- # vector input
84
- ts, pts, vfs_gnd_sky = test_system_fixed_tilt
85
- vfs = utils.vf_ground_sky_2d(ts['rotation'], ts['gcr'], pts,
86
- ts['pitch'], ts['height'], max_rows=1)
87
- assert np.allclose(vfs, vfs_gnd_sky, rtol=0.1) # middle point vf is off
88
- # test with singleton x
89
- vf = utils.vf_ground_sky_2d(ts['rotation'], ts['gcr'], pts[0],
90
- ts['pitch'], ts['height'], max_rows=1)
91
- assert np.isclose(vf, vfs_gnd_sky[0])
92
-
93
-
94
- @pytest.mark.parametrize("vectorize", [True, False])
95
- def test_vf_ground_sky_2d_integ(test_system_fixed_tilt, vectorize):
96
- ts, pts, vfs_gnd_sky = test_system_fixed_tilt
97
- # pass rotation here since max_rows=1 for the hand-solved case in
98
- # the fixture test_system, which means the ground-to-sky view factor
99
- # isn't summed over enough rows for symmetry to hold.
100
- vf_integ = utils.vf_ground_sky_2d_integ(
101
- ts['rotation'], ts['gcr'], ts['height'], ts['pitch'],
102
- max_rows=1, npoints=3, vectorize=vectorize)
103
- expected_vf_integ = trapezoid(vfs_gnd_sky, pts, axis=0)
104
- assert np.isclose(vf_integ, expected_vf_integ, rtol=0.1)
105
-
106
-
107
- def test_vf_row_sky_2d(test_system_fixed_tilt):
108
- ts, _, _ = test_system_fixed_tilt
109
- # with float input, fx at top of row
110
- vf = utils.vf_row_sky_2d(ts['surface_tilt'], ts['gcr'], 1.)
111
- expected = 0.5 * (1 + cosd(ts['surface_tilt']))
112
- assert np.isclose(vf, expected)
113
- # with array input
114
- fx = np.array([0., 0.5, 1.])
115
- vf = utils.vf_row_sky_2d(ts['surface_tilt'], ts['gcr'], fx)
116
- phi = masking_angle(ts['surface_tilt'], ts['gcr'], fx)
117
- expected = 0.5 * (1 + cosd(ts['surface_tilt'] + phi))
118
- assert np.allclose(vf, expected)
119
-
120
-
121
- def test_vf_row_sky_2d_integ(test_system_fixed_tilt):
122
- ts, _, _ = test_system_fixed_tilt
123
- # with float input, check end position
124
- with np.errstate(invalid='ignore'):
125
- vf = utils.vf_row_sky_2d_integ(ts['surface_tilt'], ts['gcr'], 1., 1.)
126
- expected = utils.vf_row_sky_2d(ts['surface_tilt'], ts['gcr'], 1.)
127
- assert np.isclose(vf, expected)
128
- # with array input
129
- fx0 = np.array([0., 0.5])
130
- fx1 = np.array([0., 0.8])
131
- with np.errstate(invalid='ignore'):
132
- vf = utils.vf_row_sky_2d_integ(ts['surface_tilt'], ts['gcr'], fx0, fx1)
133
- phi = masking_angle(ts['surface_tilt'], ts['gcr'], fx0[0])
134
- y0 = 0.5 * (1 + cosd(ts['surface_tilt'] + phi))
135
- x = np.arange(fx0[1], fx1[1], 1e-4)
136
- phi_y = masking_angle(ts['surface_tilt'], ts['gcr'], x)
137
- y = 0.5 * (1 + cosd(ts['surface_tilt'] + phi_y))
138
- y1 = trapezoid(y, x) / (fx1[1] - fx0[1])
139
- expected = np.array([y0, y1])
140
- assert np.allclose(vf, expected, rtol=1e-3)
141
- # with defaults (0, 1)
142
- vf = utils.vf_row_sky_2d_integ(ts['surface_tilt'], ts['gcr'])
143
- x = np.arange(0, 1, 1e-4)
144
- phi_y = masking_angle(ts['surface_tilt'], ts['gcr'], x)
145
- y = 0.5 * (1 + cosd(ts['surface_tilt'] + phi_y))
146
- y1 = trapezoid(y, x) / (1 - 0)
147
- assert np.allclose(vf, y1, rtol=1e-3)
148
-
149
-
150
- def test_vf_row_ground_2d(test_system_fixed_tilt):
151
- ts, _, _ = test_system_fixed_tilt
152
- # with float input, fx at bottom of row
153
- vf = utils.vf_row_ground_2d(ts['surface_tilt'], ts['gcr'], 0.)
154
- expected = 0.5 * (1. - cosd(ts['surface_tilt']))
155
- assert np.isclose(vf, expected)
156
- # with array input
157
- fx = np.array([0., 0.5, 1.0])
158
- vf = utils.vf_row_ground_2d(ts['surface_tilt'], ts['gcr'], fx)
159
- phi = ground_angle(ts['surface_tilt'], ts['gcr'], fx)
160
- expected = 0.5 * (1 - cosd(phi - ts['surface_tilt']))
161
- assert np.allclose(vf, expected)
162
-
163
-
164
- def test_vf_ground_2d_integ(test_system_fixed_tilt):
165
- ts, _, _ = test_system_fixed_tilt
166
- # with float input, check end position
167
- with np.errstate(invalid='ignore'):
168
- vf = utils.vf_row_ground_2d_integ(ts['surface_tilt'], ts['gcr'],
169
- 0., 0.)
170
- expected = utils.vf_row_ground_2d(ts['surface_tilt'], ts['gcr'], 0.)
171
- assert np.isclose(vf, expected)
172
- # with array input
173
- fx0 = np.array([0., 0.5])
174
- fx1 = np.array([0., 0.8])
175
- with np.errstate(invalid='ignore'):
176
- vf = utils.vf_row_ground_2d_integ(ts['surface_tilt'], ts['gcr'],
177
- fx0, fx1)
178
- phi = ground_angle(ts['surface_tilt'], ts['gcr'], fx0[0])
179
- y0 = 0.5 * (1 - cosd(phi - ts['surface_tilt']))
180
- x = np.arange(fx0[1], fx1[1], 1e-4)
181
- phi_y = ground_angle(ts['surface_tilt'], ts['gcr'], x)
182
- y = 0.5 * (1 - cosd(phi_y - ts['surface_tilt']))
183
- y1 = trapezoid(y, x) / (fx1[1] - fx0[1])
184
- expected = np.array([y0, y1])
185
- assert np.allclose(vf, expected, rtol=1e-2)
186
- # with defaults (0, 1)
187
- vf = utils.vf_row_ground_2d_integ(ts['surface_tilt'], ts['gcr'], 0, 1)
188
- x = np.arange(0, 1, 1e-4)
189
- phi_y = ground_angle(ts['surface_tilt'], ts['gcr'], x)
190
- y = 0.5 * (1 - cosd(phi_y - ts['surface_tilt']))
191
- y1 = trapezoid(y, x) / (1 - 0)
192
- assert np.allclose(vf, y1, rtol=1e-2)
pvlib/tests/conftest.py DELETED
@@ -1,476 +0,0 @@
1
- from pathlib import Path
2
- import platform
3
- import warnings
4
-
5
- import pandas as pd
6
- import os
7
- from packaging.version import Version
8
- import pytest
9
- from functools import wraps
10
-
11
- import pvlib
12
- from pvlib.location import Location
13
-
14
-
15
- pvlib_base_version = Version(Version(pvlib.__version__).base_version)
16
-
17
-
18
- # decorator takes one argument: the base version for which it should fail
19
- # for example @fail_on_pvlib_version('0.7') will cause a test to fail
20
- # on pvlib versions 0.7a, 0.7b, 0.7rc1, etc.
21
- def fail_on_pvlib_version(version):
22
- # second level of decorator takes the function under consideration
23
- def wrapper(func):
24
- # third level defers computation until the test is called
25
- # this allows the specific test to fail at test runtime,
26
- # rather than at decoration time (when the module is imported)
27
- @wraps(func)
28
- def inner(*args, **kwargs):
29
- # fail if the version is too high
30
- if pvlib_base_version >= Version(version):
31
- pytest.fail('the tested function is scheduled to be '
32
- 'removed in %s' % version)
33
- # otherwise return the function to be executed
34
- else:
35
- return func(*args, **kwargs)
36
- return inner
37
- return wrapper
38
-
39
-
40
- def _check_pandas_assert_kwargs(kwargs):
41
- # handles the change in API related to default
42
- # tolerances in pandas 1.1.0. See pvlib GH #1018
43
- if Version(pd.__version__) >= Version('1.1.0'):
44
- if kwargs.pop('check_less_precise', False):
45
- kwargs['atol'] = 1e-3
46
- kwargs['rtol'] = 1e-3
47
- else:
48
- kwargs['atol'] = 1e-5
49
- kwargs['rtol'] = 1e-5
50
- else:
51
- kwargs.pop('rtol', None)
52
- kwargs.pop('atol', None)
53
- return kwargs
54
-
55
-
56
- def assert_index_equal(left, right, **kwargs):
57
- kwargs = _check_pandas_assert_kwargs(kwargs)
58
- pd.testing.assert_index_equal(left, right, **kwargs)
59
-
60
-
61
- def assert_series_equal(left, right, **kwargs):
62
- kwargs = _check_pandas_assert_kwargs(kwargs)
63
- pd.testing.assert_series_equal(left, right, **kwargs)
64
-
65
-
66
- def assert_frame_equal(left, right, **kwargs):
67
- kwargs = _check_pandas_assert_kwargs(kwargs)
68
- pd.testing.assert_frame_equal(left, right, **kwargs)
69
-
70
-
71
- # commonly used directories in the tests
72
- TEST_DIR = Path(__file__).parent
73
- DATA_DIR = TEST_DIR.parent / 'data'
74
-
75
-
76
- # pytest-rerunfailures variables
77
- RERUNS = 5
78
- RERUNS_DELAY = 2
79
-
80
-
81
- platform_is_windows = platform.system() == 'Windows'
82
- skip_windows = pytest.mark.skipif(platform_is_windows,
83
- reason='does not run on windows')
84
-
85
-
86
- try:
87
- # Attempt to load BSRN credentials used for testing pvlib.iotools.get_bsrn
88
- bsrn_username = os.environ["BSRN_FTP_USERNAME"]
89
- bsrn_password = os.environ["BSRN_FTP_PASSWORD"]
90
- has_bsrn_credentials = True
91
- except KeyError:
92
- has_bsrn_credentials = False
93
-
94
- requires_bsrn_credentials = pytest.mark.skipif(
95
- not has_bsrn_credentials, reason='requires bsrn credentials')
96
-
97
-
98
- try:
99
- # Attempt to load SolarAnywhere API key used for testing
100
- # pvlib.iotools.get_solaranywhere
101
- solaranywhere_api_key = os.environ["SOLARANYWHERE_API_KEY"]
102
- has_solaranywhere_credentials = True
103
- except KeyError:
104
- has_solaranywhere_credentials = False
105
-
106
- requires_solaranywhere_credentials = pytest.mark.skipif(
107
- not has_solaranywhere_credentials,
108
- reason='requires solaranywhere credentials')
109
-
110
-
111
- try:
112
- import statsmodels # noqa: F401
113
- has_statsmodels = True
114
- except ImportError:
115
- has_statsmodels = False
116
-
117
- requires_statsmodels = pytest.mark.skipif(
118
- not has_statsmodels, reason='requires statsmodels')
119
-
120
-
121
- try:
122
- import ephem # noqa: F401
123
- has_ephem = True
124
- except ImportError:
125
- has_ephem = False
126
-
127
- requires_ephem = pytest.mark.skipif(not has_ephem, reason='requires ephem')
128
-
129
-
130
- def has_spa_c():
131
- try:
132
- from pvlib.spa_c_files.spa_py import spa_calc # noqa: F401
133
- except ImportError:
134
- return False
135
- else:
136
- return True
137
-
138
-
139
- requires_spa_c = pytest.mark.skipif(not has_spa_c(), reason="requires spa_c")
140
-
141
-
142
- try:
143
- import numba # noqa: F401
144
- has_numba = True
145
- except ImportError:
146
- has_numba = False
147
-
148
-
149
- requires_numba = pytest.mark.skipif(not has_numba, reason="requires numba")
150
-
151
-
152
- try:
153
- import pvfactors # noqa: F401
154
- has_pvfactors = True
155
- except ImportError:
156
- has_pvfactors = False
157
-
158
- requires_pvfactors = pytest.mark.skipif(not has_pvfactors,
159
- reason='requires pvfactors')
160
-
161
-
162
- try:
163
- import PySAM # noqa: F401
164
- has_pysam = True
165
- except ImportError:
166
- has_pysam = False
167
-
168
- requires_pysam = pytest.mark.skipif(not has_pysam, reason="requires PySAM")
169
-
170
-
171
- has_pandas_2_0 = Version(pd.__version__) >= Version("2.0.0")
172
- requires_pandas_2_0 = pytest.mark.skipif(not has_pandas_2_0,
173
- reason="requires pandas>=2.0.0")
174
-
175
-
176
- @pytest.fixture()
177
- def golden():
178
- return Location(39.742476, -105.1786, 'America/Denver', 1830.14)
179
-
180
-
181
- @pytest.fixture()
182
- def golden_mst():
183
- return Location(39.742476, -105.1786, 'MST', 1830.14)
184
-
185
-
186
- @pytest.fixture()
187
- def expected_solpos():
188
- return pd.DataFrame({'elevation': 39.872046,
189
- 'apparent_zenith': 50.111622,
190
- 'azimuth': 194.340241,
191
- 'apparent_elevation': 39.888378},
192
- index=['2003-10-17T12:30:30Z'])
193
-
194
-
195
- @pytest.fixture(scope="session")
196
- def sam_data():
197
- data = {}
198
- with warnings.catch_warnings():
199
- # ignore messages about duplicate entries in the databases.
200
- warnings.simplefilter("ignore", UserWarning)
201
- data['sandiamod'] = pvlib.pvsystem.retrieve_sam('sandiamod')
202
- data['adrinverter'] = pvlib.pvsystem.retrieve_sam('adrinverter')
203
- return data
204
-
205
-
206
- @pytest.fixture(scope="function")
207
- def pvsyst_module_params():
208
- """
209
- Define some PVSyst module parameters for testing.
210
-
211
- The scope of the fixture is set to ``'function'`` to allow tests to modify
212
- parameters if required without affecting other tests.
213
- """
214
- parameters = {
215
- 'gamma_ref': 1.05,
216
- 'mu_gamma': 0.001,
217
- 'I_L_ref': 6.0,
218
- 'I_o_ref': 5e-9,
219
- 'EgRef': 1.121,
220
- 'R_sh_ref': 300,
221
- 'R_sh_0': 1000,
222
- 'R_s': 0.5,
223
- 'R_sh_exp': 5.5,
224
- 'cells_in_series': 60,
225
- 'alpha_sc': 0.001,
226
- }
227
- return parameters
228
-
229
-
230
- @pytest.fixture(scope='function')
231
- def adr_inverter_parameters():
232
- """
233
- Define some ADR inverter parameters for testing.
234
-
235
- The scope of the fixture is set to ``'function'`` to allow tests to modify
236
- parameters if required without affecting other tests.
237
- """
238
- parameters = {
239
- 'Name': 'Ablerex Electronics Co., Ltd.: ES 2200-US-240 (240Vac)'
240
- '[CEC 2011]',
241
- 'Vac': 240.,
242
- 'Pacmax': 2110.,
243
- 'Pnom': 2200.,
244
- 'Vnom': 396.,
245
- 'Vmin': 155.,
246
- 'Vmax': 413.,
247
- 'Vdcmax': 500.,
248
- 'MPPTHi': 450.,
249
- 'MPPTLow': 150.,
250
- 'Pnt': 0.25,
251
- 'ADRCoefficients': [0.01385, 0.0152, 0.00794, 0.00286, -0.01872,
252
- -0.01305, 0.0, 0.0, 0.0]
253
- }
254
- return parameters
255
-
256
-
257
- @pytest.fixture(scope='function')
258
- def cec_inverter_parameters():
259
- """
260
- Define some CEC inverter parameters for testing.
261
-
262
- The scope of the fixture is set to ``'function'`` to allow tests to modify
263
- parameters if required without affecting other tests.
264
- """
265
- parameters = {
266
- 'Name': 'ABB: MICRO-0.25-I-OUTD-US-208 208V [CEC 2014]',
267
- 'Vac': 208.0,
268
- 'Paco': 250.0,
269
- 'Pdco': 259.5220505,
270
- 'Vdco': 40.24260317,
271
- 'Pso': 1.771614224,
272
- 'C0': -2.48e-5,
273
- 'C1': -9.01e-5,
274
- 'C2': 6.69e-4,
275
- 'C3': -0.0189,
276
- 'Pnt': 0.02,
277
- 'Vdcmax': 65.0,
278
- 'Idcmax': 10.0,
279
- 'Mppt_low': 20.0,
280
- 'Mppt_high': 50.0,
281
- }
282
- return parameters
283
-
284
-
285
- @pytest.fixture(scope='function')
286
- def cec_module_params():
287
- """
288
- Define some CEC module parameters for testing.
289
-
290
- The scope of the fixture is set to ``'function'`` to allow tests to modify
291
- parameters if required without affecting other tests.
292
- """
293
- parameters = {
294
- 'Name': 'Example Module',
295
- 'BIPV': 'Y',
296
- 'Date': '4/28/2008',
297
- 'T_NOCT': 65,
298
- 'A_c': 0.67,
299
- 'N_s': 18,
300
- 'I_sc_ref': 7.5,
301
- 'V_oc_ref': 10.4,
302
- 'I_mp_ref': 6.6,
303
- 'V_mp_ref': 8.4,
304
- 'alpha_sc': 0.003,
305
- 'beta_oc': -0.04,
306
- 'a_ref': 0.473,
307
- 'I_L_ref': 7.545,
308
- 'I_o_ref': 1.94e-09,
309
- 'R_s': 0.094,
310
- 'R_sh_ref': 15.72,
311
- 'Adjust': 10.6,
312
- 'gamma_r': -0.5,
313
- 'Version': 'MM105',
314
- 'PTC': 48.9,
315
- 'Technology': 'Multi-c-Si',
316
- }
317
- return parameters
318
-
319
-
320
- @pytest.fixture(scope='function')
321
- def cec_module_cs5p_220m():
322
- """
323
- Define Canadian Solar CS5P-220M module parameters for testing.
324
-
325
- The scope of the fixture is set to ``'function'`` to allow tests to modify
326
- parameters if required without affecting other tests.
327
- """
328
- parameters = {
329
- 'Name': 'Canadian Solar CS5P-220M',
330
- 'BIPV': 'N',
331
- 'Date': '10/5/2009',
332
- 'T_NOCT': 42.4,
333
- 'A_c': 1.7,
334
- 'N_s': 96,
335
- 'I_sc_ref': 5.1,
336
- 'V_oc_ref': 59.4,
337
- 'I_mp_ref': 4.69,
338
- 'V_mp_ref': 46.9,
339
- 'alpha_sc': 0.004539,
340
- 'beta_oc': -0.22216,
341
- 'a_ref': 2.6373,
342
- 'I_L_ref': 5.114,
343
- 'I_o_ref': 8.196e-10,
344
- 'R_s': 1.065,
345
- 'R_sh_ref': 381.68,
346
- 'Adjust': 8.7,
347
- 'gamma_r': -0.476,
348
- 'Version': 'MM106',
349
- 'PTC': 200.1,
350
- 'Technology': 'Mono-c-Si',
351
- }
352
- return parameters
353
-
354
-
355
- @pytest.fixture(scope='function')
356
- def cec_module_spr_e20_327():
357
- """
358
- Define SunPower SPR-E20-327 module parameters for testing.
359
-
360
- The scope of the fixture is set to ``'function'`` to allow tests to modify
361
- parameters if required without affecting other tests.
362
- """
363
- parameters = {
364
- 'Name': 'SunPower SPR-E20-327',
365
- 'BIPV': 'N',
366
- 'Date': '1/14/2013',
367
- 'T_NOCT': 46,
368
- 'A_c': 1.631,
369
- 'N_s': 96,
370
- 'I_sc_ref': 6.46,
371
- 'V_oc_ref': 65.1,
372
- 'I_mp_ref': 5.98,
373
- 'V_mp_ref': 54.7,
374
- 'alpha_sc': 0.004522,
375
- 'beta_oc': -0.23176,
376
- 'a_ref': 2.6868,
377
- 'I_L_ref': 6.468,
378
- 'I_o_ref': 1.88e-10,
379
- 'R_s': 0.37,
380
- 'R_sh_ref': 298.13,
381
- 'Adjust': -0.1862,
382
- 'gamma_r': -0.386,
383
- 'Version': 'NRELv1',
384
- 'PTC': 301.4,
385
- 'Technology': 'Mono-c-Si',
386
- }
387
- return parameters
388
-
389
-
390
- @pytest.fixture(scope='function')
391
- def cec_module_fs_495():
392
- """
393
- Define First Solar FS-495 module parameters for testing.
394
-
395
- The scope of the fixture is set to ``'function'`` to allow tests to modify
396
- parameters if required without affecting other tests.
397
- """
398
- parameters = {
399
- 'Name': 'First Solar FS-495',
400
- 'BIPV': 'N',
401
- 'Date': '9/18/2014',
402
- 'T_NOCT': 44.6,
403
- 'A_c': 0.72,
404
- 'N_s': 216,
405
- 'I_sc_ref': 1.55,
406
- 'V_oc_ref': 86.5,
407
- 'I_mp_ref': 1.4,
408
- 'V_mp_ref': 67.9,
409
- 'alpha_sc': 0.000924,
410
- 'beta_oc': -0.22741,
411
- 'a_ref': 2.9482,
412
- 'I_L_ref': 1.563,
413
- 'I_o_ref': 2.64e-13,
414
- 'R_s': 6.804,
415
- 'R_sh_ref': 806.27,
416
- 'Adjust': -10.65,
417
- 'gamma_r': -0.264,
418
- 'Version': 'NRELv1',
419
- 'PTC': 89.7,
420
- 'Technology': 'CdTe',
421
- }
422
- return parameters
423
-
424
-
425
- @pytest.fixture(scope='function')
426
- def sapm_temperature_cs5p_220m():
427
- # SAPM temperature model parameters for Canadian_Solar_CS5P_220M
428
- # (glass/polymer) in open rack
429
- return {'a': -3.40641, 'b': -0.0842075, 'deltaT': 3}
430
-
431
-
432
- @pytest.fixture(scope='function')
433
- def sapm_module_params():
434
- """
435
- Define SAPM model parameters for Canadian Solar CS5P 220M module.
436
-
437
- The scope of the fixture is set to ``'function'`` to allow tests to modify
438
- parameters if required without affecting other tests.
439
- """
440
- parameters = {'Material': 'c-Si',
441
- 'Cells_in_Series': 96,
442
- 'Parallel_Strings': 1,
443
- 'A0': 0.928385,
444
- 'A1': 0.068093,
445
- 'A2': -0.0157738,
446
- 'A3': 0.0016606,
447
- 'A4': -6.93E-05,
448
- 'B0': 1,
449
- 'B1': -0.002438,
450
- 'B2': 0.0003103,
451
- 'B3': -0.00001246,
452
- 'B4': 2.11E-07,
453
- 'B5': -1.36E-09,
454
- 'C0': 1.01284,
455
- 'C1': -0.0128398,
456
- 'C2': 0.279317,
457
- 'C3': -7.24463,
458
- 'C4': 0.996446,
459
- 'C5': 0.003554,
460
- 'C6': 1.15535,
461
- 'C7': -0.155353,
462
- 'Isco': 5.09115,
463
- 'Impo': 4.54629,
464
- 'Voco': 59.2608,
465
- 'Vmpo': 48.3156,
466
- 'Aisc': 0.000397,
467
- 'Aimp': 0.000181,
468
- 'Bvoco': -0.21696,
469
- 'Mbvoc': 0.0,
470
- 'Bvmpo': -0.235488,
471
- 'Mbvmp': 0.0,
472
- 'N': 1.4032,
473
- 'IXO': 4.97599,
474
- 'IXXO': 3.18803,
475
- 'FD': 1}
476
- return parameters
File without changes