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.
- pvlib/__init__.py +1 -0
- pvlib/_deprecation.py +73 -0
- pvlib/atmosphere.py +77 -7
- pvlib/bifacial/infinite_sheds.py +4 -3
- pvlib/bifacial/utils.py +2 -1
- pvlib/clearsky.py +35 -22
- pvlib/iam.py +4 -4
- pvlib/iotools/midc.py +1 -1
- pvlib/iotools/psm3.py +1 -1
- pvlib/iotools/pvgis.py +10 -12
- pvlib/iotools/tmy.py +3 -69
- pvlib/irradiance.py +112 -55
- pvlib/ivtools/sdm.py +75 -52
- pvlib/location.py +73 -33
- pvlib/modelchain.py +18 -35
- pvlib/pvsystem.py +139 -94
- pvlib/snow.py +64 -28
- pvlib/solarposition.py +46 -30
- pvlib/spa.py +4 -2
- pvlib/spectrum/__init__.py +0 -1
- pvlib/spectrum/irradiance.py +2 -64
- pvlib/spectrum/mismatch.py +3 -3
- pvlib/spectrum/spectrl2.py +2 -1
- pvlib/temperature.py +49 -3
- pvlib/tools.py +6 -5
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/METADATA +14 -11
- pvlib-0.12.0.dist-info/RECORD +75 -0
- {pvlib-0.11.1.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/aod550_tcwv_20121101_test.nc +0 -0
- 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.dat +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_2020.csv +0 -8789
- pvlib/data/tmy_45.000_8.000_2005_2020.epw +0 -8768
- pvlib/data/tmy_45.000_8.000_2005_2020.json +0 -1
- pvlib/data/tmy_45.000_8.000_2005_2020.txt +0 -8761
- pvlib/data/tmy_45.000_8.000_userhorizon.json +0 -1
- pvlib/data/variables_style_rules.csv +0 -56
- 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 -407
- 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_albedo.py +0 -84
- pvlib/tests/test_atmosphere.py +0 -204
- pvlib/tests/test_clearsky.py +0 -878
- pvlib/tests/test_conftest.py +0 -81
- pvlib/tests/test_iam.py +0 -555
- pvlib/tests/test_inverter.py +0 -213
- pvlib/tests/test_irradiance.py +0 -1441
- 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 -2495
- 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 -933
- pvlib/tests/test_spa.py +0 -425
- 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.1.dist-info/RECORD +0 -192
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/AUTHORS.md +0 -0
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info/licenses}/LICENSE +0 -0
- {pvlib-0.11.1.dist-info → pvlib-0.12.0.dist-info}/top_level.txt +0 -0
pvlib/__init__.py
CHANGED
pvlib/_deprecation.py
CHANGED
|
@@ -316,3 +316,76 @@ def deprecated(since, message='', name='', alternative='', pending=False,
|
|
|
316
316
|
return finalize(wrapper, new_doc)
|
|
317
317
|
|
|
318
318
|
return deprecate
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def renamed_kwarg_warning(since, old_param_name, new_param_name, removal=""):
|
|
322
|
+
"""
|
|
323
|
+
Decorator to mark a possible keyword argument as deprecated and replaced
|
|
324
|
+
with other name.
|
|
325
|
+
|
|
326
|
+
Raises a warning when the deprecated argument is used, and replaces the
|
|
327
|
+
call with the new argument name. Does not modify the function signature.
|
|
328
|
+
|
|
329
|
+
.. warning::
|
|
330
|
+
Ensure ``removal`` date with a ``fail_on_pvlib_version`` decorator in
|
|
331
|
+
the test suite.
|
|
332
|
+
|
|
333
|
+
.. note::
|
|
334
|
+
Not compatible with positional-only arguments.
|
|
335
|
+
|
|
336
|
+
.. note::
|
|
337
|
+
Documentation for the function may updated to reflect the new parameter
|
|
338
|
+
name; it is suggested to add a |.. versionchanged::| directive.
|
|
339
|
+
|
|
340
|
+
Parameters
|
|
341
|
+
----------
|
|
342
|
+
since : str
|
|
343
|
+
The release at which this API became deprecated.
|
|
344
|
+
old_param_name : str
|
|
345
|
+
The name of the deprecated parameter.
|
|
346
|
+
new_param_name : str
|
|
347
|
+
The name of the new parameter.
|
|
348
|
+
removal : str, optional
|
|
349
|
+
The expected removal version, in order to compose the Warning message.
|
|
350
|
+
|
|
351
|
+
Examples
|
|
352
|
+
--------
|
|
353
|
+
>>> @renamed_kwarg_warning("1.4.0", "old_name", "new_name", "1.6.0")
|
|
354
|
+
>>> def some_function(new_name=None):
|
|
355
|
+
>>> pass
|
|
356
|
+
>>> some_function(old_name=1)
|
|
357
|
+
Parameter 'old_name' has been renamed since 1.4.0. and
|
|
358
|
+
will be removed in 1.6.0. Please use 'new_name' instead.
|
|
359
|
+
|
|
360
|
+
>>> @renamed_kwarg_warning("1.4.0", "old_name", "new_name")
|
|
361
|
+
>>> def some_function(new_name=None):
|
|
362
|
+
>>> pass
|
|
363
|
+
>>> some_function(old_name=1)
|
|
364
|
+
Parameter 'old_name' has been renamed since 1.4.0. and
|
|
365
|
+
will be removed soon. Please use 'new_name' instead.
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
def deprecate(func, old=old_param_name, new=new_param_name, since=since):
|
|
369
|
+
def wrapper(*args, **kwargs):
|
|
370
|
+
if old in kwargs:
|
|
371
|
+
if new in kwargs:
|
|
372
|
+
raise ValueError(
|
|
373
|
+
f"{func.__name__} received both '{old}' and '{new}', "
|
|
374
|
+
"which are mutually exclusive since they refer to the "
|
|
375
|
+
f"same parameter. Please remove deprecated '{old}'."
|
|
376
|
+
)
|
|
377
|
+
warnings.warn(
|
|
378
|
+
f"Parameter '{old}' has been renamed since {since}. "
|
|
379
|
+
f"and will be removed "
|
|
380
|
+
+ (f"in {removal}" if removal else "soon")
|
|
381
|
+
+ f". Please use '{new}' instead.",
|
|
382
|
+
_projectWarning,
|
|
383
|
+
stacklevel=2,
|
|
384
|
+
)
|
|
385
|
+
kwargs[new] = kwargs.pop(old)
|
|
386
|
+
return func(*args, **kwargs)
|
|
387
|
+
|
|
388
|
+
wrapper = functools.wraps(func)(wrapper)
|
|
389
|
+
return wrapper
|
|
390
|
+
|
|
391
|
+
return deprecate
|
pvlib/atmosphere.py
CHANGED
|
@@ -6,9 +6,6 @@ speed at different heights.
|
|
|
6
6
|
|
|
7
7
|
import numpy as np
|
|
8
8
|
import pandas as pd
|
|
9
|
-
import pvlib
|
|
10
|
-
|
|
11
|
-
from pvlib._deprecation import deprecated
|
|
12
9
|
|
|
13
10
|
APPARENT_ZENITH_MODELS = ('simple', 'kasten1966', 'kastenyoung1989',
|
|
14
11
|
'gueymard1993', 'pickering2002')
|
|
@@ -337,10 +334,83 @@ def gueymard94_pw(temp_air, relative_humidity):
|
|
|
337
334
|
return pw
|
|
338
335
|
|
|
339
336
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
337
|
+
def rh_from_tdew(temp_air, temp_dew, coeff=(6.112, 17.62, 243.12)):
|
|
338
|
+
"""
|
|
339
|
+
Calculate relative humidity from dewpoint temperature using the Magnus
|
|
340
|
+
equation.
|
|
341
|
+
|
|
342
|
+
Parameters
|
|
343
|
+
----------
|
|
344
|
+
temp_air : numeric
|
|
345
|
+
Air temperature (dry-bulb temperature). [°C]
|
|
346
|
+
temp_dew : numeric
|
|
347
|
+
Dew-point temperature. [°C]
|
|
348
|
+
coeff : tuple, default (6.112, 17.62, 243.12)
|
|
349
|
+
Magnus equation coefficients (A, B, C). The default values are those
|
|
350
|
+
recommended by the WMO [1]_.
|
|
351
|
+
|
|
352
|
+
Returns
|
|
353
|
+
-------
|
|
354
|
+
numeric
|
|
355
|
+
Relative humidity (0.0-100.0). [%]
|
|
356
|
+
|
|
357
|
+
References
|
|
358
|
+
----------
|
|
359
|
+
.. [1] "Guide to Instruments and Methods of Observation",
|
|
360
|
+
World Meteorological Organization, WMO-No. 8, 2023.
|
|
361
|
+
https://library.wmo.int/idurl/4/68695
|
|
362
|
+
"""
|
|
363
|
+
|
|
364
|
+
# Calculate vapor pressure (e) and saturation vapor pressure (es)
|
|
365
|
+
e = coeff[0] * np.exp((coeff[1] * temp_air) / (coeff[2] + temp_air))
|
|
366
|
+
es = coeff[0] * np.exp((coeff[1] * temp_dew) / (coeff[2] + temp_dew))
|
|
367
|
+
|
|
368
|
+
# Calculate relative humidity as percentage
|
|
369
|
+
relative_humidity = 100 * (es / e)
|
|
370
|
+
|
|
371
|
+
return relative_humidity
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def tdew_from_rh(temp_air, relative_humidity, coeff=(6.112, 17.62, 243.12)):
|
|
375
|
+
"""
|
|
376
|
+
Calculate dewpoint temperature using the Magnus equation.
|
|
377
|
+
This is a reversal of the calculation in :py:func:`rh_from_tdew`.
|
|
378
|
+
|
|
379
|
+
Parameters
|
|
380
|
+
----------
|
|
381
|
+
temp_air : numeric
|
|
382
|
+
Air temperature (dry-bulb temperature). [°C]
|
|
383
|
+
relative_humidity : numeric
|
|
384
|
+
Relative humidity (0-100). [%]
|
|
385
|
+
coeff: tuple, default (6.112, 17.62, 243.12)
|
|
386
|
+
Magnus equation coefficients (A, B, C). The default values are those
|
|
387
|
+
recommended by the WMO [1]_.
|
|
388
|
+
|
|
389
|
+
Returns
|
|
390
|
+
-------
|
|
391
|
+
numeric
|
|
392
|
+
Dewpoint temperature. [°C]
|
|
393
|
+
|
|
394
|
+
References
|
|
395
|
+
----------
|
|
396
|
+
.. [1] "Guide to Instruments and Methods of Observation",
|
|
397
|
+
World Meteorological Organization, WMO-No. 8, 2023.
|
|
398
|
+
https://library.wmo.int/idurl/4/68695
|
|
399
|
+
"""
|
|
400
|
+
# Calculate the term inside the log
|
|
401
|
+
# From RH = 100 * (es/e), we get es = (RH/100) * e
|
|
402
|
+
# Substituting the Magnus equation and solving for dewpoint
|
|
403
|
+
|
|
404
|
+
# First calculate ln(es/A)
|
|
405
|
+
ln_term = (
|
|
406
|
+
(coeff[1] * temp_air) / (coeff[2] + temp_air)
|
|
407
|
+
+ np.log(relative_humidity/100)
|
|
408
|
+
)
|
|
409
|
+
|
|
410
|
+
# Then solve for dewpoint
|
|
411
|
+
dewpoint = coeff[2] * ln_term / (coeff[1] - ln_term)
|
|
412
|
+
|
|
413
|
+
return dewpoint
|
|
344
414
|
|
|
345
415
|
|
|
346
416
|
def bird_hulstrom80_aod_bb(aod380, aod500):
|
pvlib/bifacial/infinite_sheds.py
CHANGED
|
@@ -260,8 +260,9 @@ def get_irradiance_poa(surface_tilt, surface_azimuth, solar_zenith,
|
|
|
260
260
|
Returns
|
|
261
261
|
-------
|
|
262
262
|
output : dict or DataFrame
|
|
263
|
-
Output is a DataFrame when
|
|
264
|
-
|
|
263
|
+
Output is a ``pandas.DataFrame`` when ``ghi`` is a Series.
|
|
264
|
+
Otherwise it is a dict of ``numpy.ndarray``
|
|
265
|
+
See Notes for descriptions of content.
|
|
265
266
|
|
|
266
267
|
Notes
|
|
267
268
|
-----
|
|
@@ -372,7 +373,7 @@ def get_irradiance_poa(surface_tilt, surface_azimuth, solar_zenith,
|
|
|
372
373
|
'poa_global': poa_global, 'poa_direct': poa_direct,
|
|
373
374
|
'poa_diffuse': poa_diffuse, 'poa_ground_diffuse': poa_gnd_pv,
|
|
374
375
|
'poa_sky_diffuse': poa_sky_pv, 'shaded_fraction': f_x}
|
|
375
|
-
if isinstance(
|
|
376
|
+
if isinstance(ghi, pd.Series):
|
|
376
377
|
output = pd.DataFrame(output)
|
|
377
378
|
return output
|
|
378
379
|
|
pvlib/bifacial/utils.py
CHANGED
|
@@ -87,7 +87,8 @@ def _unshaded_ground_fraction(surface_tilt, surface_azimuth, solar_zenith,
|
|
|
87
87
|
surface_azimuth)
|
|
88
88
|
f_gnd_beam = 1.0 - np.minimum(
|
|
89
89
|
1.0, gcr * np.abs(cosd(surface_tilt) + sind(surface_tilt) * tan_phi))
|
|
90
|
-
|
|
90
|
+
# [1], Eq. 4
|
|
91
|
+
f_gnd_beam = np.where(solar_zenith > max_zenith, 0., f_gnd_beam)
|
|
91
92
|
return f_gnd_beam # 1 - min(1, abs()) < 1 always
|
|
92
93
|
|
|
93
94
|
|
pvlib/clearsky.py
CHANGED
|
@@ -327,13 +327,13 @@ def haurwitz(apparent_zenith):
|
|
|
327
327
|
'''
|
|
328
328
|
|
|
329
329
|
cos_zenith = tools.cosd(apparent_zenith.values)
|
|
330
|
-
|
|
330
|
+
ghi_clear = np.zeros_like(apparent_zenith.values)
|
|
331
331
|
cos_zen_gte_0 = cos_zenith > 0
|
|
332
|
-
|
|
333
|
-
|
|
332
|
+
ghi_clear[cos_zen_gte_0] = (1098.0 * cos_zenith[cos_zen_gte_0] *
|
|
333
|
+
np.exp(-0.059/cos_zenith[cos_zen_gte_0]))
|
|
334
334
|
|
|
335
335
|
df_out = pd.DataFrame(index=apparent_zenith.index,
|
|
336
|
-
data=
|
|
336
|
+
data=ghi_clear,
|
|
337
337
|
columns=['ghi'])
|
|
338
338
|
|
|
339
339
|
return df_out
|
|
@@ -683,22 +683,26 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
|
|
|
683
683
|
var_diff=0.005, slope_dev=8, max_iterations=20,
|
|
684
684
|
return_components=False):
|
|
685
685
|
"""
|
|
686
|
-
Detects clear sky times
|
|
687
|
-
and Hansen
|
|
688
|
-
validated for analyzing GHI time series only. Users may attempt to
|
|
689
|
-
apply it to other types of time series data using different filter
|
|
690
|
-
settings, but should be skeptical of the results.
|
|
686
|
+
Detects clear sky times using the algorithm developed by Reno
|
|
687
|
+
and Hansen.
|
|
691
688
|
|
|
692
|
-
The algorithm
|
|
689
|
+
The algorithm [1]_ was designed and
|
|
690
|
+
validated for analyzing GHI time series. Jordan and Hansen [2]_ extended
|
|
691
|
+
the algorithm to plane-of-array (POA) irradiance measurements.
|
|
692
|
+
|
|
693
|
+
The algorithm [1]_ detects clear sky times by comparing statistics for a
|
|
693
694
|
measured time series and an expected clearsky time series.
|
|
694
695
|
Statistics are calculated using a sliding time window (e.g., 10
|
|
695
696
|
minutes). An iterative algorithm identifies clear periods, uses the
|
|
696
697
|
identified periods to estimate bias in the clearsky data, scales the
|
|
697
698
|
clearsky data and repeats.
|
|
698
699
|
|
|
699
|
-
Clear times are identified by meeting
|
|
700
|
+
Clear times are identified by meeting five criteria. Default values for
|
|
700
701
|
these thresholds are appropriate for 10 minute windows of 1 minute
|
|
701
|
-
GHI data.
|
|
702
|
+
GHI data. For data at longer intervals, it is recommended
|
|
703
|
+
to set ``infer_limits=True`` to use the thresholds from [2]_.
|
|
704
|
+
|
|
705
|
+
For POA data, ``clearsky`` must be on the same plane as ``measured``.
|
|
702
706
|
|
|
703
707
|
Parameters
|
|
704
708
|
----------
|
|
@@ -713,8 +717,8 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
|
|
|
713
717
|
If True, does not use passed in kwargs (or defaults), but instead
|
|
714
718
|
interpolates these values from Table 1 in [2]_.
|
|
715
719
|
window_length : int, default 10
|
|
716
|
-
Length of sliding time window in minutes.
|
|
717
|
-
|
|
720
|
+
Length of sliding time window in minutes. Each window must contain at
|
|
721
|
+
least three data points.
|
|
718
722
|
mean_diff : float, default 75
|
|
719
723
|
Threshold value for agreement between mean values of measured
|
|
720
724
|
and clearsky in each interval, see Eq. 6 in [1]. [W/m2]
|
|
@@ -723,8 +727,6 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
|
|
|
723
727
|
clearsky values in each interval, see Eq. 7 in [1]. [W/m2]
|
|
724
728
|
lower_line_length : float, default -5
|
|
725
729
|
Lower limit of line length criterion from Eq. 8 in [1].
|
|
726
|
-
Criterion satisfied when lower_line_length < line length difference
|
|
727
|
-
< upper_line_length.
|
|
728
730
|
upper_line_length : float, default 10
|
|
729
731
|
Upper limit of line length criterion from Eq. 8 in [1].
|
|
730
732
|
var_diff : float, default 0.005
|
|
@@ -736,7 +738,7 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
|
|
|
736
738
|
change in successive values, see Eqs. 12 through 14 in [1].
|
|
737
739
|
max_iterations : int, default 20
|
|
738
740
|
Maximum number of times to apply a different scaling factor to
|
|
739
|
-
the clearsky and redetermine clear_samples
|
|
741
|
+
the clearsky and redetermine ``clear_samples``. Must be 1 or larger.
|
|
740
742
|
return_components : bool, default False
|
|
741
743
|
Controls if additional output should be returned. See below.
|
|
742
744
|
|
|
@@ -748,19 +750,23 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
|
|
|
748
750
|
|
|
749
751
|
components : OrderedDict, optional
|
|
750
752
|
Dict of arrays of whether or not the given time window is clear
|
|
751
|
-
for each condition. Only provided if return_components is True.
|
|
753
|
+
for each condition. Only provided if ``return_components`` is True.
|
|
752
754
|
|
|
753
755
|
alpha : scalar, optional
|
|
754
|
-
Scaling factor applied to
|
|
755
|
-
detected clear_samples
|
|
756
|
+
Scaling factor applied to ``clearsky`` to obtain the
|
|
757
|
+
detected ``clear_samples``. Only provided if ``return_components`` is
|
|
756
758
|
True.
|
|
757
759
|
|
|
758
760
|
Raises
|
|
759
761
|
------
|
|
760
762
|
ValueError
|
|
761
|
-
If measured is not a Series and times is not provided
|
|
763
|
+
If ``measured`` is not a Series and times is not provided.
|
|
764
|
+
ValueError
|
|
765
|
+
If a window contains less than three data points.
|
|
766
|
+
ValueError
|
|
767
|
+
If the measured data is not sufficient to fill a window.
|
|
762
768
|
NotImplementedError
|
|
763
|
-
If timestamps are not equally spaced
|
|
769
|
+
If timestamps are not equally spaced.
|
|
764
770
|
|
|
765
771
|
References
|
|
766
772
|
----------
|
|
@@ -812,6 +818,13 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
|
|
|
812
818
|
sample_interval, samples_per_window = \
|
|
813
819
|
tools._get_sample_intervals(times, window_length)
|
|
814
820
|
|
|
821
|
+
if samples_per_window < 3:
|
|
822
|
+
raise ValueError(f"Samples per window of {samples_per_window}"
|
|
823
|
+
" found. Each window must contain at least 3 data"
|
|
824
|
+
" points."
|
|
825
|
+
f" Window length of {window_length} found; increase"
|
|
826
|
+
f" window length to {3*sample_interval} or longer.")
|
|
827
|
+
|
|
815
828
|
# if infer_limits, find threshold values using the sample interval
|
|
816
829
|
if infer_limits:
|
|
817
830
|
window_length, mean_diff, max_diff, lower_line_length, \
|
pvlib/iam.py
CHANGED
|
@@ -269,8 +269,8 @@ def martin_ruiz(aoi, a_r=0.16):
|
|
|
269
269
|
|
|
270
270
|
which is presented as :math:`AL(\alpha) = 1 - IAM` in equation 4 of [1]_,
|
|
271
271
|
with :math:`\alpha` representing the angle of incidence AOI. Thus IAM = 1
|
|
272
|
-
at AOI = 0
|
|
273
|
-
|
|
272
|
+
at AOI = 0°, and IAM = 0 at AOI = 90°. This equation is only valid for
|
|
273
|
+
0° <= aoi <= 90°, therefore `iam` is constrained to 0.0 outside this
|
|
274
274
|
interval.
|
|
275
275
|
|
|
276
276
|
References
|
|
@@ -891,8 +891,8 @@ def schlick_diffuse(surface_tilt):
|
|
|
891
891
|
implements only the integrated Schlick approximation.
|
|
892
892
|
|
|
893
893
|
Note also that the output of this function (which is an exact integration)
|
|
894
|
-
can be compared with the output of :py:func:`marion_diffuse` which
|
|
895
|
-
integrates the Schlick approximation:
|
|
894
|
+
can be compared with the output of :py:func:`marion_diffuse` which
|
|
895
|
+
numerically integrates the Schlick approximation:
|
|
896
896
|
|
|
897
897
|
.. code::
|
|
898
898
|
|
pvlib/iotools/midc.py
CHANGED
|
@@ -193,7 +193,7 @@ def read_midc(filename, variable_map={}, raw_data=False, **kwargs):
|
|
|
193
193
|
|
|
194
194
|
See the MIDC_VARIABLE_MAP for collection of mappings by site.
|
|
195
195
|
For a full list of pvlib variable names see the
|
|
196
|
-
:ref:`
|
|
196
|
+
:ref:`nomenclature`.
|
|
197
197
|
|
|
198
198
|
Be sure to check the units for the variables you will use on the
|
|
199
199
|
`MIDC site <https://midcdmz.nrel.gov/>`_.
|
pvlib/iotools/psm3.py
CHANGED
|
@@ -49,7 +49,7 @@ REQUEST_VARIABLE_MAP = {
|
|
|
49
49
|
'ghi_clear': 'clearsky_ghi',
|
|
50
50
|
'dhi_clear': 'clearsky_dhi',
|
|
51
51
|
'dni_clear': 'clearsky_dni',
|
|
52
|
-
'
|
|
52
|
+
'solar_zenith': 'solar_zenith_angle',
|
|
53
53
|
'temp_air': 'air_temperature',
|
|
54
54
|
'temp_dew': 'dew_point',
|
|
55
55
|
'relative_humidity': 'relative_humidity',
|
pvlib/iotools/pvgis.py
CHANGED
|
@@ -467,16 +467,6 @@ def get_pvgis_tmy(latitude, longitude, outputformat='json', usehorizon=True,
|
|
|
467
467
|
metadata : list or dict
|
|
468
468
|
file metadata, ``None`` for basic
|
|
469
469
|
|
|
470
|
-
Note
|
|
471
|
-
----
|
|
472
|
-
The PVGIS website uses 10 years of data to generate the TMY, whereas the
|
|
473
|
-
API accessed by this function defaults to using all available years. This
|
|
474
|
-
means that the TMY returned by this function may not be identical to the
|
|
475
|
-
one generated by the website. To replicate the website requests, specify
|
|
476
|
-
the corresponding 10 year period using ``startyear`` and ``endyear``.
|
|
477
|
-
Specifying ``endyear`` also avoids the TMY changing when new data becomes
|
|
478
|
-
available.
|
|
479
|
-
|
|
480
470
|
Raises
|
|
481
471
|
------
|
|
482
472
|
requests.HTTPError
|
|
@@ -569,9 +559,17 @@ def _parse_pvgis_tmy_csv(src):
|
|
|
569
559
|
inputs['longitude'] = float(src.readline().split(b':')[1])
|
|
570
560
|
# Elevation (m): 1389.0\r\n
|
|
571
561
|
inputs['elevation'] = float(src.readline().split(b':')[1])
|
|
562
|
+
|
|
563
|
+
# TMY has an extra line here: Irradiance Time Offset (h): 0.1761\r\n
|
|
564
|
+
line = src.readline()
|
|
565
|
+
if line.startswith(b'Irradiance Time Offset'):
|
|
566
|
+
inputs['irradiance time offset'] = float(line.split(b':')[1])
|
|
567
|
+
src.readline() # skip over the "month,year\r\n"
|
|
568
|
+
else:
|
|
569
|
+
# `line` is already the "month,year\r\n" line, so nothing to do
|
|
570
|
+
pass
|
|
572
571
|
# then there's a 13 row comma separated table with two columns: month, year
|
|
573
|
-
# which contains the year used for that month in the
|
|
574
|
-
src.readline() # get "month,year\r\n"
|
|
572
|
+
# which contains the year used for that month in the TMY
|
|
575
573
|
months_selected = []
|
|
576
574
|
for month in range(12):
|
|
577
575
|
months_selected.append(
|
pvlib/iotools/tmy.py
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
import datetime
|
|
4
4
|
import re
|
|
5
5
|
import pandas as pd
|
|
6
|
-
import warnings
|
|
7
|
-
from pvlib._deprecation import pvlibDeprecationWarning
|
|
8
6
|
|
|
9
7
|
# Dictionary mapping TMY3 names to pvlib names
|
|
10
8
|
VARIABLE_MAP = {
|
|
@@ -24,8 +22,7 @@ VARIABLE_MAP = {
|
|
|
24
22
|
}
|
|
25
23
|
|
|
26
24
|
|
|
27
|
-
def read_tmy3(filename, coerce_year=None, map_variables=
|
|
28
|
-
encoding=None):
|
|
25
|
+
def read_tmy3(filename, coerce_year=None, map_variables=True, encoding=None):
|
|
29
26
|
"""Read a TMY3 file into a pandas dataframe.
|
|
30
27
|
|
|
31
28
|
Note that values contained in the metadata dictionary are unchanged
|
|
@@ -44,13 +41,9 @@ def read_tmy3(filename, coerce_year=None, map_variables=None, recolumn=None,
|
|
|
44
41
|
If supplied, the year of the index will be set to ``coerce_year``, except
|
|
45
42
|
for the last index value which will be set to the *next* year so that
|
|
46
43
|
the index increases monotonically.
|
|
47
|
-
map_variables : bool,
|
|
44
|
+
map_variables : bool, default True
|
|
48
45
|
When True, renames columns of the DataFrame to pvlib variable names
|
|
49
46
|
where applicable. See variable :const:`VARIABLE_MAP`.
|
|
50
|
-
recolumn : bool (deprecated, use map_variables instead)
|
|
51
|
-
If ``True``, apply standard names to TMY3 columns. Typically this
|
|
52
|
-
results in stripping the units from the column name.
|
|
53
|
-
Cannot be used in combination with ``map_variables``.
|
|
54
47
|
encoding : str, optional
|
|
55
48
|
Encoding of the file. For files that contain non-UTF8 characters it may
|
|
56
49
|
be necessary to specify an alternative encoding, e.g., for
|
|
@@ -233,74 +226,15 @@ def read_tmy3(filename, coerce_year=None, map_variables=None, recolumn=None,
|
|
|
233
226
|
# unit must be in (D,h,m,s,ms,us,ns), but pandas>=0.24 allows unit='hour'
|
|
234
227
|
data.index = data_ymd + pd.to_timedelta(shifted_hour, unit='h') \
|
|
235
228
|
+ pd.to_timedelta(minutes, unit='min')
|
|
236
|
-
|
|
237
|
-
if recolumn is not None and map_variables is not None:
|
|
238
|
-
msg = "`map_variables` and `recolumn` cannot both be specified"
|
|
239
|
-
raise ValueError(msg)
|
|
240
|
-
elif map_variables is None and recolumn is not None:
|
|
241
|
-
warnings.warn(
|
|
242
|
-
'The recolumn parameter is deprecated and will be removed in '
|
|
243
|
-
'pvlib 0.11.0. Use `map_variables` instead, although note that '
|
|
244
|
-
'its behavior is different from `recolumn`.',
|
|
245
|
-
pvlibDeprecationWarning)
|
|
246
|
-
elif map_variables is None and recolumn is None:
|
|
247
|
-
warnings.warn(
|
|
248
|
-
'TMY3 variable names will be renamed to pvlib conventions by '
|
|
249
|
-
'default starting in pvlib 0.11.0. Specify map_variables=True '
|
|
250
|
-
'to enable that behavior now, or specify map_variables=False '
|
|
251
|
-
'to hide this warning.', pvlibDeprecationWarning)
|
|
229
|
+
|
|
252
230
|
if map_variables:
|
|
253
231
|
data = data.rename(columns=VARIABLE_MAP)
|
|
254
|
-
elif recolumn or (recolumn is None and map_variables is None):
|
|
255
|
-
data = _recolumn(data)
|
|
256
232
|
|
|
257
233
|
data = data.tz_localize(int(meta['TZ'] * 3600))
|
|
258
234
|
|
|
259
235
|
return data, meta
|
|
260
236
|
|
|
261
237
|
|
|
262
|
-
def _recolumn(tmy3_dataframe):
|
|
263
|
-
"""
|
|
264
|
-
Rename the columns of the TMY3 DataFrame.
|
|
265
|
-
|
|
266
|
-
Parameters
|
|
267
|
-
----------
|
|
268
|
-
tmy3_dataframe : DataFrame
|
|
269
|
-
inplace : bool
|
|
270
|
-
passed to DataFrame.rename()
|
|
271
|
-
|
|
272
|
-
Returns
|
|
273
|
-
-------
|
|
274
|
-
Recolumned DataFrame.
|
|
275
|
-
"""
|
|
276
|
-
# paste in the header as one long line
|
|
277
|
-
raw_columns = 'ETR (W/m^2),ETRN (W/m^2),GHI (W/m^2),GHI source,GHI uncert (%),DNI (W/m^2),DNI source,DNI uncert (%),DHI (W/m^2),DHI source,DHI uncert (%),GH illum (lx),GH illum source,Global illum uncert (%),DN illum (lx),DN illum source,DN illum uncert (%),DH illum (lx),DH illum source,DH illum uncert (%),Zenith lum (cd/m^2),Zenith lum source,Zenith lum uncert (%),TotCld (tenths),TotCld source,TotCld uncert (code),OpqCld (tenths),OpqCld source,OpqCld uncert (code),Dry-bulb (C),Dry-bulb source,Dry-bulb uncert (code),Dew-point (C),Dew-point source,Dew-point uncert (code),RHum (%),RHum source,RHum uncert (code),Pressure (mbar),Pressure source,Pressure uncert (code),Wdir (degrees),Wdir source,Wdir uncert (code),Wspd (m/s),Wspd source,Wspd uncert (code),Hvis (m),Hvis source,Hvis uncert (code),CeilHgt (m),CeilHgt source,CeilHgt uncert (code),Pwat (cm),Pwat source,Pwat uncert (code),AOD (unitless),AOD source,AOD uncert (code),Alb (unitless),Alb source,Alb uncert (code),Lprecip depth (mm),Lprecip quantity (hr),Lprecip source,Lprecip uncert (code),PresWth (METAR code),PresWth source,PresWth uncert (code)' # noqa: E501
|
|
278
|
-
|
|
279
|
-
new_columns = [
|
|
280
|
-
'ETR', 'ETRN', 'GHI', 'GHISource', 'GHIUncertainty',
|
|
281
|
-
'DNI', 'DNISource', 'DNIUncertainty', 'DHI', 'DHISource',
|
|
282
|
-
'DHIUncertainty', 'GHillum', 'GHillumSource', 'GHillumUncertainty',
|
|
283
|
-
'DNillum', 'DNillumSource', 'DNillumUncertainty', 'DHillum',
|
|
284
|
-
'DHillumSource', 'DHillumUncertainty', 'Zenithlum',
|
|
285
|
-
'ZenithlumSource', 'ZenithlumUncertainty', 'TotCld', 'TotCldSource',
|
|
286
|
-
'TotCldUncertainty', 'OpqCld', 'OpqCldSource', 'OpqCldUncertainty',
|
|
287
|
-
'DryBulb', 'DryBulbSource', 'DryBulbUncertainty', 'DewPoint',
|
|
288
|
-
'DewPointSource', 'DewPointUncertainty', 'RHum', 'RHumSource',
|
|
289
|
-
'RHumUncertainty', 'Pressure', 'PressureSource',
|
|
290
|
-
'PressureUncertainty', 'Wdir', 'WdirSource', 'WdirUncertainty',
|
|
291
|
-
'Wspd', 'WspdSource', 'WspdUncertainty', 'Hvis', 'HvisSource',
|
|
292
|
-
'HvisUncertainty', 'CeilHgt', 'CeilHgtSource', 'CeilHgtUncertainty',
|
|
293
|
-
'Pwat', 'PwatSource', 'PwatUncertainty', 'AOD', 'AODSource',
|
|
294
|
-
'AODUncertainty', 'Alb', 'AlbSource', 'AlbUncertainty',
|
|
295
|
-
'Lprecipdepth', 'Lprecipquantity', 'LprecipSource',
|
|
296
|
-
'LprecipUncertainty', 'PresWth', 'PresWthSource',
|
|
297
|
-
'PresWthUncertainty']
|
|
298
|
-
|
|
299
|
-
mapping = dict(zip(raw_columns.split(','), new_columns))
|
|
300
|
-
|
|
301
|
-
return tmy3_dataframe.rename(columns=mapping)
|
|
302
|
-
|
|
303
|
-
|
|
304
238
|
def read_tmy2(filename):
|
|
305
239
|
"""
|
|
306
240
|
Read a TMY2 file into a DataFrame.
|