pvlib 0.9.4a1__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 (86) hide show
  1. pvlib/__init__.py +3 -2
  2. pvlib/atmosphere.py +23 -173
  3. pvlib/bifacial/infinite_sheds.py +88 -277
  4. pvlib/bifacial/utils.py +270 -28
  5. pvlib/data/adr-library-cec-inverters-2019-03-05.csv +5009 -0
  6. pvlib/data/precise_iv_curves1.json +10251 -0
  7. pvlib/data/precise_iv_curves2.json +10251 -0
  8. pvlib/data/precise_iv_curves_parameter_sets1.csv +33 -0
  9. pvlib/data/precise_iv_curves_parameter_sets2.csv +33 -0
  10. pvlib/data/test_psm3_2017.csv +17521 -17521
  11. pvlib/data/test_psm3_2019_5min.csv +288 -288
  12. pvlib/data/test_read_psm3.csv +17522 -17522
  13. pvlib/data/test_read_pvgis_horizon.csv +49 -0
  14. pvlib/data/variables_style_rules.csv +3 -0
  15. pvlib/iam.py +207 -51
  16. pvlib/inverter.py +6 -1
  17. pvlib/iotools/__init__.py +7 -2
  18. pvlib/iotools/acis.py +516 -0
  19. pvlib/iotools/midc.py +4 -4
  20. pvlib/iotools/psm3.py +59 -42
  21. pvlib/iotools/pvgis.py +84 -28
  22. pvlib/iotools/sodapro.py +8 -6
  23. pvlib/iotools/srml.py +121 -18
  24. pvlib/iotools/surfrad.py +2 -2
  25. pvlib/iotools/tmy.py +146 -102
  26. pvlib/irradiance.py +270 -15
  27. pvlib/ivtools/sde.py +14 -20
  28. pvlib/ivtools/sdm.py +31 -20
  29. pvlib/ivtools/utils.py +127 -6
  30. pvlib/location.py +3 -2
  31. pvlib/modelchain.py +67 -70
  32. pvlib/pvarray.py +225 -0
  33. pvlib/pvsystem.py +169 -539
  34. pvlib/shading.py +43 -2
  35. pvlib/singlediode.py +216 -66
  36. pvlib/snow.py +36 -15
  37. pvlib/soiling.py +3 -3
  38. pvlib/spa.py +327 -368
  39. pvlib/spectrum/__init__.py +8 -2
  40. pvlib/spectrum/mismatch.py +335 -0
  41. pvlib/temperature.py +124 -13
  42. pvlib/tests/bifacial/test_infinite_sheds.py +44 -106
  43. pvlib/tests/bifacial/test_utils.py +102 -5
  44. pvlib/tests/conftest.py +0 -31
  45. pvlib/tests/iotools/test_acis.py +213 -0
  46. pvlib/tests/iotools/test_midc.py +6 -6
  47. pvlib/tests/iotools/test_psm3.py +7 -5
  48. pvlib/tests/iotools/test_pvgis.py +21 -14
  49. pvlib/tests/iotools/test_sodapro.py +1 -1
  50. pvlib/tests/iotools/test_srml.py +71 -6
  51. pvlib/tests/iotools/test_tmy.py +43 -8
  52. pvlib/tests/ivtools/test_sde.py +19 -17
  53. pvlib/tests/ivtools/test_sdm.py +9 -4
  54. pvlib/tests/ivtools/test_utils.py +96 -1
  55. pvlib/tests/test_atmosphere.py +8 -64
  56. pvlib/tests/test_clearsky.py +0 -1
  57. pvlib/tests/test_iam.py +74 -1
  58. pvlib/tests/test_irradiance.py +56 -2
  59. pvlib/tests/test_location.py +1 -1
  60. pvlib/tests/test_modelchain.py +33 -76
  61. pvlib/tests/test_pvarray.py +46 -0
  62. pvlib/tests/test_pvsystem.py +366 -201
  63. pvlib/tests/test_shading.py +35 -0
  64. pvlib/tests/test_singlediode.py +306 -29
  65. pvlib/tests/test_snow.py +84 -1
  66. pvlib/tests/test_soiling.py +8 -7
  67. pvlib/tests/test_solarposition.py +7 -7
  68. pvlib/tests/test_spa.py +6 -7
  69. pvlib/tests/test_spectrum.py +145 -1
  70. pvlib/tests/test_temperature.py +29 -11
  71. pvlib/tests/test_tools.py +41 -0
  72. pvlib/tests/test_tracking.py +0 -149
  73. pvlib/tools.py +49 -25
  74. pvlib/tracking.py +1 -269
  75. pvlib-0.10.0.dist-info/AUTHORS.md +35 -0
  76. {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/LICENSE +5 -2
  77. {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/METADATA +3 -13
  78. {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/RECORD +80 -75
  79. {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/WHEEL +1 -1
  80. pvlib/data/adr-library-2013-10-01.csv +0 -1762
  81. pvlib/forecast.py +0 -1211
  82. pvlib/iotools/ecmwf_macc.py +0 -312
  83. pvlib/tests/iotools/test_ecmwf_macc.py +0 -162
  84. pvlib/tests/test_forecast.py +0 -228
  85. pvlib-0.9.4a1.dist-info/AUTHORS.md +0 -32
  86. {pvlib-0.9.4a1.dist-info → pvlib-0.10.0.dist-info}/top_level.txt +0 -0
pvlib/iotools/tmy.py CHANGED
@@ -3,9 +3,29 @@
3
3
  import datetime
4
4
  import re
5
5
  import pandas as pd
6
-
7
-
8
- def read_tmy3(filename, coerce_year=None, recolumn=True):
6
+ import warnings
7
+ from pvlib._deprecation import pvlibDeprecationWarning
8
+
9
+ # Dictionary mapping TMY3 names to pvlib names
10
+ VARIABLE_MAP = {
11
+ 'GHI (W/m^2)': 'ghi',
12
+ 'ETR (W/m^2)': 'ghi_extra',
13
+ 'DNI (W/m^2)': 'dni',
14
+ 'ETRN (W/m^2)': 'dni_extra',
15
+ 'DHI (W/m^2)': 'dhi',
16
+ 'Pressure (mbar)': 'pressure',
17
+ 'Wdir (degrees)': 'wind_direction',
18
+ 'Wspd (m/s)': 'wind_speed',
19
+ 'Dry-bulb (C)': 'temp_air',
20
+ 'Dew-point (C)': 'temp_dew',
21
+ 'RHum (%)': 'relative_humidity',
22
+ 'Alb (unitless)': 'albedo',
23
+ 'Pwat (cm)': 'precipitable_water'
24
+ }
25
+
26
+
27
+ def read_tmy3(filename, coerce_year=None, map_variables=None, recolumn=None,
28
+ encoding=None):
9
29
  """Read a TMY3 file into a pandas dataframe.
10
30
 
11
31
  Note that values contained in the metadata dictionary are unchanged
@@ -24,9 +44,18 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
24
44
  If supplied, the year of the index will be set to `coerce_year`, except
25
45
  for the last index value which will be set to the *next* year so that
26
46
  the index increases monotonically.
27
- recolumn : bool, default True
47
+ map_variables : bool, default None
48
+ When True, renames columns of the DataFrame to pvlib variable names
49
+ where applicable. See variable :const:`VARIABLE_MAP`.
50
+ recolumn : bool (deprecated, use map_variables instead)
28
51
  If ``True``, apply standard names to TMY3 columns. Typically this
29
52
  results in stripping the units from the column name.
53
+ Cannot be used in combination with ``map_variables``.
54
+ encoding : str, optional
55
+ Encoding of the file. For files that contain non-UTF8 characters it may
56
+ be necessary to specify an alternative encoding, e.g., for
57
+ SolarAnywhere TMY3 files the encoding should be 'iso-8859-1'. Users
58
+ may also consider using the 'utf-8-sig' encoding.
30
59
 
31
60
  Returns
32
61
  -------
@@ -35,7 +64,7 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
35
64
  data : DataFrame
36
65
  A pandas dataframe with the columns described in the table
37
66
  below. For more detailed descriptions of each component, please
38
- consult the TMY3 User's Manual ([1]_), especially tables 1-1
67
+ consult the TMY3 User's Manual [1]_, especially tables 1-1
39
68
  through 1-6.
40
69
 
41
70
  metadata : dict
@@ -57,80 +86,83 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
57
86
  USAF Int USAF identifier
58
87
  =============== ====== ===================
59
88
 
60
- ===================== ======================================================================================================================================================
61
- field description
62
- ===================== ======================================================================================================================================================
63
- Index A pandas datetime index. NOTE, the index is timezone aware, and times are set to local standard time (daylight savings is not included)
64
- ETR Extraterrestrial horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
65
- ETRN Extraterrestrial normal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
66
- GHI Direct and diffuse horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
67
- GHISource See [1]_, Table 1-4
68
- GHIUncertainty Uncertainty based on random and bias error estimates see [2]_
69
- DNI Amount of direct normal radiation (modeled) recv'd during 60 mintues prior to timestamp, Wh/m^2
70
- DNISource See [1]_, Table 1-4
71
- DNIUncertainty Uncertainty based on random and bias error estimates see [2]_
72
- DHI Amount of diffuse horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
73
- DHISource See [1]_, Table 1-4
74
- DHIUncertainty Uncertainty based on random and bias error estimates see [2]_
75
- GHillum Avg. total horizontal illuminance recv'd during the 60 minutes prior to timestamp, lx
76
- GHillumSource See [1]_, Table 1-4
77
- GHillumUncertainty Uncertainty based on random and bias error estimates see [2]_
78
- DNillum Avg. direct normal illuminance recv'd during the 60 minutes prior to timestamp, lx
79
- DNillumSource See [1]_, Table 1-4
80
- DNillumUncertainty Uncertainty based on random and bias error estimates see [2]_
81
- DHillum Avg. horizontal diffuse illuminance recv'd during the 60 minutes prior to timestamp, lx
82
- DHillumSource See [1]_, Table 1-4
83
- DHillumUncertainty Uncertainty based on random and bias error estimates see [2]_
84
- Zenithlum Avg. luminance at the sky's zenith during the 60 minutes prior to timestamp, cd/m^2
85
- ZenithlumSource See [1]_, Table 1-4
86
- ZenithlumUncertainty Uncertainty based on random and bias error estimates see [1]_ section 2.10
87
- TotCld Amount of sky dome covered by clouds or obscuring phenonema at time stamp, tenths of sky
88
- TotCldSource See [1]_, Table 1-5
89
- TotCldUncertainty See [1]_, Table 1-6
90
- OpqCld Amount of sky dome covered by clouds or obscuring phenonema that prevent observing the sky at time stamp, tenths of sky
91
- OpqCldSource See [1]_, Table 1-5
92
- OpqCldUncertainty See [1]_, Table 1-6
93
- DryBulb Dry bulb temperature at the time indicated, deg C
94
- DryBulbSource See [1]_, Table 1-5
95
- DryBulbUncertainty See [1]_, Table 1-6
96
- DewPoint Dew-point temperature at the time indicated, deg C
97
- DewPointSource See [1]_, Table 1-5
98
- DewPointUncertainty See [1]_, Table 1-6
99
- RHum Relatitudeive humidity at the time indicated, percent
100
- RHumSource See [1]_, Table 1-5
101
- RHumUncertainty See [1]_, Table 1-6
102
- Pressure Station pressure at the time indicated, 1 mbar
103
- PressureSource See [1]_, Table 1-5
104
- PressureUncertainty See [1]_, Table 1-6
105
- Wdir Wind direction at time indicated, degrees from north (360 = north; 0 = undefined,calm)
106
- WdirSource See [1]_, Table 1-5
107
- WdirUncertainty See [1]_, Table 1-6
108
- Wspd Wind speed at the time indicated, meter/second
109
- WspdSource See [1]_, Table 1-5
110
- WspdUncertainty See [1]_, Table 1-6
111
- Hvis Distance to discernable remote objects at time indicated (7777=unlimited), meter
112
- HvisSource See [1]_, Table 1-5
113
- HvisUncertainty See [1]_, Table 1-6
114
- CeilHgt Height of cloud base above local terrain (7777=unlimited), meter
115
- CeilHgtSource See [1]_, Table 1-5
116
- CeilHgtUncertainty See [1]_, Table 1-6
117
- Pwat Total precipitable water contained in a column of unit cross section from earth to top of atmosphere, cm
118
- PwatSource See [1]_, Table 1-5
119
- PwatUncertainty See [1]_, Table 1-6
120
- AOD The broadband aerosol optical depth per unit of air mass due to extinction by aerosol component of atmosphere, unitless
121
- AODSource See [1]_, Table 1-5
122
- AODUncertainty See [1]_, Table 1-6
123
- Alb The ratio of reflected solar irradiance to global horizontal irradiance, unitless
124
- AlbSource See [1]_, Table 1-5
125
- AlbUncertainty See [1]_, Table 1-6
126
- Lprecipdepth The amount of liquid precipitation observed at indicated time for the period indicated in the liquid precipitation quantity field, millimeter
127
- Lprecipquantity The period of accumulatitudeion for the liquid precipitation depth field, hour
128
- LprecipSource See [1]_, Table 1-5
129
- LprecipUncertainty See [1]_, Table 1-6
130
- PresWth Present weather code, see [2]_.
131
- PresWthSource Present weather code source, see [2]_.
132
- PresWthUncertainty Present weather code uncertainty, see [2]_.
133
- ===================== ======================================================================================================================================================
89
+
90
+ ======================== ======================================================================================================================================================
91
+ field description
92
+ ======================== ======================================================================================================================================================
93
+ **† denotes variables that are mapped when `map_variables` is True**
94
+ -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
95
+ Index A pandas datetime index. NOTE, the index is timezone aware, and times are set to local standard time (daylight savings is not included)
96
+ ghi_extra† Extraterrestrial horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
97
+ dni_extra† Extraterrestrial normal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
98
+ ghi† Direct and diffuse horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
99
+ GHI source See [1]_, Table 1-4
100
+ GHI uncert (%) Uncertainty based on random and bias error estimates see [2]_
101
+ dni† Amount of direct normal radiation (modeled) recv'd during 60 mintues prior to timestamp, Wh/m^2
102
+ DNI source See [1]_, Table 1-4
103
+ DNI uncert (%) Uncertainty based on random and bias error estimates see [2]_
104
+ dhi† Amount of diffuse horizontal radiation recv'd during 60 minutes prior to timestamp, Wh/m^2
105
+ DHI source See [1]_, Table 1-4
106
+ DHI uncert (%) Uncertainty based on random and bias error estimates see [2]_
107
+ GH illum (lx) Avg. total horizontal illuminance recv'd during the 60 minutes prior to timestamp, lx
108
+ GH illum source See [1]_, Table 1-4
109
+ GH illum uncert (%) Uncertainty based on random and bias error estimates see [2]_
110
+ DN illum (lx) Avg. direct normal illuminance recv'd during the 60 minutes prior to timestamp, lx
111
+ DN illum source See [1]_, Table 1-4
112
+ DN illum uncert (%) Uncertainty based on random and bias error estimates see [2]_
113
+ DH illum (lx) Avg. horizontal diffuse illuminance recv'd during the 60 minutes prior to timestamp, lx
114
+ DH illum source See [1]_, Table 1-4
115
+ DH illum uncert (%) Uncertainty based on random and bias error estimates see [2]_
116
+ Zenith lum (cd/m^2) Avg. luminance at the sky's zenith during the 60 minutes prior to timestamp, cd/m^2
117
+ Zenith lum source See [1]_, Table 1-4
118
+ Zenith lum uncert (%) Uncertainty based on random and bias error estimates see [1]_ section 2.10
119
+ TotCld (tenths) Amount of sky dome covered by clouds or obscuring phenonema at time stamp, tenths of sky
120
+ TotCld source See [1]_, Table 1-5
121
+ TotCld uncert (code) See [1]_, Table 1-6
122
+ OpqCld (tenths) Amount of sky dome covered by clouds or obscuring phenonema that prevent observing the sky at time stamp, tenths of sky
123
+ OpqCld source See [1]_, Table 1-5
124
+ OpqCld uncert (code) See [1]_, Table 1-6
125
+ temp_air† Dry bulb temperature at the time indicated, deg C
126
+ Dry-bulb source See [1]_, Table 1-5
127
+ Dry-bulb uncert (code) See [1]_, Table 1-6
128
+ temp_dew† Dew-point temperature at the time indicated, deg C
129
+ Dew-point source See [1]_, Table 1-5
130
+ Dew-point uncert (code) See [1]_, Table 1-6
131
+ relative_humidity† Relatitudeive humidity at the time indicated, percent
132
+ RHum source See [1]_, Table 1-5
133
+ RHum uncert (code) See [1]_, Table 1-6
134
+ pressure† Station pressure at the time indicated, 1 mbar
135
+ Pressure source See [1]_, Table 1-5
136
+ Pressure uncert (code) See [1]_, Table 1-6
137
+ wind_direction† Wind direction at time indicated, degrees from north (360 = north; 0 = undefined,calm)
138
+ Wdir source See [1]_, Table 1-5
139
+ Wdir uncert (code) See [1]_, Table 1-6
140
+ wind_speed† Wind speed at the time indicated, meter/second
141
+ Wspd source See [1]_, Table 1-5
142
+ Wspd uncert (code) See [1]_, Table 1-6
143
+ Hvis (m) Distance to discernable remote objects at time indicated (7777=unlimited), meter
144
+ Hvis source See [1]_, Table 1-5
145
+ Hvis uncert (coe) See [1]_, Table 1-6
146
+ CeilHgt (m) Height of cloud base above local terrain (7777=unlimited), meter
147
+ CeilHgt source See [1]_, Table 1-5
148
+ CeilHgt uncert (code) See [1]_, Table 1-6
149
+ precipitable_water† Total precipitable water contained in a column of unit cross section from earth to top of atmosphere, cm
150
+ Pwat source See [1]_, Table 1-5
151
+ Pwat uncert (code) See [1]_, Table 1-6
152
+ AOD The broadband aerosol optical depth per unit of air mass due to extinction by aerosol component of atmosphere, unitless
153
+ AOD source See [1]_, Table 1-5
154
+ AOD uncert (code) See [1]_, Table 1-6
155
+ albedo† The ratio of reflected solar irradiance to global horizontal irradiance, unitless
156
+ Alb source See [1]_, Table 1-5
157
+ Alb uncert (code) See [1]_, Table 1-6
158
+ Lprecip depth (mm) The amount of liquid precipitation observed at indicated time for the period indicated in the liquid precipitation quantity field, millimeter
159
+ Lprecip quantity (hr) The period of accumulatitudeion for the liquid precipitation depth field, hour
160
+ Lprecip source See [1]_, Table 1-5
161
+ Lprecip uncert (code) See [1]_, Table 1-6
162
+ PresWth (METAR code) Present weather code, see [2]_.
163
+ PresWth source Present weather code source, see [2]_.
164
+ PresWth uncert (code) Present weather code uncertainty, see [2]_.
165
+ ======================== ======================================================================================================================================================
134
166
 
135
167
  .. admonition:: Midnight representation
136
168
 
@@ -152,21 +184,21 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
152
184
  ----------
153
185
  .. [1] Wilcox, S and Marion, W. "Users Manual for TMY3 Data Sets".
154
186
  NREL/TP-581-43156, Revised May 2008.
187
+ :doi:`10.2172/928611`
155
188
  .. [2] Wilcox, S. (2007). National Solar Radiation Database 1991 2005
156
189
  Update: Users Manual. 472 pp.; NREL Report No. TP-581-41364.
190
+ :doi:`10.2172/901864`
157
191
  .. [3] `SolarAnywhere file formats
158
192
  <https://www.solaranywhere.com/support/historical-data/file-formats/>`_
159
193
  """ # noqa: E501
160
194
  head = ['USAF', 'Name', 'State', 'TZ', 'latitude', 'longitude', 'altitude']
161
195
 
162
- try:
163
- with open(str(filename), 'r') as fbuf:
164
- firstline, data = _parse_tmy3(fbuf)
165
- # SolarAnywhere files contain non-UTF8 characters and may require
166
- # encoding='iso-8859-1' in order to be parsed
167
- except UnicodeDecodeError:
168
- with open(str(filename), 'r', encoding='iso-8859-1') as fbuf:
169
- firstline, data = _parse_tmy3(fbuf)
196
+ with open(str(filename), 'r', encoding=encoding) as fbuf:
197
+ # header information on the 1st line (0 indexing)
198
+ firstline = fbuf.readline()
199
+ # use pandas to read the csv file buffer
200
+ # header is actually the second line, but tell pandas to look for
201
+ data = pd.read_csv(fbuf, header=0)
170
202
 
171
203
  meta = dict(zip(head, firstline.rstrip('\n').split(",")))
172
204
  # convert metadata strings to numeric types
@@ -178,8 +210,10 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
178
210
 
179
211
  # get the date column as a pd.Series of numpy datetime64
180
212
  data_ymd = pd.to_datetime(data['Date (MM/DD/YYYY)'], format='%m/%d/%Y')
213
+ # extract minutes
214
+ minutes = data['Time (HH:MM)'].str.split(':').str[1].astype(int)
181
215
  # shift the time column so that midnite is 00:00 instead of 24:00
182
- shifted_hour = data['Time (HH:MM)'].str[:2].astype(int) % 24
216
+ shifted_hour = data['Time (HH:MM)'].str.split(':').str[0].astype(int) % 24
183
217
  # shift the dates at midnight (24:00) so they correspond to the next day.
184
218
  # If midnight is specified as 00:00 do not shift date.
185
219
  data_ymd[data['Time (HH:MM)'].str[:2] == '24'] += datetime.timedelta(days=1) # noqa: E501
@@ -197,25 +231,34 @@ def read_tmy3(filename, coerce_year=None, recolumn=True):
197
231
  data_ymd.iloc[-1] = data_ymd.iloc[-1].replace(year=coerce_year+1)
198
232
  # NOTE: as of pvlib-0.6.3, min req is pandas-0.18.1, so pd.to_timedelta
199
233
  # unit must be in (D,h,m,s,ms,us,ns), but pandas>=0.24 allows unit='hour'
200
- data.index = data_ymd + pd.to_timedelta(shifted_hour, unit='h')
201
-
202
- if recolumn:
203
- data = _recolumn(data) # rename to standard column names
234
+ data.index = data_ymd + pd.to_timedelta(shifted_hour, unit='h') \
235
+ + pd.to_timedelta(minutes, unit='min')
236
+ # shouldnt' specify both recolumn and map_variables
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)
252
+ if map_variables:
253
+ data = data.rename(columns=VARIABLE_MAP)
254
+ elif recolumn or (recolumn is None and map_variables is None):
255
+ data = _recolumn(data)
204
256
 
205
257
  data = data.tz_localize(int(meta['TZ'] * 3600))
206
258
 
207
259
  return data, meta
208
260
 
209
261
 
210
- def _parse_tmy3(fbuf):
211
- # header information on the 1st line (0 indexing)
212
- firstline = fbuf.readline()
213
- # use pandas to read the csv file buffer
214
- # header is actually the second line, but tell pandas to look for
215
- data = pd.read_csv(fbuf, header=0)
216
- return firstline, data
217
-
218
-
219
262
  def _recolumn(tmy3_dataframe):
220
263
  """
221
264
  Rename the columns of the TMY3 DataFrame.
@@ -283,7 +326,7 @@ def read_tmy2(filename):
283
326
  data : DataFrame
284
327
  A dataframe with the columns described in the table below. For a
285
328
  more detailed descriptions of each component, please consult the
286
- TMY2 User's Manual ([1]_), especially tables 3-1 through 3-6, and
329
+ TMY2 User's Manual [1]_, especially tables 3-1 through 3-6, and
287
330
  Appendix B.
288
331
 
289
332
  metadata : dict
@@ -385,6 +428,7 @@ def read_tmy2(filename):
385
428
  ----------
386
429
  .. [1] Marion, W and Urban, K. "Wilcox, S and Marion, W. "User's Manual
387
430
  for TMY2s". NREL 1995.
431
+ :doi:`10.2172/87130`
388
432
  """ # noqa: E501
389
433
  # paste in the column info as one long line
390
434
  string = '%2d%2d%2d%2d%4d%4d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%4d%1s%1d%2d%1s%1d%2d%1s%1d%4d%1s%1d%4d%1s%1d%3d%1s%1d%4d%1s%1d%3d%1s%1d%3d%1s%1d%4d%1s%1d%5d%1s%1d%10d%3d%1s%1d%3d%1s%1d%3d%1s%1d%2d%1s%1d' # noqa: E501
pvlib/irradiance.py CHANGED
@@ -1481,24 +1481,24 @@ def _disc_kn(clearness_index, airmass, max_airmass=12):
1481
1481
 
1482
1482
  am = np.minimum(am, max_airmass) # GH 450
1483
1483
 
1484
- # powers of kt will be used repeatedly, so compute only once
1485
- kt2 = kt * kt # about the same as kt ** 2
1486
- kt3 = kt2 * kt # 5-10x faster than kt ** 3
1487
-
1488
- bools = (kt <= 0.6)
1489
- a = np.where(bools,
1490
- 0.512 - 1.56*kt + 2.286*kt2 - 2.222*kt3,
1491
- -5.743 + 21.77*kt - 27.49*kt2 + 11.56*kt3)
1492
- b = np.where(bools,
1493
- 0.37 + 0.962*kt,
1494
- 41.4 - 118.5*kt + 66.05*kt2 + 31.9*kt3)
1495
- c = np.where(bools,
1496
- -0.28 + 0.932*kt - 2.048*kt2,
1497
- -47.01 + 184.2*kt - 222.0*kt2 + 73.81*kt3)
1484
+ is_cloudy = (kt <= 0.6)
1485
+ # Use Horner's method to compute polynomials efficiently
1486
+ a = np.where(
1487
+ is_cloudy,
1488
+ 0.512 + kt*(-1.56 + kt*(2.286 - 2.222*kt)),
1489
+ -5.743 + kt*(21.77 + kt*(-27.49 + 11.56*kt)))
1490
+ b = np.where(
1491
+ is_cloudy,
1492
+ 0.37 + 0.962*kt,
1493
+ 41.4 + kt*(-118.5 + kt*(66.05 + 31.9*kt)))
1494
+ c = np.where(
1495
+ is_cloudy,
1496
+ -0.28 + kt*(0.932 - 2.048*kt),
1497
+ -47.01 + kt*(184.2 + kt*(-222.0 + 73.81*kt)))
1498
1498
 
1499
1499
  delta_kn = a + b * np.exp(c*am)
1500
1500
 
1501
- Knc = 0.866 - 0.122*am + 0.0121*am**2 - 0.000653*am**3 + 1.4e-05*am**4
1501
+ Knc = 0.866 + am*(-0.122 + am*(0.0121 + am*(-0.000653 + 1.4e-05*am)))
1502
1502
  Kn = Knc - delta_kn
1503
1503
  return Kn, am
1504
1504
 
@@ -2227,6 +2227,8 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
2227
2227
  --------
2228
2228
  dirint
2229
2229
  disc
2230
+ orgill_hollands
2231
+ boland
2230
2232
  """
2231
2233
 
2232
2234
  dni_extra = get_extra_radiation(datetime_or_doy)
@@ -2265,6 +2267,198 @@ def erbs(ghi, zenith, datetime_or_doy, min_cos_zenith=0.065, max_zenith=87):
2265
2267
  return data
2266
2268
 
2267
2269
 
2270
+ def orgill_hollands(ghi, zenith, datetime_or_doy, dni_extra=None,
2271
+ min_cos_zenith=0.065, max_zenith=87):
2272
+ """Estimate DNI and DHI from GHI using the Orgill and Hollands model.
2273
+
2274
+ The Orgill and Hollands model [1]_ estimates the diffuse fraction DF from
2275
+ global horizontal irradiance through an empirical relationship between
2276
+ hourly DF observations (in Toronto, Canada) and the ratio of GHI to
2277
+ extraterrestrial irradiance, Kt.
2278
+
2279
+ Parameters
2280
+ ----------
2281
+ ghi: numeric
2282
+ Global horizontal irradiance in W/m^2.
2283
+ zenith: numeric
2284
+ True (not refraction-corrected) zenith angles in decimal degrees.
2285
+ datetime_or_doy : int, float, array, pd.DatetimeIndex
2286
+ Day of year or array of days of year e.g.
2287
+ pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
2288
+ dni_extra : None or numeric, default None
2289
+ Extraterrestrial direct normal irradiance. [W/m2]
2290
+ min_cos_zenith : numeric, default 0.065
2291
+ Minimum value of cos(zenith) to allow when calculating global
2292
+ clearness index `kt`. Equivalent to zenith = 86.273 degrees.
2293
+ max_zenith : numeric, default 87
2294
+ Maximum value of zenith to allow in DNI calculation. DNI will be
2295
+ set to 0 for times with zenith values greater than `max_zenith`.
2296
+
2297
+ Returns
2298
+ -------
2299
+ data : OrderedDict or DataFrame
2300
+ Contains the following keys/columns:
2301
+
2302
+ * ``dni``: the modeled direct normal irradiance in W/m^2.
2303
+ * ``dhi``: the modeled diffuse horizontal irradiance in
2304
+ W/m^2.
2305
+ * ``kt``: Ratio of global to extraterrestrial irradiance
2306
+ on a horizontal plane.
2307
+
2308
+ References
2309
+ ----------
2310
+ .. [1] Orgill, J.F., Hollands, K.G.T., Correlation equation for hourly
2311
+ diffuse radiation on a horizontal surface, Solar Energy 19(4), pp 357–359,
2312
+ 1977. Eqs. 3(a), 3(b) and 3(c)
2313
+ :doi:`10.1016/0038-092X(77)90006-8`
2314
+
2315
+ See Also
2316
+ --------
2317
+ dirint
2318
+ disc
2319
+ erbs
2320
+ boland
2321
+ """
2322
+ if dni_extra is None:
2323
+ dni_extra = get_extra_radiation(datetime_or_doy)
2324
+
2325
+ kt = clearness_index(ghi, zenith, dni_extra, min_cos_zenith=min_cos_zenith,
2326
+ max_clearness_index=1)
2327
+
2328
+ # For Kt < 0.35, set the diffuse fraction
2329
+ df = 1 - 0.249*kt
2330
+
2331
+ # For Kt >= 0.35 and Kt <= 0.75, set the diffuse fraction
2332
+ df = np.where((kt >= 0.35) & (kt <= 0.75),
2333
+ 1.557 - 1.84*kt, df)
2334
+
2335
+ # For Kt > 0.75, set the diffuse fraction
2336
+ df = np.where(kt > 0.75, 0.177, df)
2337
+
2338
+ dhi = df * ghi
2339
+
2340
+ dni = (ghi - dhi) / tools.cosd(zenith)
2341
+ bad_values = (zenith > max_zenith) | (ghi < 0) | (dni < 0)
2342
+ dni = np.where(bad_values, 0, dni)
2343
+ # ensure that closure relationship remains valid
2344
+ dhi = np.where(bad_values, ghi, dhi)
2345
+
2346
+ data = OrderedDict()
2347
+ data['dni'] = dni
2348
+ data['dhi'] = dhi
2349
+ data['kt'] = kt
2350
+
2351
+ if isinstance(datetime_or_doy, pd.DatetimeIndex):
2352
+ data = pd.DataFrame(data, index=datetime_or_doy)
2353
+
2354
+ return data
2355
+
2356
+
2357
+ def boland(ghi, solar_zenith, datetime_or_doy, a_coeff=8.645, b_coeff=0.613,
2358
+ min_cos_zenith=0.065, max_zenith=87):
2359
+ r"""
2360
+ Estimate DNI and DHI from GHI using the Boland clearness index model.
2361
+
2362
+ The Boland model [1]_, [2]_ estimates the diffuse fraction, DF, from global
2363
+ horizontal irradiance, GHI, through an empirical relationship between DF
2364
+ and the clearness index, :math:`k_t`, the ratio of GHI to horizontal
2365
+ extraterrestrial irradiance.
2366
+
2367
+ .. math::
2368
+
2369
+ \mathit{DF} = \frac{1}{1 + \exp\left(a \left(k_t - b\right)\right)}
2370
+
2371
+
2372
+ Parameters
2373
+ ----------
2374
+ ghi: numeric
2375
+ Global horizontal irradiance. [W/m^2]
2376
+ solar_zenith: numeric
2377
+ True (not refraction-corrected) zenith angles in decimal degrees.
2378
+ datetime_or_doy : numeric, pandas.DatetimeIndex
2379
+ Day of year or array of days of year e.g.
2380
+ pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
2381
+ a_coeff : float, default 8.645
2382
+ Logistic curve fit coefficient.
2383
+ b_coeff : float, default 0.613
2384
+ Logistic curve fit coefficient.
2385
+ min_cos_zenith : numeric, default 0.065
2386
+ Minimum value of cos(zenith) to allow when calculating global
2387
+ clearness index :math:`k_t`. Equivalent to zenith = 86.273 degrees.
2388
+ max_zenith : numeric, default 87
2389
+ Maximum value of zenith to allow in DNI calculation. DNI will be
2390
+ set to 0 for times with zenith values greater than `max_zenith`.
2391
+
2392
+ Returns
2393
+ -------
2394
+ data : OrderedDict or DataFrame
2395
+ Contains the following keys/columns:
2396
+
2397
+ * ``dni``: the modeled direct normal irradiance in W/m^2.
2398
+ * ``dhi``: the modeled diffuse horizontal irradiance in
2399
+ W/m^2.
2400
+ * ``kt``: Ratio of global to extraterrestrial irradiance
2401
+ on a horizontal plane.
2402
+
2403
+ References
2404
+ ----------
2405
+ .. [1] J. Boland, B. Ridley (2008) Models of Diffuse Solar Fraction. In:
2406
+ Badescu V. (eds) Modeling Solar Radiation at the Earth’s Surface.
2407
+ Springer, Berlin, Heidelberg. :doi:`10.1007/978-3-540-77455-6_8`
2408
+ .. [2] John Boland, Lynne Scott, and Mark Luther, Modelling the diffuse
2409
+ fraction of global solar radiation on a horizontal surface,
2410
+ Environmetrics 12(2), pp 103-116, 2001,
2411
+ :doi:`10.1002/1099-095X(200103)12:2%3C103::AID-ENV447%3E3.0.CO;2-2`
2412
+
2413
+ See also
2414
+ --------
2415
+ dirint
2416
+ disc
2417
+ erbs
2418
+ orgill_hollands
2419
+
2420
+ Notes
2421
+ -----
2422
+ Boland diffuse fraction differs from other decomposition algorithms by use
2423
+ of a logistic function to fit the entire range of clearness index,
2424
+ :math:`k_t`. Parameters ``a_coeff`` and ``b_coeff`` are reported in [2]_
2425
+ for different time intervals:
2426
+
2427
+ * 15-minute: ``a = 8.645`` and ``b = 0.613``
2428
+ * 1-hour: ``a = 7.997`` and ``b = 0.586``
2429
+ """
2430
+
2431
+ dni_extra = get_extra_radiation(datetime_or_doy)
2432
+
2433
+ kt = clearness_index(
2434
+ ghi, solar_zenith, dni_extra, min_cos_zenith=min_cos_zenith,
2435
+ max_clearness_index=1)
2436
+
2437
+ # Boland equation
2438
+ df = 1.0 / (1.0 + np.exp(a_coeff * (kt - b_coeff)))
2439
+ # NOTE: [2] has different coefficients, for different time intervals
2440
+ # 15-min: df = 1 / (1 + exp(8.645 * (kt - 0.613)))
2441
+ # 1-hour: df = 1 / (1 + exp(7.997 * (kt - 0.586)))
2442
+
2443
+ dhi = df * ghi
2444
+
2445
+ dni = (ghi - dhi) / tools.cosd(solar_zenith)
2446
+ bad_values = (solar_zenith > max_zenith) | (ghi < 0) | (dni < 0)
2447
+ dni = np.where(bad_values, 0, dni)
2448
+ # ensure that closure relationship remains valid
2449
+ dhi = np.where(bad_values, ghi, dhi)
2450
+
2451
+ data = OrderedDict()
2452
+ data['dni'] = dni
2453
+ data['dhi'] = dhi
2454
+ data['kt'] = kt
2455
+
2456
+ if isinstance(datetime_or_doy, pd.DatetimeIndex):
2457
+ data = pd.DataFrame(data, index=datetime_or_doy)
2458
+
2459
+ return data
2460
+
2461
+
2268
2462
  def campbell_norman(zenith, transmittance, pressure=101325.0,
2269
2463
  dni_extra=1367.0):
2270
2464
  '''
@@ -3013,3 +3207,64 @@ def complete_irradiance(solar_zenith,
3013
3207
  'dhi': dhi,
3014
3208
  'dni': dni})
3015
3209
  return component_sum_df
3210
+
3211
+
3212
+ def louche(ghi, solar_zenith, datetime_or_doy, max_zenith=90):
3213
+ """
3214
+ Determine DNI and DHI from GHI using the Louche model.
3215
+
3216
+ Parameters
3217
+ ----------
3218
+ ghi : numeric
3219
+ Global horizontal irradiance. [W/m^2]
3220
+
3221
+ solar_zenith : numeric
3222
+ True (not refraction-corrected) zenith angles in decimal
3223
+ degrees. Angles must be >=0 and <=90.
3224
+
3225
+ datetime_or_doy : numeric, pandas.DatetimeIndex
3226
+ Day of year or array of days of year e.g.
3227
+ pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
3228
+
3229
+ Returns
3230
+ -------
3231
+ data: OrderedDict or DataFrame
3232
+ Contains the following keys/columns:
3233
+
3234
+ * ``dni``: the modeled direct normal irradiance in W/m^2.
3235
+ * ``dhi``: the modeled diffuse horizontal irradiance in
3236
+ W/m^2.
3237
+ * ``kt``: Ratio of global to extraterrestrial irradiance
3238
+ on a horizontal plane.
3239
+
3240
+ References
3241
+ -------
3242
+ .. [1] Louche A, Notton G, Poggi P, Simonnot G. Correlations for direct
3243
+ normal and global horizontal irradiation on a French Mediterranean site.
3244
+ Solar Energy 1991;46:261-6. :doi:`10.1016/0038-092X(91)90072-5`
3245
+
3246
+ """
3247
+
3248
+ I0 = get_extra_radiation(datetime_or_doy)
3249
+
3250
+ Kt = clearness_index(ghi, solar_zenith, I0)
3251
+
3252
+ kb = -10.627*Kt**5 + 15.307*Kt**4 - 5.205 * \
3253
+ Kt**3 + 0.994*Kt**2 - 0.059*Kt + 0.002
3254
+ dni = kb*I0
3255
+ dhi = ghi - dni*tools.cosd(solar_zenith)
3256
+
3257
+ bad_values = (solar_zenith > max_zenith) | (ghi < 0) | (dni < 0)
3258
+ dni = np.where(bad_values, 0, dni)
3259
+ # ensure that closure relationship remains valid
3260
+ dhi = np.where(bad_values, ghi, dhi)
3261
+
3262
+ data = OrderedDict()
3263
+ data['dni'] = dni
3264
+ data['dhi'] = dhi
3265
+ data['kt'] = Kt
3266
+
3267
+ if isinstance(datetime_or_doy, pd.DatetimeIndex):
3268
+ data = pd.DataFrame(data, index=datetime_or_doy)
3269
+
3270
+ return data