@@ -159,7 +159,12 @@ def latlon_to_xy(coordinates):
159
159
160
160
def _compute_wavelet (clearsky_index , dt = None ):
161
161
"""
162
- Compute the wavelet transform on the input clear_sky time series.
162
+ Compute the wavelet transform on the input clear_sky time series. Uses a
163
+ Haar wavelet based on moving average. Output resembles a Stationary Wavelet
164
+ Transform (SWT), but has shifted time positions on the averages relative to
165
+ output from other wavelet codes. Returns one level of approximation
166
+ coefficient (CAn) and n levels of detail coefficients (CD1, CD2, ...,
167
+ CDn-1, CDn). Maximum scale is 4096 s (12 levels at a signal dt of 1s).
163
168
164
169
Parameters
165
170
----------
@@ -174,7 +179,8 @@ def _compute_wavelet(clearsky_index, dt=None):
174
179
Returns
175
180
-------
176
181
wavelet: numeric
177
- The individual wavelets for the time series
182
+ The individual wavelets for the time series. Format follows increasing
183
+ scale (decreasing frequency): [CD1, CD2, ..., CDn, CAn]
178
184
179
185
tmscales: numeric
180
186
The timescales associated with the wavelets in seconds [s]
@@ -211,29 +217,31 @@ def _compute_wavelet(clearsky_index, dt=None):
211
217
min_tmscale = np .ceil (np .log (dt )/ np .log (2 )) # Minimum wavelet timescale
212
218
max_tmscale = int (12 - min_tmscale ) # maximum wavelet timescale
213
219
214
- tmscales = np .zeros (max_tmscale )
215
- csi_mean = np .zeros ([max_tmscale , len (cs_long )])
216
- # Loop for all time scales we will consider
217
- for i in np .arange (0 , max_tmscale ):
218
- j = i + 1
219
- tmscales [i ] = 2 ** j * dt # Wavelet integration time scale
220
- intvlen = 2 ** j # Wavelet integration time series interval
220
+ # Compute approximation coefficients via moving average (Haar wavelet)
221
+ csi_mean = np .zeros ([max_tmscale + 1 , len (cs_long )])
222
+ csi_mean [0 , :] = cs_long .values .flatten () # CA0, the original signal
223
+ for i in np .arange (1 , max_tmscale + 1 ):
224
+ intvlen = 2 ** i # Wavelet integration time series interval
221
225
# Rolling average, retains only lower frequencies than interval
222
226
df = cs_long .rolling (window = intvlen , center = True , min_periods = 1 ).mean ()
223
227
# Fill nan's in both directions
224
228
df = df .fillna (method = 'bfill' ).fillna (method = 'ffill' )
225
229
# Pop values back out of the dataframe and store
226
- csi_mean [i , :] = df .values .flatten ()
230
+ csi_mean [i , :] = df .values .flatten () # Approximation Coeffs CA0,CA1,...
227
231
228
- # Calculate the wavelets by isolating the rolling mean frequency ranges
232
+ # Calculate detail coeffs by difference between approximation levels
229
233
wavelet_long = np .zeros (csi_mean .shape )
230
- for i in np .arange (0 , max_tmscale - 1 ):
234
+ tmscales = np .zeros (max_tmscale + 1 )
235
+ for i in np .arange (0 , max_tmscale ):
236
+ # Compute detail coeffs, beginning with CD1 through CDn
231
237
wavelet_long [i , :] = csi_mean [i , :] - csi_mean [i + 1 , :]
232
- wavelet_long [max_tmscale - 1 , :] = csi_mean [max_tmscale - 1 , :] # Lowest freq
238
+ tmscales [i ] = 2 ** (i + 1 ) * dt # Wavelet integration time scale
239
+ wavelet_long [max_tmscale , :] = csi_mean [max_tmscale , :] # Lowest freq (CAn)
240
+ tmscales [max_tmscale ] = tmscales [max_tmscale - 1 ] # CAn and CDn share scale
233
241
234
242
# Clip off the padding and just return the original time window
235
- wavelet = np .zeros ([max_tmscale , len (vals )])
236
- for i in np .arange (0 , max_tmscale ):
237
- wavelet [i , :] = wavelet_long [i , len (vals )+ 1 : 2 * len (vals )+ 1 ]
243
+ wavelet = np .zeros ([max_tmscale + 1 , len (vals )])
244
+ for i in np .arange (0 , max_tmscale + 1 ):
245
+ wavelet [i , :] = wavelet_long [i , len (vals ): 2 * len (vals )]
238
246
239
247
return wavelet , tmscales
0 commit comments