pvlib 0.9.5__py3-none-any.whl → 0.10.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 +3 -2
- pvlib/atmosphere.py +6 -171
- pvlib/bifacial/infinite_sheds.py +30 -267
- pvlib/bifacial/utils.py +225 -5
- pvlib/data/test_psm3_2017.csv +17521 -17521
- pvlib/data/test_read_psm3.csv +17522 -17522
- pvlib/data/test_read_pvgis_horizon.csv +49 -0
- pvlib/data/variables_style_rules.csv +3 -0
- pvlib/iam.py +17 -4
- pvlib/inverter.py +6 -1
- pvlib/iotools/__init__.py +7 -2
- pvlib/iotools/acis.py +516 -0
- pvlib/iotools/midc.py +4 -4
- pvlib/iotools/psm3.py +32 -31
- pvlib/iotools/pvgis.py +84 -28
- pvlib/iotools/sodapro.py +8 -6
- pvlib/iotools/srml.py +121 -18
- pvlib/iotools/surfrad.py +2 -2
- pvlib/iotools/tmy.py +146 -102
- pvlib/irradiance.py +151 -0
- pvlib/ivtools/sde.py +11 -7
- pvlib/ivtools/sdm.py +16 -10
- pvlib/ivtools/utils.py +6 -6
- pvlib/location.py +3 -2
- pvlib/modelchain.py +67 -70
- pvlib/pvsystem.py +160 -532
- pvlib/shading.py +41 -0
- pvlib/singlediode.py +215 -65
- pvlib/soiling.py +3 -3
- pvlib/spa.py +327 -368
- pvlib/spectrum/__init__.py +8 -2
- pvlib/spectrum/mismatch.py +335 -0
- pvlib/temperature.py +1 -8
- pvlib/tests/bifacial/test_infinite_sheds.py +0 -111
- pvlib/tests/bifacial/test_utils.py +101 -4
- pvlib/tests/conftest.py +0 -31
- pvlib/tests/iotools/test_acis.py +213 -0
- pvlib/tests/iotools/test_midc.py +6 -6
- pvlib/tests/iotools/test_psm3.py +3 -3
- pvlib/tests/iotools/test_pvgis.py +21 -14
- pvlib/tests/iotools/test_sodapro.py +1 -1
- pvlib/tests/iotools/test_srml.py +71 -6
- pvlib/tests/iotools/test_tmy.py +43 -8
- pvlib/tests/ivtools/test_sde.py +19 -17
- pvlib/tests/ivtools/test_sdm.py +9 -4
- pvlib/tests/test_atmosphere.py +6 -62
- pvlib/tests/test_iam.py +12 -0
- pvlib/tests/test_irradiance.py +40 -2
- pvlib/tests/test_location.py +1 -1
- pvlib/tests/test_modelchain.py +33 -76
- pvlib/tests/test_pvsystem.py +366 -201
- pvlib/tests/test_shading.py +28 -0
- pvlib/tests/test_singlediode.py +166 -30
- pvlib/tests/test_soiling.py +8 -7
- pvlib/tests/test_spa.py +6 -7
- pvlib/tests/test_spectrum.py +145 -1
- pvlib/tests/test_temperature.py +0 -7
- pvlib/tests/test_tools.py +25 -0
- pvlib/tests/test_tracking.py +0 -149
- pvlib/tools.py +26 -1
- pvlib/tracking.py +1 -269
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/METADATA +1 -9
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/RECORD +67 -68
- pvlib/forecast.py +0 -1211
- pvlib/iotools/ecmwf_macc.py +0 -312
- pvlib/tests/iotools/test_ecmwf_macc.py +0 -162
- pvlib/tests/test_forecast.py +0 -228
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/AUTHORS.md +0 -0
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/LICENSE +0 -0
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/WHEEL +0 -0
- {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/top_level.txt +0 -0
pvlib/ivtools/utils.py
CHANGED
|
@@ -150,12 +150,12 @@ def rectify_iv_curve(voltage, current, decimals=None):
|
|
|
150
150
|
``rectify_iv_curve`` ensures that the IV curve lies in the first quadrant
|
|
151
151
|
of the (voltage, current) plane. The returned IV curve:
|
|
152
152
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
153
|
+
* increases in voltage
|
|
154
|
+
* contains no negative current or voltage values
|
|
155
|
+
* contains no NaNs
|
|
156
|
+
* contains no points with duplicate voltage values. Where voltage
|
|
157
|
+
values are repeated, a single data point is substituted with current
|
|
158
|
+
equal to the average of current at duplicated voltages.
|
|
159
159
|
"""
|
|
160
160
|
|
|
161
161
|
df = pd.DataFrame(data=np.vstack((voltage, current)).T, columns=['v', 'i'])
|
pvlib/location.py
CHANGED
|
@@ -331,8 +331,9 @@ class Location:
|
|
|
331
331
|
method : str, default 'pyephem'
|
|
332
332
|
'pyephem', 'spa', or 'geometric'
|
|
333
333
|
|
|
334
|
-
kwargs
|
|
335
|
-
|
|
334
|
+
kwargs :
|
|
335
|
+
Passed to the relevant functions. See
|
|
336
|
+
solarposition.sun_rise_set_transit_<method> for details.
|
|
336
337
|
|
|
337
338
|
Returns
|
|
338
339
|
-------
|
pvlib/modelchain.py
CHANGED
|
@@ -14,8 +14,7 @@ from dataclasses import dataclass, field
|
|
|
14
14
|
from typing import Union, Tuple, Optional, TypeVar
|
|
15
15
|
|
|
16
16
|
from pvlib import (atmosphere, clearsky, inverter, pvsystem, solarposition,
|
|
17
|
-
temperature
|
|
18
|
-
from pvlib.tracking import SingleAxisTracker
|
|
17
|
+
temperature)
|
|
19
18
|
import pvlib.irradiance # avoid name conflict with full import
|
|
20
19
|
from pvlib.pvsystem import _DC_MODEL_PARAMS
|
|
21
20
|
from pvlib._deprecation import pvlibDeprecationWarning
|
|
@@ -254,6 +253,33 @@ def get_orientation(strategy, **kwargs):
|
|
|
254
253
|
return surface_tilt, surface_azimuth
|
|
255
254
|
|
|
256
255
|
|
|
256
|
+
def _getmcattr(self, attr):
|
|
257
|
+
"""
|
|
258
|
+
Helper for __repr__ methods, needed to avoid recursion in property
|
|
259
|
+
lookups
|
|
260
|
+
"""
|
|
261
|
+
out = getattr(self, attr)
|
|
262
|
+
try:
|
|
263
|
+
out = out.__name__
|
|
264
|
+
except AttributeError:
|
|
265
|
+
pass
|
|
266
|
+
return out
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _mcr_repr(obj):
|
|
270
|
+
'''
|
|
271
|
+
Helper for ModelChainResult.__repr__
|
|
272
|
+
'''
|
|
273
|
+
if isinstance(obj, tuple):
|
|
274
|
+
return "Tuple (" + ", ".join([_mcr_repr(o) for o in obj]) + ")"
|
|
275
|
+
if isinstance(obj, pd.DataFrame):
|
|
276
|
+
return "DataFrame ({} rows x {} columns)".format(*obj.shape)
|
|
277
|
+
if isinstance(obj, pd.Series):
|
|
278
|
+
return "Series (length {})".format(len(obj))
|
|
279
|
+
# scalar, None, other?
|
|
280
|
+
return repr(obj)
|
|
281
|
+
|
|
282
|
+
|
|
257
283
|
# Type for fields that vary between arrays
|
|
258
284
|
T = TypeVar('T')
|
|
259
285
|
|
|
@@ -385,6 +411,33 @@ class ModelChainResult:
|
|
|
385
411
|
value = self._result_type(value)
|
|
386
412
|
super().__setattr__(key, value)
|
|
387
413
|
|
|
414
|
+
def __repr__(self):
|
|
415
|
+
mc_attrs = dir(self)
|
|
416
|
+
|
|
417
|
+
def _head(obj):
|
|
418
|
+
try:
|
|
419
|
+
return obj[:3]
|
|
420
|
+
except:
|
|
421
|
+
return obj
|
|
422
|
+
|
|
423
|
+
if type(self.dc) is tuple:
|
|
424
|
+
num_arrays = len(self.dc)
|
|
425
|
+
else:
|
|
426
|
+
num_arrays = 1
|
|
427
|
+
|
|
428
|
+
desc1 = ('=== ModelChainResult === \n')
|
|
429
|
+
desc2 = (f'Number of Arrays: {num_arrays} \n')
|
|
430
|
+
attr = 'times'
|
|
431
|
+
desc3 = ('times (first 3)\n' +
|
|
432
|
+
f'{_head(_getmcattr(self, attr))}' +
|
|
433
|
+
'\n')
|
|
434
|
+
lines = []
|
|
435
|
+
for attr in mc_attrs:
|
|
436
|
+
if not (attr.startswith('_') or attr=='times'):
|
|
437
|
+
lines.append(f' {attr}: ' + _mcr_repr(getattr(self, attr)))
|
|
438
|
+
desc4 = '\n'.join(lines)
|
|
439
|
+
return (desc1 + desc2 + desc3 + desc4)
|
|
440
|
+
|
|
388
441
|
|
|
389
442
|
class ModelChain:
|
|
390
443
|
"""
|
|
@@ -465,13 +518,6 @@ class ModelChain:
|
|
|
465
518
|
Name of ModelChain instance.
|
|
466
519
|
"""
|
|
467
520
|
|
|
468
|
-
# list of deprecated attributes
|
|
469
|
-
_deprecated_attrs = ['solar_position', 'airmass', 'total_irrad',
|
|
470
|
-
'aoi', 'aoi_modifier', 'spectral_modifier',
|
|
471
|
-
'cell_temperature', 'effective_irradiance',
|
|
472
|
-
'dc', 'ac', 'diode_params', 'tracking',
|
|
473
|
-
'weather', 'times', 'losses']
|
|
474
|
-
|
|
475
521
|
def __init__(self, system, location,
|
|
476
522
|
clearsky_model='ineichen',
|
|
477
523
|
transposition_model='haydavies',
|
|
@@ -503,26 +549,6 @@ class ModelChain:
|
|
|
503
549
|
|
|
504
550
|
self.results = ModelChainResult()
|
|
505
551
|
|
|
506
|
-
def __getattr__(self, key):
|
|
507
|
-
if key in ModelChain._deprecated_attrs:
|
|
508
|
-
msg = f'ModelChain.{key} is deprecated and will' \
|
|
509
|
-
f' be removed in v0.10. Use' \
|
|
510
|
-
f' ModelChain.results.{key} instead'
|
|
511
|
-
warnings.warn(msg, pvlibDeprecationWarning)
|
|
512
|
-
return getattr(self.results, key)
|
|
513
|
-
# __getattr__ is only called if __getattribute__ fails.
|
|
514
|
-
# In that case we should check if key is a deprecated attribute,
|
|
515
|
-
# and fail with an AttributeError if it is not.
|
|
516
|
-
raise AttributeError
|
|
517
|
-
|
|
518
|
-
def __setattr__(self, key, value):
|
|
519
|
-
if key in ModelChain._deprecated_attrs:
|
|
520
|
-
msg = f'ModelChain.{key} is deprecated from v0.9. Use' \
|
|
521
|
-
f' ModelChain.results.{key} instead'
|
|
522
|
-
warnings.warn(msg, pvlibDeprecationWarning)
|
|
523
|
-
setattr(self.results, key, value)
|
|
524
|
-
else:
|
|
525
|
-
super().__setattr__(key, value)
|
|
526
552
|
|
|
527
553
|
@classmethod
|
|
528
554
|
def with_pvwatts(cls, system, location,
|
|
@@ -560,7 +586,7 @@ class ModelChain:
|
|
|
560
586
|
Examples
|
|
561
587
|
--------
|
|
562
588
|
>>> module_parameters = dict(gamma_pdc=-0.003, pdc0=4500)
|
|
563
|
-
>>> inverter_parameters = dict(
|
|
589
|
+
>>> inverter_parameters = dict(pdc0=4000)
|
|
564
590
|
>>> tparams = TEMPERATURE_MODEL_PARAMETERS['sapm']['open_rack_glass_glass']
|
|
565
591
|
>>> system = PVSystem(surface_tilt=30, surface_azimuth=180,
|
|
566
592
|
... module_parameters=module_parameters,
|
|
@@ -678,18 +704,8 @@ class ModelChain:
|
|
|
678
704
|
'airmass_model', 'dc_model', 'ac_model', 'aoi_model',
|
|
679
705
|
'spectral_model', 'temperature_model', 'losses_model'
|
|
680
706
|
]
|
|
681
|
-
|
|
682
|
-
def getmcattr(self, attr):
|
|
683
|
-
"""needed to avoid recursion in property lookups"""
|
|
684
|
-
out = getattr(self, attr)
|
|
685
|
-
try:
|
|
686
|
-
out = out.__name__
|
|
687
|
-
except AttributeError:
|
|
688
|
-
pass
|
|
689
|
-
return out
|
|
690
|
-
|
|
691
707
|
return ('ModelChain: \n ' + '\n '.join(
|
|
692
|
-
f'{attr}: {
|
|
708
|
+
f'{attr}: {_getmcattr(self, attr)}' for attr in attrs))
|
|
693
709
|
|
|
694
710
|
@property
|
|
695
711
|
def dc_model(self):
|
|
@@ -1535,27 +1551,11 @@ class ModelChain:
|
|
|
1535
1551
|
self._prep_inputs_solar_pos(weather)
|
|
1536
1552
|
self._prep_inputs_airmass()
|
|
1537
1553
|
self._prep_inputs_albedo(weather)
|
|
1554
|
+
self._prep_inputs_fixed()
|
|
1538
1555
|
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
# the differences.
|
|
1543
|
-
if isinstance(self.system, SingleAxisTracker):
|
|
1544
|
-
self._prep_inputs_tracking()
|
|
1545
|
-
get_irradiance = partial(
|
|
1546
|
-
self.system.get_irradiance,
|
|
1547
|
-
self.results.tracking['surface_tilt'],
|
|
1548
|
-
self.results.tracking['surface_azimuth'],
|
|
1549
|
-
self.results.solar_position['apparent_zenith'],
|
|
1550
|
-
self.results.solar_position['azimuth'])
|
|
1551
|
-
else:
|
|
1552
|
-
self._prep_inputs_fixed()
|
|
1553
|
-
get_irradiance = partial(
|
|
1554
|
-
self.system.get_irradiance,
|
|
1555
|
-
self.results.solar_position['apparent_zenith'],
|
|
1556
|
-
self.results.solar_position['azimuth'])
|
|
1557
|
-
|
|
1558
|
-
self.results.total_irrad = get_irradiance(
|
|
1556
|
+
self.results.total_irrad = self.system.get_irradiance(
|
|
1557
|
+
self.results.solar_position['apparent_zenith'],
|
|
1558
|
+
self.results.solar_position['azimuth'],
|
|
1559
1559
|
_tuple_from_dfs(self.results.weather, 'dni'),
|
|
1560
1560
|
_tuple_from_dfs(self.results.weather, 'ghi'),
|
|
1561
1561
|
_tuple_from_dfs(self.results.weather, 'dhi'),
|
|
@@ -1636,10 +1636,7 @@ class ModelChain:
|
|
|
1636
1636
|
self._prep_inputs_solar_pos(data)
|
|
1637
1637
|
self._prep_inputs_airmass()
|
|
1638
1638
|
|
|
1639
|
-
|
|
1640
|
-
self._prep_inputs_tracking()
|
|
1641
|
-
else:
|
|
1642
|
-
self._prep_inputs_fixed()
|
|
1639
|
+
self._prep_inputs_fixed()
|
|
1643
1640
|
|
|
1644
1641
|
return self
|
|
1645
1642
|
|
|
@@ -1686,7 +1683,7 @@ class ModelChain:
|
|
|
1686
1683
|
self.temperature_model()
|
|
1687
1684
|
return self
|
|
1688
1685
|
|
|
1689
|
-
def _prepare_temperature(self, data
|
|
1686
|
+
def _prepare_temperature(self, data):
|
|
1690
1687
|
"""
|
|
1691
1688
|
Sets cell_temperature using inputs in data and the specified
|
|
1692
1689
|
temperature model.
|
|
@@ -1699,7 +1696,7 @@ class ModelChain:
|
|
|
1699
1696
|
|
|
1700
1697
|
Parameters
|
|
1701
1698
|
----------
|
|
1702
|
-
data : DataFrame
|
|
1699
|
+
data : DataFrame
|
|
1703
1700
|
May contain columns ``'cell_temperature'`` or
|
|
1704
1701
|
``'module_temperaure'``.
|
|
1705
1702
|
|
|
@@ -1878,13 +1875,13 @@ class ModelChain:
|
|
|
1878
1875
|
|
|
1879
1876
|
return self
|
|
1880
1877
|
|
|
1881
|
-
def _run_from_effective_irrad(self, data
|
|
1878
|
+
def _run_from_effective_irrad(self, data):
|
|
1882
1879
|
"""
|
|
1883
1880
|
Executes the temperature, DC, losses and AC models.
|
|
1884
1881
|
|
|
1885
1882
|
Parameters
|
|
1886
1883
|
----------
|
|
1887
|
-
data : DataFrame, or tuple of DataFrame
|
|
1884
|
+
data : DataFrame, or tuple of DataFrame
|
|
1888
1885
|
If optional column ``'cell_temperature'`` is provided, these values
|
|
1889
1886
|
are used instead of `temperature_model`. If optional column
|
|
1890
1887
|
`module_temperature` is provided, `temperature_model` must be
|
|
@@ -1907,7 +1904,7 @@ class ModelChain:
|
|
|
1907
1904
|
|
|
1908
1905
|
return self
|
|
1909
1906
|
|
|
1910
|
-
def run_model_from_effective_irradiance(self, data
|
|
1907
|
+
def run_model_from_effective_irradiance(self, data):
|
|
1911
1908
|
"""
|
|
1912
1909
|
Run the model starting with effective irradiance in the plane of array.
|
|
1913
1910
|
|