pvlib 0.11.2__py3-none-any.whl → 0.12.1a1__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 (147) hide show
  1. pvlib/__init__.py +1 -0
  2. pvlib/atmosphere.py +40 -40
  3. pvlib/bifacial/infinite_sheds.py +4 -3
  4. pvlib/bifacial/utils.py +2 -1
  5. pvlib/iotools/__init__.py +6 -0
  6. pvlib/iotools/psm3.py +1 -1
  7. pvlib/iotools/psm4.py +819 -0
  8. pvlib/iotools/pvgis.py +10 -2
  9. pvlib/iotools/tmy.py +3 -69
  10. pvlib/irradiance.py +38 -15
  11. pvlib/ivtools/sdm/__init__.py +20 -0
  12. pvlib/ivtools/sdm/_fit_desoto_pvsyst_sandia.py +585 -0
  13. pvlib/ivtools/sdm/cec.py +93 -0
  14. pvlib/ivtools/sdm/desoto.py +401 -0
  15. pvlib/ivtools/sdm/pvsyst.py +630 -0
  16. pvlib/location.py +73 -33
  17. pvlib/modelchain.py +19 -36
  18. pvlib/pvsystem.py +114 -65
  19. pvlib/snow.py +64 -28
  20. pvlib/spectrum/__init__.py +0 -1
  21. pvlib/spectrum/irradiance.py +2 -64
  22. pvlib/spectrum/mismatch.py +3 -3
  23. pvlib/tools.py +6 -5
  24. {pvlib-0.11.2.dist-info → pvlib-0.12.1a1.dist-info}/METADATA +6 -5
  25. pvlib-0.12.1a1.dist-info/RECORD +80 -0
  26. {pvlib-0.11.2.dist-info → pvlib-0.12.1a1.dist-info}/WHEEL +1 -1
  27. pvlib/data/BIRD_08_16_2012.csv +0 -8761
  28. pvlib/data/BIRD_08_16_2012_patm.csv +0 -8761
  29. pvlib/data/Burlington, United States SolarAnywhere Time Series 2021 Lat_44_465 Lon_-73_205 TMY3 format.csv +0 -8762
  30. pvlib/data/Burlington, United States SolarAnywhere Time Series 20210101 to 20210103 Lat_44_4675 Lon_-73_2075 SA format.csv +0 -578
  31. pvlib/data/Burlington, United States SolarAnywhere Typical GHI Year Lat_44_465 Lon_-73_205 SA format.csv +0 -74
  32. pvlib/data/CPS SCH275KTL-DO-US-800-250kW_275kVA_1.OND +0 -146
  33. pvlib/data/CRNS0101-05-2019-AZ_Tucson_11_W.txt +0 -4
  34. pvlib/data/CRN_with_problems.txt +0 -3
  35. pvlib/data/ET-M772BH550GL.PAN +0 -75
  36. pvlib/data/NLD_Amsterdam062400_IWEC.epw +0 -8768
  37. pvlib/data/PVsyst_demo.csv +0 -10757
  38. pvlib/data/PVsyst_demo_model.csv +0 -3588
  39. pvlib/data/SRML-day-EUPO1801.txt +0 -1441
  40. pvlib/data/abq19056.dat +0 -6
  41. pvlib/data/bishop88_numerical_precision.csv +0 -101
  42. pvlib/data/bsrn-lr0100-pay0616.dat +0 -86901
  43. pvlib/data/bsrn-pay0616.dat.gz +0 -0
  44. pvlib/data/cams_mcclear_1min_verbose.csv +0 -60
  45. pvlib/data/cams_mcclear_monthly.csv +0 -42
  46. pvlib/data/cams_radiation_1min_verbose.csv +0 -72
  47. pvlib/data/cams_radiation_monthly.csv +0 -47
  48. pvlib/data/detect_clearsky_data.csv +0 -35
  49. pvlib/data/detect_clearsky_threshold_data.csv +0 -126
  50. pvlib/data/greensboro_kimber_soil_manwash.dat +0 -8761
  51. pvlib/data/greensboro_kimber_soil_nowash.dat +0 -8761
  52. pvlib/data/inverter_fit_snl_meas.csv +0 -127
  53. pvlib/data/inverter_fit_snl_sim.csv +0 -19
  54. pvlib/data/ivtools_numdiff.csv +0 -52
  55. pvlib/data/midc_20181014.txt +0 -1441
  56. pvlib/data/midc_raw_20181018.txt +0 -1441
  57. pvlib/data/midc_raw_short_header_20191115.txt +0 -1441
  58. pvlib/data/msn19056.dat +0 -6
  59. pvlib/data/precise_iv_curves1.json +0 -10251
  60. pvlib/data/precise_iv_curves2.json +0 -10251
  61. pvlib/data/precise_iv_curves_parameter_sets1.csv +0 -33
  62. pvlib/data/precise_iv_curves_parameter_sets2.csv +0 -33
  63. pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA2_10kWp_CIS_5_2a_2013_2014.json +0 -1
  64. pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA_30deg_0deg_2016_2016.csv +0 -35
  65. pvlib/data/pvgis_tmy_meta.json +0 -32
  66. pvlib/data/pvgis_tmy_test.csv +0 -8761
  67. pvlib/data/pvwatts_8760_rackmount.csv +0 -8779
  68. pvlib/data/pvwatts_8760_roofmount.csv +0 -8779
  69. pvlib/data/singleaxis_tracker_wslope.csv +0 -8761
  70. pvlib/data/spectrl2_example_spectra.csv +0 -123
  71. pvlib/data/surfrad-slv16001.dat +0 -1442
  72. pvlib/data/test_psm3_2017.csv +0 -17521
  73. pvlib/data/test_psm3_2019_5min.csv +0 -289
  74. pvlib/data/test_psm3_tmy-2017.csv +0 -8761
  75. pvlib/data/test_read_psm3.csv +0 -17523
  76. pvlib/data/test_read_pvgis_horizon.csv +0 -49
  77. pvlib/data/tmy_45.000_8.000_2005_2023.csv +0 -8789
  78. pvlib/data/tmy_45.000_8.000_2005_2023.epw +0 -8768
  79. pvlib/data/tmy_45.000_8.000_2005_2023.json +0 -1
  80. pvlib/data/tmy_45.000_8.000_2005_2023.txt +0 -8761
  81. pvlib/data/tmy_45.000_8.000_userhorizon.json +0 -1
  82. pvlib/ivtools/sdm.py +0 -1379
  83. pvlib/spa_c_files/README.md +0 -81
  84. pvlib/spa_c_files/cspa_py.pxd +0 -43
  85. pvlib/spa_c_files/spa_py.pyx +0 -30
  86. pvlib/tests/__init__.py +0 -0
  87. pvlib/tests/bifacial/__init__.py +0 -0
  88. pvlib/tests/bifacial/test_infinite_sheds.py +0 -317
  89. pvlib/tests/bifacial/test_losses_models.py +0 -54
  90. pvlib/tests/bifacial/test_pvfactors.py +0 -82
  91. pvlib/tests/bifacial/test_utils.py +0 -192
  92. pvlib/tests/conftest.py +0 -476
  93. pvlib/tests/iotools/__init__.py +0 -0
  94. pvlib/tests/iotools/test_acis.py +0 -213
  95. pvlib/tests/iotools/test_bsrn.py +0 -131
  96. pvlib/tests/iotools/test_crn.py +0 -95
  97. pvlib/tests/iotools/test_epw.py +0 -23
  98. pvlib/tests/iotools/test_midc.py +0 -89
  99. pvlib/tests/iotools/test_panond.py +0 -32
  100. pvlib/tests/iotools/test_psm3.py +0 -198
  101. pvlib/tests/iotools/test_pvgis.py +0 -644
  102. pvlib/tests/iotools/test_sodapro.py +0 -298
  103. pvlib/tests/iotools/test_solaranywhere.py +0 -287
  104. pvlib/tests/iotools/test_solargis.py +0 -68
  105. pvlib/tests/iotools/test_solcast.py +0 -324
  106. pvlib/tests/iotools/test_solrad.py +0 -152
  107. pvlib/tests/iotools/test_srml.py +0 -124
  108. pvlib/tests/iotools/test_surfrad.py +0 -75
  109. pvlib/tests/iotools/test_tmy.py +0 -133
  110. pvlib/tests/ivtools/__init__.py +0 -0
  111. pvlib/tests/ivtools/test_sde.py +0 -230
  112. pvlib/tests/ivtools/test_sdm.py +0 -429
  113. pvlib/tests/ivtools/test_utils.py +0 -173
  114. pvlib/tests/spectrum/__init__.py +0 -0
  115. pvlib/tests/spectrum/conftest.py +0 -40
  116. pvlib/tests/spectrum/test_irradiance.py +0 -138
  117. pvlib/tests/spectrum/test_mismatch.py +0 -304
  118. pvlib/tests/spectrum/test_response.py +0 -124
  119. pvlib/tests/spectrum/test_spectrl2.py +0 -72
  120. pvlib/tests/test__deprecation.py +0 -97
  121. pvlib/tests/test_albedo.py +0 -84
  122. pvlib/tests/test_atmosphere.py +0 -351
  123. pvlib/tests/test_clearsky.py +0 -884
  124. pvlib/tests/test_conftest.py +0 -37
  125. pvlib/tests/test_iam.py +0 -555
  126. pvlib/tests/test_inverter.py +0 -213
  127. pvlib/tests/test_irradiance.py +0 -1487
  128. pvlib/tests/test_location.py +0 -356
  129. pvlib/tests/test_modelchain.py +0 -2020
  130. pvlib/tests/test_numerical_precision.py +0 -124
  131. pvlib/tests/test_pvarray.py +0 -71
  132. pvlib/tests/test_pvsystem.py +0 -2511
  133. pvlib/tests/test_scaling.py +0 -207
  134. pvlib/tests/test_shading.py +0 -391
  135. pvlib/tests/test_singlediode.py +0 -608
  136. pvlib/tests/test_snow.py +0 -212
  137. pvlib/tests/test_soiling.py +0 -230
  138. pvlib/tests/test_solarposition.py +0 -966
  139. pvlib/tests/test_spa.py +0 -454
  140. pvlib/tests/test_temperature.py +0 -470
  141. pvlib/tests/test_tools.py +0 -146
  142. pvlib/tests/test_tracking.py +0 -474
  143. pvlib/tests/test_transformer.py +0 -60
  144. pvlib-0.11.2.dist-info/RECORD +0 -191
  145. {pvlib-0.11.2.dist-info → pvlib-0.12.1a1.dist-info/licenses}/AUTHORS.md +0 -0
  146. {pvlib-0.11.2.dist-info → pvlib-0.12.1a1.dist-info/licenses}/LICENSE +0 -0
  147. {pvlib-0.11.2.dist-info → pvlib-0.12.1a1.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