pvlib 0.11.0a1__py3-none-any.whl → 0.11.2__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 (62) hide show
  1. pvlib/_deprecation.py +73 -0
  2. pvlib/atmosphere.py +236 -1
  3. pvlib/bifacial/__init__.py +4 -4
  4. pvlib/bifacial/loss_models.py +163 -0
  5. pvlib/clearsky.py +53 -51
  6. pvlib/data/pvgis_tmy_meta.json +32 -93
  7. pvlib/data/pvgis_tmy_test.csv +8761 -0
  8. pvlib/data/tmy_45.000_8.000_2005_2023.csv +8789 -0
  9. pvlib/data/tmy_45.000_8.000_2005_2023.epw +8768 -0
  10. pvlib/data/tmy_45.000_8.000_2005_2023.json +1 -0
  11. pvlib/data/tmy_45.000_8.000_2005_2023.txt +8761 -0
  12. pvlib/data/tmy_45.000_8.000_userhorizon.json +1 -1
  13. pvlib/iam.py +4 -4
  14. pvlib/iotools/midc.py +1 -1
  15. pvlib/iotools/pvgis.py +39 -13
  16. pvlib/irradiance.py +237 -173
  17. pvlib/ivtools/sdm.py +75 -52
  18. pvlib/location.py +5 -5
  19. pvlib/modelchain.py +1 -1
  20. pvlib/pvsystem.py +134 -86
  21. pvlib/shading.py +8 -8
  22. pvlib/singlediode.py +1 -1
  23. pvlib/solarposition.py +101 -80
  24. pvlib/spa.py +28 -24
  25. pvlib/spectrum/__init__.py +9 -4
  26. pvlib/spectrum/irradiance.py +273 -0
  27. pvlib/spectrum/mismatch.py +118 -508
  28. pvlib/spectrum/response.py +280 -0
  29. pvlib/spectrum/spectrl2.py +18 -17
  30. pvlib/temperature.py +49 -3
  31. pvlib/tests/bifacial/test_losses_models.py +54 -0
  32. pvlib/tests/iotools/test_pvgis.py +58 -12
  33. pvlib/tests/ivtools/test_sdm.py +23 -1
  34. pvlib/tests/spectrum/__init__.py +0 -0
  35. pvlib/tests/spectrum/conftest.py +40 -0
  36. pvlib/tests/spectrum/test_irradiance.py +138 -0
  37. pvlib/tests/{test_spectrum.py → spectrum/test_mismatch.py} +32 -306
  38. pvlib/tests/spectrum/test_response.py +124 -0
  39. pvlib/tests/spectrum/test_spectrl2.py +72 -0
  40. pvlib/tests/test__deprecation.py +97 -0
  41. pvlib/tests/test_atmosphere.py +218 -0
  42. pvlib/tests/test_clearsky.py +44 -26
  43. pvlib/tests/test_conftest.py +0 -44
  44. pvlib/tests/test_irradiance.py +62 -16
  45. pvlib/tests/test_pvsystem.py +17 -1
  46. pvlib/tests/test_solarposition.py +117 -36
  47. pvlib/tests/test_spa.py +30 -1
  48. pvlib/tools.py +26 -2
  49. pvlib/tracking.py +53 -47
  50. {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/METADATA +34 -31
  51. {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/RECORD +55 -47
  52. {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/WHEEL +1 -1
  53. pvlib/data/aod550_tcwv_20121101_test.nc +0 -0
  54. pvlib/data/pvgis_tmy_test.dat +0 -8761
  55. pvlib/data/tmy_45.000_8.000_2005_2016.csv +0 -8789
  56. pvlib/data/tmy_45.000_8.000_2005_2016.epw +0 -8768
  57. pvlib/data/tmy_45.000_8.000_2005_2016.json +0 -1
  58. pvlib/data/tmy_45.000_8.000_2005_2016.txt +0 -8761
  59. pvlib/data/variables_style_rules.csv +0 -55
  60. {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/AUTHORS.md +0 -0
  61. {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/LICENSE +0 -0
  62. {pvlib-0.11.0a1.dist-info → pvlib-0.11.2.dist-info}/top_level.txt +0 -0
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, and IAM = 0 at AOI = 90. This equation is only valid for
273
- -90 <= aoi <= 90, therefore `iam` is constrained to 0.0 outside this
272
+ at AOI = 0°, and IAM = 0 at AOI = 90°. This equation is only valid for
273
+ <= 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 numerically
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:`variables_style_rules`.
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/pvgis.py CHANGED
@@ -18,10 +18,10 @@ import io
18
18
  import json
19
19
  from pathlib import Path
20
20
  import requests
21
+ import numpy as np
21
22
  import pandas as pd
23
+ import pytz
22
24
  from pvlib.iotools import read_epw, parse_epw
23
- import warnings
24
- from pvlib._deprecation import pvlibDeprecationWarning
25
25
 
26
26
  URL = 'https://re.jrc.ec.europa.eu/api/'
27
27
 
@@ -390,9 +390,33 @@ def read_pvgis_hourly(filename, pvgis_format=None, map_variables=True):
390
390
  raise ValueError(err_msg)
391
391
 
392
392
 
393
+ def _coerce_and_roll_tmy(tmy_data, tz, year):
394
+ """
395
+ Assumes ``tmy_data`` input is UTC, converts from UTC to ``tz``, rolls
396
+ dataframe so timeseries starts at midnight, and forces all indices to
397
+ ``year``. Only works for integer ``tz``, but ``None`` and ``False`` are
398
+ re-interpreted as zero / UTC.
399
+ """
400
+ if tz:
401
+ tzname = pytz.timezone(f'Etc/GMT{-tz:+d}')
402
+ else:
403
+ tz = 0
404
+ tzname = pytz.timezone('UTC')
405
+ new_index = pd.DatetimeIndex([
406
+ timestamp.replace(year=year, tzinfo=tzname)
407
+ for timestamp in tmy_data.index],
408
+ name=f'time({tzname})')
409
+ new_tmy_data = pd.DataFrame(
410
+ np.roll(tmy_data, tz, axis=0),
411
+ columns=tmy_data.columns,
412
+ index=new_index)
413
+ return new_tmy_data
414
+
415
+
393
416
  def get_pvgis_tmy(latitude, longitude, outputformat='json', usehorizon=True,
394
417
  userhorizon=None, startyear=None, endyear=None,
395
- map_variables=True, url=URL, timeout=30):
418
+ map_variables=True, url=URL, timeout=30,
419
+ roll_utc_offset=None, coerce_year=None):
396
420
  """
397
421
  Get TMY data from PVGIS.
398
422
 
@@ -424,6 +448,13 @@ def get_pvgis_tmy(latitude, longitude, outputformat='json', usehorizon=True,
424
448
  base url of PVGIS API, append ``tmy`` to get TMY endpoint
425
449
  timeout : int, default 30
426
450
  time in seconds to wait for server response before timeout
451
+ roll_utc_offset: int, optional
452
+ Use to specify a time zone other than the default UTC zero and roll
453
+ dataframe by ``roll_utc_offset`` so it starts at midnight on January
454
+ 1st. Ignored if ``None``, otherwise will force year to ``coerce_year``.
455
+ coerce_year: int, optional
456
+ Use to force indices to desired year. Will default to 1990 if
457
+ ``coerce_year`` is not specified, but ``roll_utc_offset`` is specified.
427
458
 
428
459
  Returns
429
460
  -------
@@ -436,16 +467,6 @@ def get_pvgis_tmy(latitude, longitude, outputformat='json', usehorizon=True,
436
467
  metadata : list or dict
437
468
  file metadata, ``None`` for basic
438
469
 
439
- Note
440
- ----
441
- The PVGIS website uses 10 years of data to generate the TMY, whereas the
442
- API accessed by this function defaults to using all available years. This
443
- means that the TMY returned by this function may not be identical to the
444
- one generated by the website. To replicate the website requests, specify
445
- the corresponding 10 year period using ``startyear`` and ``endyear``.
446
- Specifying ``endyear`` also avoids the TMY changing when new data becomes
447
- available.
448
-
449
470
  Raises
450
471
  ------
451
472
  requests.HTTPError
@@ -510,6 +531,11 @@ def get_pvgis_tmy(latitude, longitude, outputformat='json', usehorizon=True,
510
531
  if map_variables:
511
532
  data = data.rename(columns=VARIABLE_MAP)
512
533
 
534
+ if not (roll_utc_offset is None and coerce_year is None):
535
+ # roll_utc_offset is specified, but coerce_year isn't
536
+ coerce_year = coerce_year or 1990
537
+ data = _coerce_and_roll_tmy(data, roll_utc_offset, coerce_year)
538
+
513
539
  return data, months_selected, inputs, meta
514
540
 
515
541