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.
Files changed (71) hide show
  1. pvlib/__init__.py +3 -2
  2. pvlib/atmosphere.py +6 -171
  3. pvlib/bifacial/infinite_sheds.py +30 -267
  4. pvlib/bifacial/utils.py +225 -5
  5. pvlib/data/test_psm3_2017.csv +17521 -17521
  6. pvlib/data/test_read_psm3.csv +17522 -17522
  7. pvlib/data/test_read_pvgis_horizon.csv +49 -0
  8. pvlib/data/variables_style_rules.csv +3 -0
  9. pvlib/iam.py +17 -4
  10. pvlib/inverter.py +6 -1
  11. pvlib/iotools/__init__.py +7 -2
  12. pvlib/iotools/acis.py +516 -0
  13. pvlib/iotools/midc.py +4 -4
  14. pvlib/iotools/psm3.py +32 -31
  15. pvlib/iotools/pvgis.py +84 -28
  16. pvlib/iotools/sodapro.py +8 -6
  17. pvlib/iotools/srml.py +121 -18
  18. pvlib/iotools/surfrad.py +2 -2
  19. pvlib/iotools/tmy.py +146 -102
  20. pvlib/irradiance.py +151 -0
  21. pvlib/ivtools/sde.py +11 -7
  22. pvlib/ivtools/sdm.py +16 -10
  23. pvlib/ivtools/utils.py +6 -6
  24. pvlib/location.py +3 -2
  25. pvlib/modelchain.py +67 -70
  26. pvlib/pvsystem.py +160 -532
  27. pvlib/shading.py +41 -0
  28. pvlib/singlediode.py +215 -65
  29. pvlib/soiling.py +3 -3
  30. pvlib/spa.py +327 -368
  31. pvlib/spectrum/__init__.py +8 -2
  32. pvlib/spectrum/mismatch.py +335 -0
  33. pvlib/temperature.py +1 -8
  34. pvlib/tests/bifacial/test_infinite_sheds.py +0 -111
  35. pvlib/tests/bifacial/test_utils.py +101 -4
  36. pvlib/tests/conftest.py +0 -31
  37. pvlib/tests/iotools/test_acis.py +213 -0
  38. pvlib/tests/iotools/test_midc.py +6 -6
  39. pvlib/tests/iotools/test_psm3.py +3 -3
  40. pvlib/tests/iotools/test_pvgis.py +21 -14
  41. pvlib/tests/iotools/test_sodapro.py +1 -1
  42. pvlib/tests/iotools/test_srml.py +71 -6
  43. pvlib/tests/iotools/test_tmy.py +43 -8
  44. pvlib/tests/ivtools/test_sde.py +19 -17
  45. pvlib/tests/ivtools/test_sdm.py +9 -4
  46. pvlib/tests/test_atmosphere.py +6 -62
  47. pvlib/tests/test_iam.py +12 -0
  48. pvlib/tests/test_irradiance.py +40 -2
  49. pvlib/tests/test_location.py +1 -1
  50. pvlib/tests/test_modelchain.py +33 -76
  51. pvlib/tests/test_pvsystem.py +366 -201
  52. pvlib/tests/test_shading.py +28 -0
  53. pvlib/tests/test_singlediode.py +166 -30
  54. pvlib/tests/test_soiling.py +8 -7
  55. pvlib/tests/test_spa.py +6 -7
  56. pvlib/tests/test_spectrum.py +145 -1
  57. pvlib/tests/test_temperature.py +0 -7
  58. pvlib/tests/test_tools.py +25 -0
  59. pvlib/tests/test_tracking.py +0 -149
  60. pvlib/tools.py +26 -1
  61. pvlib/tracking.py +1 -269
  62. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/METADATA +1 -9
  63. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/RECORD +67 -68
  64. pvlib/forecast.py +0 -1211
  65. pvlib/iotools/ecmwf_macc.py +0 -312
  66. pvlib/tests/iotools/test_ecmwf_macc.py +0 -162
  67. pvlib/tests/test_forecast.py +0 -228
  68. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/AUTHORS.md +0 -0
  69. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/LICENSE +0 -0
  70. {pvlib-0.9.5.dist-info → pvlib-0.10.0.dist-info}/WHEEL +0 -0
  71. {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
- * 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.
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 are passed to the relevant functions. See
335
- solarposition.sun_rise_set_transit_<method> for details.
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, tools)
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(pac0=4000)
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}: {getmcattr(self, attr)}' for attr in attrs))
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
- # PVSystem.get_irradiance and SingleAxisTracker.get_irradiance
1540
- # and PVSystem.get_aoi and SingleAxisTracker.get_aoi
1541
- # have different method signatures. Use partial to handle
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
- if isinstance(self.system, SingleAxisTracker):
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=None):
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, default None
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=None):
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, default None
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=None):
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