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/clearsky.py CHANGED
@@ -9,7 +9,6 @@ import calendar
9
9
 
10
10
  import numpy as np
11
11
  import pandas as pd
12
- from scipy.optimize import minimize_scalar
13
12
  from scipy.linalg import hankel
14
13
  import h5py
15
14
 
@@ -169,6 +168,13 @@ def lookup_linke_turbidity(time, latitude, longitude, filepath=None,
169
168
  Returns
170
169
  -------
171
170
  turbidity : Series
171
+
172
+ Notes
173
+ -----
174
+ Linke turbidity is obtained from a file of historical monthly averages.
175
+ The returned value for each time is either the monthly value or an
176
+ interpolated value to smooth the transition between months.
177
+ Interpolation is done on the day of year as determined by UTC.
172
178
  """
173
179
 
174
180
  # The .h5 file 'LinkeTurbidities.h5' contains a single 2160 x 4320 x 12
@@ -201,7 +207,7 @@ def lookup_linke_turbidity(time, latitude, longitude, filepath=None,
201
207
  if interp_turbidity:
202
208
  linke_turbidity = _interpolate_turbidity(lts, time)
203
209
  else:
204
- months = time.month - 1
210
+ months = tools._pandas_to_utc(time).month - 1
205
211
  linke_turbidity = pd.Series(lts[months], index=time)
206
212
 
207
213
  linke_turbidity /= 20.
@@ -247,14 +253,11 @@ def _interpolate_turbidity(lts, time):
247
253
  # Jan 1 - Jan 15 and Dec 16 - Dec 31.
248
254
  lts_concat = np.concatenate([[lts[-1]], lts, [lts[0]]])
249
255
 
250
- # handle leap years
251
- try:
252
- isleap = time.is_leap_year
253
- except AttributeError:
254
- year = time.year
255
- isleap = _is_leap_year(year)
256
+ time_utc = tools._pandas_to_utc(time)
257
+
258
+ isleap = time_utc.is_leap_year
256
259
 
257
- dayofyear = time.dayofyear
260
+ dayofyear = time_utc.dayofyear
258
261
  days_leap = _calendar_month_middles(2016)
259
262
  days_no_leap = _calendar_month_middles(2015)
260
263
 
@@ -324,13 +327,13 @@ def haurwitz(apparent_zenith):
324
327
  '''
325
328
 
326
329
  cos_zenith = tools.cosd(apparent_zenith.values)
327
- clearsky_ghi = np.zeros_like(apparent_zenith.values)
330
+ ghi_clear = np.zeros_like(apparent_zenith.values)
328
331
  cos_zen_gte_0 = cos_zenith > 0
329
- clearsky_ghi[cos_zen_gte_0] = (1098.0 * cos_zenith[cos_zen_gte_0] *
330
- np.exp(-0.059/cos_zenith[cos_zen_gte_0]))
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]))
331
334
 
332
335
  df_out = pd.DataFrame(index=apparent_zenith.index,
333
- data=clearsky_ghi,
336
+ data=ghi_clear,
334
337
  columns=['ghi'])
335
338
 
336
339
  return df_out
@@ -680,22 +683,26 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
680
683
  var_diff=0.005, slope_dev=8, max_iterations=20,
681
684
  return_components=False):
682
685
  """
683
- Detects clear sky times according to the algorithm developed by Reno
684
- and Hansen for GHI measurements. The algorithm [1]_ was designed and
685
- validated for analyzing GHI time series only. Users may attempt to
686
- apply it to other types of time series data using different filter
687
- settings, but should be skeptical of the results.
686
+ Detects clear sky times using the algorithm developed by Reno
687
+ and Hansen.
688
+
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.
688
692
 
689
- The algorithm detects clear sky times by comparing statistics for a
693
+ The algorithm [1]_ detects clear sky times by comparing statistics for a
690
694
  measured time series and an expected clearsky time series.
691
695
  Statistics are calculated using a sliding time window (e.g., 10
692
696
  minutes). An iterative algorithm identifies clear periods, uses the
693
697
  identified periods to estimate bias in the clearsky data, scales the
694
698
  clearsky data and repeats.
695
699
 
696
- Clear times are identified by meeting 5 criteria. Default values for
700
+ Clear times are identified by meeting five criteria. Default values for
697
701
  these thresholds are appropriate for 10 minute windows of 1 minute
698
- 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``.
699
706
 
700
707
  Parameters
701
708
  ----------
@@ -710,8 +717,8 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
710
717
  If True, does not use passed in kwargs (or defaults), but instead
711
718
  interpolates these values from Table 1 in [2]_.
712
719
  window_length : int, default 10
713
- Length of sliding time window in minutes. Must be greater than 2
714
- periods.
720
+ Length of sliding time window in minutes. Each window must contain at
721
+ least three data points.
715
722
  mean_diff : float, default 75
716
723
  Threshold value for agreement between mean values of measured
717
724
  and clearsky in each interval, see Eq. 6 in [1]. [W/m2]
@@ -720,8 +727,6 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
720
727
  clearsky values in each interval, see Eq. 7 in [1]. [W/m2]
721
728
  lower_line_length : float, default -5
722
729
  Lower limit of line length criterion from Eq. 8 in [1].
723
- Criterion satisfied when lower_line_length < line length difference
724
- < upper_line_length.
725
730
  upper_line_length : float, default 10
726
731
  Upper limit of line length criterion from Eq. 8 in [1].
727
732
  var_diff : float, default 0.005
@@ -733,7 +738,7 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
733
738
  change in successive values, see Eqs. 12 through 14 in [1].
734
739
  max_iterations : int, default 20
735
740
  Maximum number of times to apply a different scaling factor to
736
- the clearsky and redetermine clear_samples. Must be 1 or larger.
741
+ the clearsky and redetermine ``clear_samples``. Must be 1 or larger.
737
742
  return_components : bool, default False
738
743
  Controls if additional output should be returned. See below.
739
744
 
@@ -745,19 +750,23 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
745
750
 
746
751
  components : OrderedDict, optional
747
752
  Dict of arrays of whether or not the given time window is clear
748
- for each condition. Only provided if return_components is True.
753
+ for each condition. Only provided if ``return_components`` is True.
749
754
 
750
755
  alpha : scalar, optional
751
- Scaling factor applied to the clearsky_ghi to obtain the
752
- detected clear_samples. Only provided if return_components is
756
+ Scaling factor applied to ``clearsky`` to obtain the
757
+ detected ``clear_samples``. Only provided if ``return_components`` is
753
758
  True.
754
759
 
755
760
  Raises
756
761
  ------
757
762
  ValueError
758
- 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.
759
768
  NotImplementedError
760
- If timestamps are not equally spaced
769
+ If timestamps are not equally spaced.
761
770
 
762
771
  References
763
772
  ----------
@@ -809,6 +818,13 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
809
818
  sample_interval, samples_per_window = \
810
819
  tools._get_sample_intervals(times, window_length)
811
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
+
812
828
  # if infer_limits, find threshold values using the sample interval
813
829
  if infer_limits:
814
830
  window_length, mean_diff, max_diff, lower_line_length, \
@@ -874,25 +890,11 @@ def detect_clearsky(measured, clearsky, times=None, infer_limits=False,
874
890
  clear_meas = meas[clear_samples]
875
891
  clear_clear = clear[clear_samples]
876
892
 
877
- def rmse(alpha):
878
- return np.sqrt(np.mean((clear_meas - alpha*clear_clear)**2))
879
-
880
- optimize_result = minimize_scalar(rmse)
881
- if not optimize_result.success:
882
- try:
883
- message = "Optimizer exited unsuccessfully: " \
884
- + optimize_result.message
885
- except AttributeError:
886
- message = "Optimizer exited unsuccessfully: \
887
- No message explaining the failure was returned. \
888
- If you would like to see this message, please \
889
- update your scipy version (try version 1.8.0 \
890
- or beyond)."
891
- raise RuntimeError(message)
892
-
893
- else:
894
- alpha = optimize_result.x
895
-
893
+ # Compute arg min of MSE between model and observations
894
+ C = (clear_clear**2).sum()
895
+ if not (pd.isna(C) or C == 0): # safety check
896
+ # only update alpha if C is strictly positive
897
+ alpha = (clear_meas * clear_clear).sum() / C
896
898
  if round(alpha*10000) == round(previous_alpha*10000):
897
899
  break
898
900
  else:
@@ -941,7 +943,7 @@ def bird(zenith, airmass_relative, aod380, aod500, precipitable_water,
941
943
  zenith is never explicitly defined in the report, since the purpose
942
944
  was to compare existing clear sky models with "rigorous radiative
943
945
  transfer models" (RTM) it is possible that apparent zenith was
944
- obtained as output from the RTM. However, the implentation presented
946
+ obtained as output from the RTM. However, the implementation presented
945
947
  in PVLIB is tested against the NREL Excel implementation by Daryl
946
948
  Myers which uses an analytical expression for solar zenith instead
947
949
  of apparent zenith.
@@ -1,93 +1,32 @@
1
- {
2
- "inputs": {
3
- "location": {
4
- "description": "Selected location",
5
- "variables": {
6
- "latitude": {
7
- "description": "Latitude",
8
- "units": "decimal degree"
9
- },
10
- "longitude": {
11
- "description": "Longitude",
12
- "units": "decimal degree"
13
- },
14
- "elevation": {
15
- "description": "Elevation",
16
- "units": "m"
17
- }
18
- }
19
- },
20
- "meteo_data": {
21
- "description": "Sources of meteorological data",
22
- "variables": {
23
- "radiation_db": {
24
- "description": "Solar radiation database"
25
- },
26
- "meteo_db": {
27
- "description": "Database used for meteorological variables other than solar radiation"
28
- },
29
- "year_min": {
30
- "description": "First year of the calculations"
31
- },
32
- "year_max": {
33
- "description": "Last year of the calculations"
34
- },
35
- "use_horizon": {
36
- "description": "Include horizon shadows"
37
- },
38
- "horizon_db": {
39
- "description": "Source of horizon data"
40
- }
41
- }
42
- }
43
- },
44
- "outputs": {
45
- "months_selected": {
46
- "type": "time series",
47
- "timestamp": "monthly",
48
- "description": "months selected for the TMY"
49
- },
50
- "tmy_hourly": {
51
- "type": "time series",
52
- "timestamp": "hourly",
53
- "variables": {
54
- "T2m": {
55
- "description": "2-m air temperature",
56
- "units": "degree Celsius"
57
- },
58
- "RH": {
59
- "description": "relative humidity",
60
- "units": "%"
61
- },
62
- "G(h)": {
63
- "description": "Global irradiance on the horizontal plane",
64
- "units": "W/m2"
65
- },
66
- "Gb(n)": {
67
- "description": "Beam/direct irradiance on a plane always normal to sun rays",
68
- "units": "W/m2"
69
- },
70
- "Gd(h)": {
71
- "description": "Diffuse irradiance on the horizontal plane",
72
- "units": "W/m2"
73
- },
74
- "IR(h)": {
75
- "description": "Surface infrared (thermal) irradiance on a horizontal plane",
76
- "units": "W/m2"
77
- },
78
- "WS10m": {
79
- "description": "10-m total wind speed",
80
- "units": "m/s"
81
- },
82
- "WD10m": {
83
- "description": "10-m wind direction (0 = N, 90 = E)",
84
- "units": "degree"
85
- },
86
- "SP": {
87
- "description": "Surface (air) pressure",
88
- "units": "Pa"
89
- }
90
- }
91
- }
92
- }
93
- }
1
+ {"inputs": {"location": {"description": "Selected location",
2
+ "variables": {"latitude": {"description": "Latitude",
3
+ "units": "decimal degree"},
4
+ "longitude": {"description": "Longitude", "units": "decimal degree"},
5
+ "elevation": {"description": "Elevation", "units": "m"}}},
6
+ "meteo_data": {"description": "Sources of meteorological data",
7
+ "variables": {"radiation_db": {"description": "Solar radiation database"},
8
+ "meteo_db": {"description": "Database used for meteorological variables other than solar radiation"},
9
+ "year_min": {"description": "First year of the calculations"},
10
+ "year_max": {"description": "Last year of the calculations"},
11
+ "use_horizon": {"description": "Include horizon shadows"},
12
+ "horizon_db": {"description": "Source of horizon data"}}}},
13
+ "outputs": {"months_selected": {"type": "time series",
14
+ "timestamp": "monthly",
15
+ "description": "months selected for the TMY"},
16
+ "tmy_hourly": {"type": "time series",
17
+ "timestamp": "hourly",
18
+ "variables": {"T2m": {"description": "2-m air temperature",
19
+ "units": "degree Celsius"},
20
+ "RH": {"description": "relative humidity", "units": "%"},
21
+ "G(h)": {"description": "Global irradiance on the horizontal plane",
22
+ "units": "W/m2"},
23
+ "Gb(n)": {"description": "Beam/direct irradiance on a plane always normal to sun rays",
24
+ "units": "W/m2"},
25
+ "Gd(h)": {"description": "Diffuse irradiance on the horizontal plane",
26
+ "units": "W/m2"},
27
+ "IR(h)": {"description": "Surface infrared (thermal) irradiance on a horizontal plane",
28
+ "units": "W/m2"},
29
+ "WS10m": {"description": "10-m total wind speed", "units": "m/s"},
30
+ "WD10m": {"description": "10-m wind direction (0 = N, 90 = E)",
31
+ "units": "degree"},
32
+ "SP": {"description": "Surface (air) pressure", "units": "Pa"}}}}}