pvlib 0.11.2__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.
- pvlib/__init__.py +1 -0
- pvlib/atmosphere.py +0 -9
- pvlib/bifacial/infinite_sheds.py +4 -3
- pvlib/bifacial/utils.py +2 -1
- pvlib/iotools/psm3.py +1 -1
- pvlib/iotools/pvgis.py +10 -2
- pvlib/iotools/tmy.py +3 -69
- pvlib/irradiance.py +14 -0
- pvlib/location.py +73 -33
- pvlib/modelchain.py +18 -35
- pvlib/pvsystem.py +7 -10
- pvlib/snow.py +64 -28
- pvlib/spectrum/__init__.py +0 -1
- pvlib/spectrum/irradiance.py +0 -63
- pvlib/spectrum/mismatch.py +3 -3
- pvlib/tools.py +6 -5
- {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info}/METADATA +5 -3
- pvlib-0.12.0.dist-info/RECORD +75 -0
- {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info}/WHEEL +1 -1
- pvlib/data/BIRD_08_16_2012.csv +0 -8761
- pvlib/data/BIRD_08_16_2012_patm.csv +0 -8761
- pvlib/data/Burlington, United States SolarAnywhere Time Series 2021 Lat_44_465 Lon_-73_205 TMY3 format.csv +0 -8762
- pvlib/data/Burlington, United States SolarAnywhere Time Series 20210101 to 20210103 Lat_44_4675 Lon_-73_2075 SA format.csv +0 -578
- pvlib/data/Burlington, United States SolarAnywhere Typical GHI Year Lat_44_465 Lon_-73_205 SA format.csv +0 -74
- pvlib/data/CPS SCH275KTL-DO-US-800-250kW_275kVA_1.OND +0 -146
- pvlib/data/CRNS0101-05-2019-AZ_Tucson_11_W.txt +0 -4
- pvlib/data/CRN_with_problems.txt +0 -3
- pvlib/data/ET-M772BH550GL.PAN +0 -75
- pvlib/data/NLD_Amsterdam062400_IWEC.epw +0 -8768
- pvlib/data/PVsyst_demo.csv +0 -10757
- pvlib/data/PVsyst_demo_model.csv +0 -3588
- pvlib/data/SRML-day-EUPO1801.txt +0 -1441
- pvlib/data/abq19056.dat +0 -6
- pvlib/data/bishop88_numerical_precision.csv +0 -101
- pvlib/data/bsrn-lr0100-pay0616.dat +0 -86901
- pvlib/data/bsrn-pay0616.dat.gz +0 -0
- pvlib/data/cams_mcclear_1min_verbose.csv +0 -60
- pvlib/data/cams_mcclear_monthly.csv +0 -42
- pvlib/data/cams_radiation_1min_verbose.csv +0 -72
- pvlib/data/cams_radiation_monthly.csv +0 -47
- pvlib/data/detect_clearsky_data.csv +0 -35
- pvlib/data/detect_clearsky_threshold_data.csv +0 -126
- pvlib/data/greensboro_kimber_soil_manwash.dat +0 -8761
- pvlib/data/greensboro_kimber_soil_nowash.dat +0 -8761
- pvlib/data/inverter_fit_snl_meas.csv +0 -127
- pvlib/data/inverter_fit_snl_sim.csv +0 -19
- pvlib/data/ivtools_numdiff.csv +0 -52
- pvlib/data/midc_20181014.txt +0 -1441
- pvlib/data/midc_raw_20181018.txt +0 -1441
- pvlib/data/midc_raw_short_header_20191115.txt +0 -1441
- pvlib/data/msn19056.dat +0 -6
- pvlib/data/precise_iv_curves1.json +0 -10251
- pvlib/data/precise_iv_curves2.json +0 -10251
- pvlib/data/precise_iv_curves_parameter_sets1.csv +0 -33
- pvlib/data/precise_iv_curves_parameter_sets2.csv +0 -33
- pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA2_10kWp_CIS_5_2a_2013_2014.json +0 -1
- pvlib/data/pvgis_hourly_Timeseries_45.000_8.000_SA_30deg_0deg_2016_2016.csv +0 -35
- pvlib/data/pvgis_tmy_meta.json +0 -32
- pvlib/data/pvgis_tmy_test.csv +0 -8761
- pvlib/data/pvwatts_8760_rackmount.csv +0 -8779
- pvlib/data/pvwatts_8760_roofmount.csv +0 -8779
- pvlib/data/singleaxis_tracker_wslope.csv +0 -8761
- pvlib/data/spectrl2_example_spectra.csv +0 -123
- pvlib/data/surfrad-slv16001.dat +0 -1442
- pvlib/data/test_psm3_2017.csv +0 -17521
- pvlib/data/test_psm3_2019_5min.csv +0 -289
- pvlib/data/test_psm3_tmy-2017.csv +0 -8761
- pvlib/data/test_read_psm3.csv +0 -17523
- pvlib/data/test_read_pvgis_horizon.csv +0 -49
- pvlib/data/tmy_45.000_8.000_2005_2023.csv +0 -8789
- pvlib/data/tmy_45.000_8.000_2005_2023.epw +0 -8768
- pvlib/data/tmy_45.000_8.000_2005_2023.json +0 -1
- pvlib/data/tmy_45.000_8.000_2005_2023.txt +0 -8761
- pvlib/data/tmy_45.000_8.000_userhorizon.json +0 -1
- pvlib/spa_c_files/README.md +0 -81
- pvlib/spa_c_files/cspa_py.pxd +0 -43
- pvlib/spa_c_files/spa_py.pyx +0 -30
- pvlib/tests/__init__.py +0 -0
- pvlib/tests/bifacial/__init__.py +0 -0
- pvlib/tests/bifacial/test_infinite_sheds.py +0 -317
- pvlib/tests/bifacial/test_losses_models.py +0 -54
- pvlib/tests/bifacial/test_pvfactors.py +0 -82
- pvlib/tests/bifacial/test_utils.py +0 -192
- pvlib/tests/conftest.py +0 -476
- pvlib/tests/iotools/__init__.py +0 -0
- pvlib/tests/iotools/test_acis.py +0 -213
- pvlib/tests/iotools/test_bsrn.py +0 -131
- pvlib/tests/iotools/test_crn.py +0 -95
- pvlib/tests/iotools/test_epw.py +0 -23
- pvlib/tests/iotools/test_midc.py +0 -89
- pvlib/tests/iotools/test_panond.py +0 -32
- pvlib/tests/iotools/test_psm3.py +0 -198
- pvlib/tests/iotools/test_pvgis.py +0 -644
- pvlib/tests/iotools/test_sodapro.py +0 -298
- pvlib/tests/iotools/test_solaranywhere.py +0 -287
- pvlib/tests/iotools/test_solargis.py +0 -68
- pvlib/tests/iotools/test_solcast.py +0 -324
- pvlib/tests/iotools/test_solrad.py +0 -152
- pvlib/tests/iotools/test_srml.py +0 -124
- pvlib/tests/iotools/test_surfrad.py +0 -75
- pvlib/tests/iotools/test_tmy.py +0 -133
- pvlib/tests/ivtools/__init__.py +0 -0
- pvlib/tests/ivtools/test_sde.py +0 -230
- pvlib/tests/ivtools/test_sdm.py +0 -429
- pvlib/tests/ivtools/test_utils.py +0 -173
- pvlib/tests/spectrum/__init__.py +0 -0
- pvlib/tests/spectrum/conftest.py +0 -40
- pvlib/tests/spectrum/test_irradiance.py +0 -138
- pvlib/tests/spectrum/test_mismatch.py +0 -304
- pvlib/tests/spectrum/test_response.py +0 -124
- pvlib/tests/spectrum/test_spectrl2.py +0 -72
- pvlib/tests/test__deprecation.py +0 -97
- pvlib/tests/test_albedo.py +0 -84
- pvlib/tests/test_atmosphere.py +0 -351
- pvlib/tests/test_clearsky.py +0 -884
- pvlib/tests/test_conftest.py +0 -37
- pvlib/tests/test_iam.py +0 -555
- pvlib/tests/test_inverter.py +0 -213
- pvlib/tests/test_irradiance.py +0 -1487
- pvlib/tests/test_location.py +0 -356
- pvlib/tests/test_modelchain.py +0 -2020
- pvlib/tests/test_numerical_precision.py +0 -124
- pvlib/tests/test_pvarray.py +0 -71
- pvlib/tests/test_pvsystem.py +0 -2511
- pvlib/tests/test_scaling.py +0 -207
- pvlib/tests/test_shading.py +0 -391
- pvlib/tests/test_singlediode.py +0 -608
- pvlib/tests/test_snow.py +0 -212
- pvlib/tests/test_soiling.py +0 -230
- pvlib/tests/test_solarposition.py +0 -966
- pvlib/tests/test_spa.py +0 -454
- pvlib/tests/test_temperature.py +0 -470
- pvlib/tests/test_tools.py +0 -146
- pvlib/tests/test_tracking.py +0 -474
- pvlib/tests/test_transformer.py +0 -60
- pvlib-0.11.2.dist-info/RECORD +0 -191
- {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info/licenses}/AUTHORS.md +0 -0
- {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info/licenses}/LICENSE +0 -0
- {pvlib-0.11.2.dist-info → pvlib-0.12.0.dist-info}/top_level.txt +0 -0
pvlib/tests/test__deprecation.py
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Test the _deprecation module.
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import pytest
|
|
6
|
-
|
|
7
|
-
from pvlib import _deprecation
|
|
8
|
-
from .conftest import fail_on_pvlib_version
|
|
9
|
-
|
|
10
|
-
import warnings
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@pytest.mark.xfail(strict=True,
|
|
14
|
-
reason='fail_on_pvlib_version should cause test to fail')
|
|
15
|
-
@fail_on_pvlib_version('0.0')
|
|
16
|
-
def test_fail_on_pvlib_version():
|
|
17
|
-
pass # pragma: no cover
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@fail_on_pvlib_version('100000.0')
|
|
21
|
-
def test_fail_on_pvlib_version_pass():
|
|
22
|
-
pass
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
@pytest.mark.xfail(strict=True, reason='ensure that the test is called')
|
|
26
|
-
@fail_on_pvlib_version('100000.0')
|
|
27
|
-
def test_fail_on_pvlib_version_fail_in_test():
|
|
28
|
-
raise Exception
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# set up to test using fixtures with function decorated with
|
|
32
|
-
# conftest.fail_on_pvlib_version
|
|
33
|
-
@pytest.fixture
|
|
34
|
-
def some_data():
|
|
35
|
-
return "some data"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def alt_func(*args):
|
|
39
|
-
return args
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
@pytest.fixture
|
|
43
|
-
def deprec_func():
|
|
44
|
-
return _deprecation.deprecated(
|
|
45
|
-
"350.8", alternative="alt_func", name="deprec_func", removal="350.9"
|
|
46
|
-
)(alt_func)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@fail_on_pvlib_version('350.9')
|
|
50
|
-
def test_use_fixture_with_decorator(some_data, deprec_func):
|
|
51
|
-
# test that the correct data is returned by the some_data fixture
|
|
52
|
-
assert some_data == "some data"
|
|
53
|
-
with pytest.warns(_deprecation.pvlibDeprecationWarning):
|
|
54
|
-
# test for custom deprecation warning provided by pvlib
|
|
55
|
-
deprec_func(some_data)
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
@pytest.fixture
|
|
59
|
-
def renamed_kwarg_func():
|
|
60
|
-
"""Returns a function decorated by renamed_kwarg_warning.
|
|
61
|
-
This function is called 'func' and has a docstring equal to 'docstring'.
|
|
62
|
-
"""
|
|
63
|
-
|
|
64
|
-
@_deprecation.renamed_kwarg_warning(
|
|
65
|
-
"0.1.0", "old_kwarg", "new_kwarg", "0.2.0"
|
|
66
|
-
)
|
|
67
|
-
def func(new_kwarg):
|
|
68
|
-
"""docstring"""
|
|
69
|
-
return new_kwarg
|
|
70
|
-
|
|
71
|
-
return func
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def test_renamed_kwarg_warning(renamed_kwarg_func):
|
|
75
|
-
# assert decorated function name and docstring are unchanged
|
|
76
|
-
assert renamed_kwarg_func.__name__ == "func"
|
|
77
|
-
assert renamed_kwarg_func.__doc__ == "docstring"
|
|
78
|
-
|
|
79
|
-
# assert no warning is raised when using the new kwarg
|
|
80
|
-
with warnings.catch_warnings():
|
|
81
|
-
warnings.simplefilter("error")
|
|
82
|
-
assert renamed_kwarg_func(new_kwarg=1) == 1 # as keyword argument
|
|
83
|
-
assert renamed_kwarg_func(1) == 1 # as positional argument
|
|
84
|
-
|
|
85
|
-
# assert a warning is raised when using the old kwarg
|
|
86
|
-
with pytest.warns(Warning, match="Parameter 'old_kwarg' has been renamed"):
|
|
87
|
-
assert renamed_kwarg_func(old_kwarg=1) == 1
|
|
88
|
-
|
|
89
|
-
# assert an error is raised when using both the old and new kwarg
|
|
90
|
-
with pytest.raises(ValueError, match="they refer to the same parameter."):
|
|
91
|
-
renamed_kwarg_func(old_kwarg=1, new_kwarg=2)
|
|
92
|
-
|
|
93
|
-
# assert when not providing any of them
|
|
94
|
-
with pytest.raises(
|
|
95
|
-
TypeError, match="missing 1 required positional argument"
|
|
96
|
-
):
|
|
97
|
-
renamed_kwarg_func()
|
pvlib/tests/test_albedo.py
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
import pandas as pd
|
|
3
|
-
import pytest
|
|
4
|
-
from pvlib import albedo
|
|
5
|
-
|
|
6
|
-
from .conftest import assert_series_equal
|
|
7
|
-
from numpy.testing import assert_allclose
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
def test_inland_water_dvoracek_default():
|
|
11
|
-
result = albedo.inland_water_dvoracek(solar_elevation=90,
|
|
12
|
-
color_coeff=0.13,
|
|
13
|
-
wave_roughness_coeff=0.29)
|
|
14
|
-
assert_allclose(result, 0.072, 0.001)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def test_inland_water_dvoracek_negative_elevation():
|
|
18
|
-
result = albedo.inland_water_dvoracek(solar_elevation=-60,
|
|
19
|
-
color_coeff=0.13,
|
|
20
|
-
wave_roughness_coeff=0.29)
|
|
21
|
-
assert_allclose(result, 0.13, 0.01)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def test_inland_water_dvoracek_string_surface_condition():
|
|
25
|
-
result = albedo.inland_water_dvoracek(solar_elevation=90,
|
|
26
|
-
surface_condition='clear_water_no_waves') # noqa: E501
|
|
27
|
-
assert_allclose(result, 0.072, 0.001)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def test_inland_water_dvoracek_ndarray():
|
|
31
|
-
solar_elevs = np.array([-50, 0, 20, 60, 90])
|
|
32
|
-
color_coeffs = np.array([0.1, 0.1, 0.2, 0.3, 0.4])
|
|
33
|
-
roughness_coeffs = np.array([0.3, 0.3, 0.8, 1.5, 2])
|
|
34
|
-
result = albedo.inland_water_dvoracek(solar_elevation=solar_elevs,
|
|
35
|
-
color_coeff=color_coeffs,
|
|
36
|
-
wave_roughness_coeff=roughness_coeffs) # noqa: E501
|
|
37
|
-
expected = np.array([0.1, 0.1, 0.12875, 0.06278, 0.064])
|
|
38
|
-
assert_allclose(expected, result, atol=1e-5)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def test_inland_water_dvoracek_series():
|
|
42
|
-
times = pd.date_range(start="2015-01-01 00:00", end="2015-01-02 00:00",
|
|
43
|
-
freq="6h")
|
|
44
|
-
solar_elevs = pd.Series([-50, 0, 20, 60, 90], index=times)
|
|
45
|
-
color_coeffs = pd.Series([0.1, 0.1, 0.2, 0.3, 0.4], index=times)
|
|
46
|
-
roughness_coeffs = pd.Series([0.1, 0.3, 0.8, 1.5, 2], index=times)
|
|
47
|
-
result = albedo.inland_water_dvoracek(solar_elevation=solar_elevs,
|
|
48
|
-
color_coeff=color_coeffs,
|
|
49
|
-
wave_roughness_coeff=roughness_coeffs) # noqa: E501
|
|
50
|
-
expected = pd.Series([0.1, 0.1, 0.12875, 0.06278, 0.064], index=times)
|
|
51
|
-
assert_series_equal(expected, result, atol=1e-5)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def test_inland_water_dvoracek_series_mix_with_array():
|
|
55
|
-
times = pd.date_range(start="2015-01-01 00:00", end="2015-01-01 06:00",
|
|
56
|
-
freq="6h")
|
|
57
|
-
solar_elevs = pd.Series([45, 60], index=times)
|
|
58
|
-
color_coeffs = 0.13
|
|
59
|
-
roughness_coeffs = 0.29
|
|
60
|
-
result = albedo.inland_water_dvoracek(solar_elevation=solar_elevs,
|
|
61
|
-
color_coeff=color_coeffs,
|
|
62
|
-
wave_roughness_coeff=roughness_coeffs) # noqa: E501
|
|
63
|
-
expected = pd.Series([0.08555, 0.07787], index=times)
|
|
64
|
-
assert_series_equal(expected, result, atol=1e-5)
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def test_inland_water_dvoracek_invalid():
|
|
68
|
-
with pytest.raises(ValueError, match='Either a `surface_condition` has to '
|
|
69
|
-
'be chosen or a combination of `color_coeff` and'
|
|
70
|
-
' `wave_roughness_coeff`.'): # no surface info given
|
|
71
|
-
albedo.inland_water_dvoracek(solar_elevation=45)
|
|
72
|
-
with pytest.raises(KeyError, match='not_a_surface_type'): # invalid type
|
|
73
|
-
albedo.inland_water_dvoracek(solar_elevation=45,
|
|
74
|
-
surface_condition='not_a_surface_type')
|
|
75
|
-
with pytest.raises(ValueError, match='Either a `surface_condition` has to '
|
|
76
|
-
'be chosen or a combination of `color_coeff` and'
|
|
77
|
-
' `wave_roughness_coeff`.'): # only one coeff given
|
|
78
|
-
albedo.inland_water_dvoracek(solar_elevation=45,
|
|
79
|
-
color_coeff=0.13)
|
|
80
|
-
with pytest.raises(ValueError, match='Either a `surface_condition` has to '
|
|
81
|
-
'be chosen or a combination of `color_coeff` and'
|
|
82
|
-
' `wave_roughness_coeff`.'): # only one coeff given
|
|
83
|
-
albedo.inland_water_dvoracek(solar_elevation=45,
|
|
84
|
-
wave_roughness_coeff=0.29)
|
pvlib/tests/test_atmosphere.py
DELETED
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
import itertools
|
|
2
|
-
|
|
3
|
-
import numpy as np
|
|
4
|
-
from numpy import nan
|
|
5
|
-
from numpy.testing import assert_allclose
|
|
6
|
-
import pandas as pd
|
|
7
|
-
from .conftest import assert_series_equal
|
|
8
|
-
import pytest
|
|
9
|
-
|
|
10
|
-
from pvlib import atmosphere
|
|
11
|
-
|
|
12
|
-
from pvlib._deprecation import pvlibDeprecationWarning
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def test_pres2alt():
|
|
16
|
-
out = atmosphere.pres2alt(np.array([10000, 90000, 101325]))
|
|
17
|
-
expected = np.array([15797.638, 988.637, 0.124])
|
|
18
|
-
assert_allclose(out, expected, atol=0.001)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def test_alt2pres():
|
|
22
|
-
out = atmosphere.alt2pres(np.array([-100, 0, 1000, 8000]))
|
|
23
|
-
expected = np.array([102532.073, 101324.999, 89874.750, 35600.496])
|
|
24
|
-
assert_allclose(out, expected, atol=0.001)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@pytest.fixture
|
|
28
|
-
def zeniths():
|
|
29
|
-
return np.array([100, 89.9, 80, 0])
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@pytest.mark.parametrize("model,expected",
|
|
33
|
-
[['simple', [nan, 572.958, 5.759, 1.000]],
|
|
34
|
-
['kasten1966', [nan, 35.365, 5.580, 0.999]],
|
|
35
|
-
['youngirvine1967', [
|
|
36
|
-
nan, -2.251358367165932e+05, 5.5365, 1.0000]],
|
|
37
|
-
['kastenyoung1989', [nan, 36.467, 5.586, 1.000]],
|
|
38
|
-
['gueymard1993', [nan, 36.431, 5.581, 1.000]],
|
|
39
|
-
['young1994', [nan, 30.733, 5.541, 1.000]],
|
|
40
|
-
['pickering2002', [nan, 37.064, 5.581, 1.000]],
|
|
41
|
-
['gueymard2003', [nan, 36.676, 5.590, 1.000]]])
|
|
42
|
-
def test_airmass(model, expected, zeniths):
|
|
43
|
-
out = atmosphere.get_relative_airmass(zeniths, model)
|
|
44
|
-
expected = np.array(expected)
|
|
45
|
-
assert_allclose(out, expected, equal_nan=True, atol=0.001)
|
|
46
|
-
# test series in/out. index does not matter
|
|
47
|
-
# hits the isinstance() block in get_relative_airmass
|
|
48
|
-
times = pd.date_range(start='20180101', periods=len(zeniths), freq='1s')
|
|
49
|
-
zeniths = pd.Series(zeniths, index=times)
|
|
50
|
-
expected = pd.Series(expected, index=times)
|
|
51
|
-
out = atmosphere.get_relative_airmass(zeniths, model)
|
|
52
|
-
assert_series_equal(out, expected, check_less_precise=True)
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def test_airmass_scalar():
|
|
56
|
-
assert not np.isnan(atmosphere.get_relative_airmass(10))
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def test_airmass_invalid():
|
|
60
|
-
with pytest.raises(ValueError):
|
|
61
|
-
atmosphere.get_relative_airmass(0, 'invalid')
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def test_get_absolute_airmass():
|
|
65
|
-
# input am
|
|
66
|
-
relative_am = np.array([nan, 40, 2, .999])
|
|
67
|
-
# call without pressure kwarg
|
|
68
|
-
out = atmosphere.get_absolute_airmass(relative_am)
|
|
69
|
-
expected = np.array([nan, 40., 2., 0.999])
|
|
70
|
-
assert_allclose(out, expected, equal_nan=True, atol=0.001)
|
|
71
|
-
# call with pressure kwarg
|
|
72
|
-
out = atmosphere.get_absolute_airmass(relative_am, pressure=90000)
|
|
73
|
-
expected = np.array([nan, 35.529, 1.776, 0.887])
|
|
74
|
-
assert_allclose(out, expected, equal_nan=True, atol=0.001)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def test_gueymard94_pw():
|
|
78
|
-
temp_air = np.array([0, 20, 40])
|
|
79
|
-
relative_humidity = np.array([0, 30, 100])
|
|
80
|
-
temps_humids = np.array(
|
|
81
|
-
list(itertools.product(temp_air, relative_humidity)))
|
|
82
|
-
pws = atmosphere.gueymard94_pw(temps_humids[:, 0], temps_humids[:, 1])
|
|
83
|
-
|
|
84
|
-
expected = np.array(
|
|
85
|
-
[ 0.1 , 0.33702061, 1.12340202, 0.1 ,
|
|
86
|
-
1.12040963, 3.73469877, 0.1 , 3.44859767, 11.49532557])
|
|
87
|
-
|
|
88
|
-
assert_allclose(pws, expected, atol=0.01)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def test_tdew_to_rh_to_tdew():
|
|
92
|
-
|
|
93
|
-
# dewpoint temp calculated with wmo and aekr coefficients
|
|
94
|
-
dewpoint_original = pd.Series([
|
|
95
|
-
15.0, 20.0, 25.0, 12.0, 8.0
|
|
96
|
-
])
|
|
97
|
-
|
|
98
|
-
temperature_ambient = pd.Series([20.0, 25.0, 30.0, 15.0, 10.0])
|
|
99
|
-
|
|
100
|
-
# Calculate relative humidity using pandas series as input
|
|
101
|
-
relative_humidity = atmosphere.rh_from_tdew(
|
|
102
|
-
temp_air=temperature_ambient,
|
|
103
|
-
temp_dew=dewpoint_original
|
|
104
|
-
)
|
|
105
|
-
|
|
106
|
-
dewpoint_calculated = atmosphere.tdew_from_rh(
|
|
107
|
-
temp_air=temperature_ambient,
|
|
108
|
-
relative_humidity=relative_humidity
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
# test
|
|
112
|
-
pd.testing.assert_series_equal(
|
|
113
|
-
dewpoint_original,
|
|
114
|
-
dewpoint_calculated,
|
|
115
|
-
check_names=False
|
|
116
|
-
)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
def test_rh_from_tdew():
|
|
120
|
-
|
|
121
|
-
dewpoint = pd.Series([
|
|
122
|
-
15.0, 20.0, 25.0, 12.0, 8.0
|
|
123
|
-
])
|
|
124
|
-
|
|
125
|
-
# relative humidity calculated with wmo and aekr coefficients
|
|
126
|
-
relative_humidity_wmo = pd.Series([
|
|
127
|
-
72.95185312581116, 73.81500029087906, 74.6401272083123,
|
|
128
|
-
82.27063889868842, 87.39018119185337
|
|
129
|
-
])
|
|
130
|
-
relative_humidity_aekr = pd.Series([
|
|
131
|
-
72.93876680928582, 73.8025121880607, 74.62820502423823,
|
|
132
|
-
82.26135295757305, 87.38323744820416
|
|
133
|
-
])
|
|
134
|
-
|
|
135
|
-
temperature_ambient = pd.Series([20.0, 25.0, 30.0, 15.0, 10.0])
|
|
136
|
-
|
|
137
|
-
# Calculate relative humidity using pandas series as input
|
|
138
|
-
rh_series = atmosphere.rh_from_tdew(
|
|
139
|
-
temp_air=temperature_ambient,
|
|
140
|
-
temp_dew=dewpoint
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
pd.testing.assert_series_equal(
|
|
144
|
-
rh_series,
|
|
145
|
-
relative_humidity_wmo,
|
|
146
|
-
check_names=False
|
|
147
|
-
)
|
|
148
|
-
|
|
149
|
-
# Calulate relative humidity using pandas series as input
|
|
150
|
-
# with AEKR coefficients
|
|
151
|
-
rh_series_aekr = atmosphere.rh_from_tdew(
|
|
152
|
-
temp_air=temperature_ambient,
|
|
153
|
-
temp_dew=dewpoint,
|
|
154
|
-
coeff=(6.1094, 17.625, 243.04)
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
pd.testing.assert_series_equal(
|
|
158
|
-
rh_series_aekr,
|
|
159
|
-
relative_humidity_aekr,
|
|
160
|
-
check_names=False
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
# Calculate relative humidity using array as input
|
|
164
|
-
rh_array = atmosphere.rh_from_tdew(
|
|
165
|
-
temp_air=temperature_ambient.to_numpy(),
|
|
166
|
-
temp_dew=dewpoint.to_numpy()
|
|
167
|
-
)
|
|
168
|
-
|
|
169
|
-
np.testing.assert_allclose(rh_array, relative_humidity_wmo.to_numpy())
|
|
170
|
-
|
|
171
|
-
# Calculate relative humidity using float as input
|
|
172
|
-
rh_float = atmosphere.rh_from_tdew(
|
|
173
|
-
temp_air=temperature_ambient.iloc[0],
|
|
174
|
-
temp_dew=dewpoint.iloc[0]
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
assert np.isclose(rh_float, relative_humidity_wmo.iloc[0])
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
# Unit tests
|
|
181
|
-
def test_tdew_from_rh():
|
|
182
|
-
|
|
183
|
-
dewpoint = pd.Series([
|
|
184
|
-
15.0, 20.0, 25.0, 12.0, 8.0
|
|
185
|
-
])
|
|
186
|
-
|
|
187
|
-
# relative humidity calculated with wmo and aekr coefficients
|
|
188
|
-
relative_humidity_wmo = pd.Series([
|
|
189
|
-
72.95185312581116, 73.81500029087906, 74.6401272083123,
|
|
190
|
-
82.27063889868842, 87.39018119185337
|
|
191
|
-
])
|
|
192
|
-
relative_humidity_aekr = pd.Series([
|
|
193
|
-
72.93876680928582, 73.8025121880607, 74.62820502423823,
|
|
194
|
-
82.26135295757305, 87.38323744820416
|
|
195
|
-
])
|
|
196
|
-
|
|
197
|
-
temperature_ambient = pd.Series([20.0, 25.0, 30.0, 15.0, 10.0])
|
|
198
|
-
|
|
199
|
-
# test as series
|
|
200
|
-
dewpoint_series = atmosphere.tdew_from_rh(
|
|
201
|
-
temp_air=temperature_ambient,
|
|
202
|
-
relative_humidity=relative_humidity_wmo
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
pd.testing.assert_series_equal(
|
|
206
|
-
dewpoint_series, dewpoint, check_names=False
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
# test as series with AEKR coefficients
|
|
210
|
-
dewpoint_series_aekr = atmosphere.tdew_from_rh(
|
|
211
|
-
temp_air=temperature_ambient,
|
|
212
|
-
relative_humidity=relative_humidity_aekr,
|
|
213
|
-
coeff=(6.1094, 17.625, 243.04)
|
|
214
|
-
)
|
|
215
|
-
|
|
216
|
-
pd.testing.assert_series_equal(
|
|
217
|
-
dewpoint_series_aekr, dewpoint,
|
|
218
|
-
check_names=False
|
|
219
|
-
)
|
|
220
|
-
|
|
221
|
-
# test as numpy array
|
|
222
|
-
dewpoint_array = atmosphere.tdew_from_rh(
|
|
223
|
-
temp_air=temperature_ambient.to_numpy(),
|
|
224
|
-
relative_humidity=relative_humidity_wmo.to_numpy()
|
|
225
|
-
)
|
|
226
|
-
|
|
227
|
-
np.testing.assert_allclose(dewpoint_array, dewpoint.to_numpy())
|
|
228
|
-
|
|
229
|
-
# test as float
|
|
230
|
-
dewpoint_float = atmosphere.tdew_from_rh(
|
|
231
|
-
temp_air=temperature_ambient.iloc[0],
|
|
232
|
-
relative_humidity=relative_humidity_wmo.iloc[0]
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
assert np.isclose(dewpoint_float, dewpoint.iloc[0])
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
def test_first_solar_spectral_correction_deprecated():
|
|
239
|
-
with pytest.warns(pvlibDeprecationWarning,
|
|
240
|
-
match='Use pvlib.spectrum.spectral_factor_firstsolar'):
|
|
241
|
-
atmosphere.first_solar_spectral_correction(1, 1, 'cdte')
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
def test_kasten96_lt():
|
|
245
|
-
"""Test Linke turbidity factor calculated from AOD, Pwat and AM"""
|
|
246
|
-
amp = np.array([1, 3, 5])
|
|
247
|
-
pwat = np.array([0, 2.5, 5])
|
|
248
|
-
aod_bb = np.array([0, 0.1, 1])
|
|
249
|
-
lt_expected = np.array(
|
|
250
|
-
[[[1.3802, 2.4102, 11.6802],
|
|
251
|
-
[1.16303976, 2.37303976, 13.26303976],
|
|
252
|
-
[1.12101907, 2.51101907, 15.02101907]],
|
|
253
|
-
|
|
254
|
-
[[2.95546945, 3.98546945, 13.25546945],
|
|
255
|
-
[2.17435443, 3.38435443, 14.27435443],
|
|
256
|
-
[1.99821967, 3.38821967, 15.89821967]],
|
|
257
|
-
|
|
258
|
-
[[3.37410769, 4.40410769, 13.67410769],
|
|
259
|
-
[2.44311797, 3.65311797, 14.54311797],
|
|
260
|
-
[2.23134152, 3.62134152, 16.13134152]]]
|
|
261
|
-
)
|
|
262
|
-
lt = atmosphere.kasten96_lt(*np.meshgrid(amp, pwat, aod_bb))
|
|
263
|
-
assert np.allclose(lt, lt_expected, 1e-3)
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
def test_angstrom_aod():
|
|
267
|
-
"""Test Angstrom turbidity model functions."""
|
|
268
|
-
aod550 = 0.15
|
|
269
|
-
aod1240 = 0.05
|
|
270
|
-
alpha = atmosphere.angstrom_alpha(aod550, 550, aod1240, 1240)
|
|
271
|
-
assert np.isclose(alpha, 1.3513924317859232)
|
|
272
|
-
aod700 = atmosphere.angstrom_aod_at_lambda(aod550, 550, alpha)
|
|
273
|
-
assert np.isclose(aod700, 0.10828110997681031)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def test_bird_hulstrom80_aod_bb():
|
|
277
|
-
"""Test Bird_Hulstrom broadband AOD."""
|
|
278
|
-
aod380, aod500 = 0.22072480948195175, 0.1614279181106312
|
|
279
|
-
bird_hulstrom = atmosphere.bird_hulstrom80_aod_bb(aod380, aod500)
|
|
280
|
-
assert np.isclose(0.11738229553812768, bird_hulstrom)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
@pytest.fixture
|
|
284
|
-
def windspeeds_data_powerlaw():
|
|
285
|
-
data = pd.DataFrame(
|
|
286
|
-
index=pd.date_range(start="2015-01-01 00:00", end="2015-01-01 05:00",
|
|
287
|
-
freq="1h"),
|
|
288
|
-
columns=["wind_ref", "height_ref", "height_desired", "wind_calc"],
|
|
289
|
-
data=[
|
|
290
|
-
(10, -2, 5, np.nan),
|
|
291
|
-
(-10, 2, 5, np.nan),
|
|
292
|
-
(5, 4, 5, 5.067393209486324),
|
|
293
|
-
(7, 6, 10, 7.2178684911195905),
|
|
294
|
-
(10, 8, 20, 10.565167835216586),
|
|
295
|
-
(12, 10, 30, 12.817653329393977)
|
|
296
|
-
]
|
|
297
|
-
)
|
|
298
|
-
return data
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
def test_windspeed_powerlaw_ndarray(windspeeds_data_powerlaw):
|
|
302
|
-
# test wind speed estimation by passing in surface_type
|
|
303
|
-
result_surface = atmosphere.windspeed_powerlaw(
|
|
304
|
-
windspeeds_data_powerlaw["wind_ref"].to_numpy(),
|
|
305
|
-
windspeeds_data_powerlaw["height_ref"],
|
|
306
|
-
windspeeds_data_powerlaw["height_desired"],
|
|
307
|
-
surface_type='unstable_air_above_open_water_surface')
|
|
308
|
-
assert_allclose(windspeeds_data_powerlaw["wind_calc"].to_numpy(),
|
|
309
|
-
result_surface)
|
|
310
|
-
# test wind speed estimation by passing in the exponent corresponding
|
|
311
|
-
# to the surface_type above
|
|
312
|
-
result_exponent = atmosphere.windspeed_powerlaw(
|
|
313
|
-
windspeeds_data_powerlaw["wind_ref"].to_numpy(),
|
|
314
|
-
windspeeds_data_powerlaw["height_ref"],
|
|
315
|
-
windspeeds_data_powerlaw["height_desired"],
|
|
316
|
-
exponent=0.06)
|
|
317
|
-
assert_allclose(windspeeds_data_powerlaw["wind_calc"].to_numpy(),
|
|
318
|
-
result_exponent)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
def test_windspeed_powerlaw_series(windspeeds_data_powerlaw):
|
|
322
|
-
result = atmosphere.windspeed_powerlaw(
|
|
323
|
-
windspeeds_data_powerlaw["wind_ref"],
|
|
324
|
-
windspeeds_data_powerlaw["height_ref"],
|
|
325
|
-
windspeeds_data_powerlaw["height_desired"],
|
|
326
|
-
surface_type='unstable_air_above_open_water_surface')
|
|
327
|
-
assert_series_equal(windspeeds_data_powerlaw["wind_calc"],
|
|
328
|
-
result, check_names=False)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
def test_windspeed_powerlaw_invalid():
|
|
332
|
-
with pytest.raises(ValueError, match="Either a 'surface_type' or an "
|
|
333
|
-
"'exponent' parameter must be given"):
|
|
334
|
-
# no exponent or surface_type given
|
|
335
|
-
atmosphere.windspeed_powerlaw(wind_speed_reference=10,
|
|
336
|
-
height_reference=5,
|
|
337
|
-
height_desired=10)
|
|
338
|
-
with pytest.raises(ValueError, match="Either a 'surface_type' or an "
|
|
339
|
-
"'exponent' parameter must be given"):
|
|
340
|
-
# no exponent or surface_type given
|
|
341
|
-
atmosphere.windspeed_powerlaw(wind_speed_reference=10,
|
|
342
|
-
height_reference=5,
|
|
343
|
-
height_desired=10,
|
|
344
|
-
exponent=1.2,
|
|
345
|
-
surface_type="surf")
|
|
346
|
-
with pytest.raises(KeyError, match='not_an_exponent'):
|
|
347
|
-
# invalid surface_type
|
|
348
|
-
atmosphere.windspeed_powerlaw(wind_speed_reference=10,
|
|
349
|
-
height_reference=5,
|
|
350
|
-
height_desired=10,
|
|
351
|
-
surface_type='not_an_exponent')
|