10
10
11
11
import datetime
12
12
from collections import OrderedDict
13
+ from functools import partial
13
14
14
15
import numpy as np
15
16
import pandas as pd
36
37
37
38
38
39
def extraradiation (datetime_or_doy , solar_constant = 1366.1 , method = 'spencer' ,
39
- ** kwargs ):
40
+ epoch_year = 2014 , ** kwargs ):
40
41
"""
41
42
Determine extraterrestrial radiation from day of year.
42
43
43
44
Parameters
44
45
----------
45
- datetime_or_doy : int, float, array, pd.DatetimeIndex
46
- Day of year, array of days of year e.g.
47
- pd.DatetimeIndex.dayofyear, or pd.DatetimeIndex.
46
+ datetime_or_doy : int, float, array, date, datetime, datetime64,
47
+ Timestamp, DatetimeIndex
48
+ Day of year, array of days of year, or datetime-like object
48
49
49
50
solar_constant : float
50
51
The solar constant.
@@ -53,132 +54,93 @@ def extraradiation(datetime_or_doy, solar_constant=1366.1, method='spencer',
53
54
The method by which the ET radiation should be calculated.
54
55
Options include ``'pyephem', 'spencer', 'asce', 'nrel'``.
55
56
57
+ epoch_year : int
58
+ The year in which a day of year input will be calculated. Only
59
+ applies to day of year input used with the pyephem or nrel
60
+ methods.
61
+
56
62
kwargs :
57
63
Passed to solarposition.nrel_earthsun_distance
58
64
59
65
Returns
60
66
-------
61
67
dni_extra : float, array, or Series
62
68
The extraterrestrial radiation present in watts per square meter
63
- on a surface which is normal to the sun. Ea is of the same size
64
- as the input doy.
65
-
66
- 'pyephem' and 'nrel' always return a Series.
67
-
68
- Notes
69
- -----
70
- The Spencer method contains a minus sign discrepancy between
71
- equation 12 of [1]. It's unclear what the correct formula is.
69
+ on a surface which is normal to the sun. Pandas Timestamp and
70
+ DatetimeIndex inputs will yield a Pandas TimeSeries. All other
71
+ inputs will yield a float or an array of floats.
72
72
73
73
References
74
74
----------
75
75
[1] M. Reno, C. Hansen, and J. Stein, "Global Horizontal Irradiance
76
76
Clear Sky Models: Implementation and Analysis", Sandia National
77
77
Laboratories, SAND2012-2389, 2012.
78
78
79
- [2] <http://solardat.uoregon.edu/SolarRadiationBasics.html>,
80
- Eqs. SR1 and SR2
81
-
82
- [3] Partridge, G. W. and Platt, C. M. R. 1976.
83
- Radiative Processes in Meteorology and Climatology.
79
+ [2] <http://solardat.uoregon.edu/SolarRadiationBasics.html>, Eqs.
80
+ SR1 and SR2
84
81
85
- [4] Duffie, J. A. and Beckman, W. A. 1991.
86
- Solar Engineering of Thermal Processes,
87
- 2nd edn. J. Wiley and Sons, New York.
82
+ [3] Partridge, G. W. and Platt, C. M. R. 1976. Radiative Processes
83
+ in Meteorology and Climatology.
88
84
89
- See Also
90
- --------
91
- pvlib.clearsky.disc
85
+ [4] Duffie, J. A. and Beckman, W. A. 1991. Solar Engineering of
86
+ Thermal Processes, 2nd edn. J. Wiley and Sons, New York.
92
87
"""
93
88
94
- pvl_logger .debug ('irradiance.extraradiation()' )
95
-
96
- method = method .lower ()
97
-
89
+ # This block will set the functions that can be used to convert the
90
+ # inputs to either day of year or pandas DatetimeIndex, and the
91
+ # functions that will yield the appropriate output type. It's
92
+ # complicated because there are many day-of-year-like input types,
93
+ # and the different algorithms need different types. Maybe you have
94
+ # a better way to do it.
98
95
if isinstance (datetime_or_doy , pd .DatetimeIndex ):
99
- doy = datetime_or_doy .dayofyear
100
- input_to_datetimeindex = lambda x : datetime_or_doy
101
- elif isinstance (datetime_or_doy , (int , float )):
102
- doy = datetime_or_doy
103
- input_to_datetimeindex = _scalar_to_datetimeindex
104
- else : # assume that we have an array-like object of doy. danger?
105
- doy = datetime_or_doy
106
- input_to_datetimeindex = _array_to_datetimeindex
107
-
108
- B = (2. * np .pi / 365. ) * (doy - 1 )
96
+ to_doy = tools ._pandas_to_doy # won't be evaluated unless necessary
97
+ to_datetimeindex = lambda x : datetime_or_doy
98
+ to_output = partial (pd .Series , index = datetime_or_doy )
99
+ elif isinstance (datetime_or_doy , pd .Timestamp ):
100
+ to_doy = tools ._pandas_to_doy
101
+ to_datetimeindex = \
102
+ tools ._datetimelike_scalar_to_datetimeindex
103
+ to_output = tools ._scalar_out
104
+ elif isinstance (datetime_or_doy ,
105
+ (datetime .date , datetime .datetime , np .datetime64 )):
106
+ to_doy = tools ._datetimelike_scalar_to_doy
107
+ to_datetimeindex = \
108
+ tools ._datetimelike_scalar_to_datetimeindex
109
+ to_output = tools ._scalar_out
110
+ elif np .isscalar (datetime_or_doy ): # ints and floats of various types
111
+ to_doy = lambda x : datetime_or_doy
112
+ to_datetimeindex = partial (tools ._doy_to_datetimeindex ,
113
+ epoch_year = epoch_year )
114
+ to_output = tools ._scalar_out
115
+ else : # assume that we have an array-like object of doy
116
+ to_doy = lambda x : datetime_or_doy
117
+ to_datetimeindex = partial (tools ._doy_to_datetimeindex ,
118
+ epoch_year = epoch_year )
119
+ to_output = tools ._array_out
109
120
110
121
method = method .lower ()
111
122
if method == 'asce' :
112
- pvl_logger . debug ( 'Calculating ET rad using ASCE method' )
123
+ B = solarposition . _calculate_simple_day_angle ( to_doy ( datetime_or_doy ) )
113
124
RoverR0sqrd = 1 + 0.033 * np .cos (B )
114
125
elif method == 'spencer' :
115
- pvl_logger . debug ( 'Calculating ET rad using Spencer method' )
126
+ B = solarposition . _calculate_simple_day_angle ( to_doy ( datetime_or_doy ) )
116
127
RoverR0sqrd = (1.00011 + 0.034221 * np .cos (B ) + 0.00128 * np .sin (B ) +
117
128
0.000719 * np .cos (2 * B ) + 7.7e-05 * np .sin (2 * B ))
118
129
elif method == 'pyephem' :
119
- pvl_logger .debug ('Calculating ET rad using pyephem method' )
120
- times = input_to_datetimeindex (datetime_or_doy )
130
+ times = to_datetimeindex (datetime_or_doy )
121
131
RoverR0sqrd = solarposition .pyephem_earthsun_distance (times ) ** (- 2 )
122
132
elif method == 'nrel' :
123
- times = input_to_datetimeindex (datetime_or_doy )
133
+ times = to_datetimeindex (datetime_or_doy )
124
134
RoverR0sqrd = \
125
135
solarposition .nrel_earthsun_distance (times , ** kwargs ) ** (- 2 )
126
136
else :
127
137
raise ValueError ('Invalid method: %s' , method )
128
138
129
139
Ea = solar_constant * RoverR0sqrd
130
140
131
- return Ea
132
-
133
-
134
- def _scalar_to_datetimeindex (doy_scalar ):
135
- """
136
- Convert a scalar day of year number to a pd.DatetimeIndex.
141
+ Ea = to_output (Ea )
137
142
138
- Parameters
139
- ----------
140
- doy_array : int or float
141
- Contains days of the year
142
-
143
- Returns
144
- -------
145
- pd.DatetimeIndex
146
- """
147
- return pd .DatetimeIndex ([_doy_to_timestamp (doy_scalar )])
148
-
149
-
150
- def _array_to_datetimeindex (doy_array ):
151
- """
152
- Convert an array of day of year numbers to a pd.DatetimeIndex.
153
-
154
- Parameters
155
- ----------
156
- doy_array : Iterable
157
- Contains days of the year
158
-
159
- Returns
160
- -------
161
- pd.DatetimeIndex
162
- """
163
- return pd .DatetimeIndex (list (map (_doy_to_timestamp , doy_array )))
164
-
165
-
166
- def _doy_to_timestamp (doy , epoch = '2013-12-31' ):
167
- """
168
- Convert a numeric day of the year to a pd.Timestamp.
169
-
170
- Parameters
171
- ----------
172
- doy : int or float.
173
- Numeric day of year.
174
- epoch : pd.Timestamp compatible object.
175
- Date to which to add the day of year to.
176
-
177
- Returns
178
- -------
179
- pd.Timestamp
180
- """
181
- return pd .Timestamp ('2013-12-31' ) + datetime .timedelta (days = float (doy ))
143
+ return Ea
182
144
183
145
184
146
def aoi_projection (surface_tilt , surface_azimuth , solar_zenith , solar_azimuth ):
0 commit comments