def swt_rot_cum_wav_svar(WJt, VJ0t, method='power'): """ swt_cum_wav_svar -- Calculate cumulative sample variance of SWT wavelet coefficients. NAME swt_cum_wav_svar -- Calculate cumulative sample variance of SWT wavelet coefficients. INPUTS WJt - JxN dwtArray of SWT wavelet coefficents where N = number of time intervals J = number of levels they can be already rotated or not VJ0t - N dwtArray of SWT J0 scaling coefficents they can be already rotated or not method - variance estimate returned 'power' = |W^2|/N 'cum' = cumulative variance 'cumsc' = cumulative "scaled" (see pag.189) Default: 'power' OUTPUTS cwsvar - cumulative wavelet sample variance (dwtArray). DESCRIPTION 'cumsc' method is equivalent to the one on pag.189 of P&W . ALGORITHM cwsvar[j,t] = 1/N * sum( WJt^2 subscript(j,u+nuH_j mod N)) for t = 0,N-1 at jth level for j in range(J): rcwsvar[j,:] = cswvar[j,:] - t*cwsvarN[j]/(N-1.) SEE ALSO swt_cir_shift, swt """ if method not in ('power','cum','cumsc'): raise ValueError('Valid methods are: "power", "cum" or "cumsc"') # check input if type(WJt) is not dwtArray: raise TypeError('Input must be a dwtArray') if WJt.info['Type'] is not 'Wavelet': raise TypeError('First input array does not contain Wavelet coefficients but {} coefficients'.format(WJt.info['Type'])) if type(VJ0t) is not dwtArray: raise TypeError('Input must be a dwtArray') if VJ0t.info['Type'] is not 'Scaling': raise TypeError('Second input array does not contain Scaling coefficients but {} coefficients'.format(VJ0t.info['Type'])) # get dimensions try: J, N = WJt.shape except ValueError: N = WJt.size J=1 if len(VJ0t.shape)>1: raise ValueError('Only J0 level scaling coefficient should be given') # rotate if they are not yet aligned WJt,VJ0t = swt_cir_shift(WJt, VJ0t) # the check for rotation is done in swt_cir_shift pWJt = WJt**2; pVJ0t = VJ0t**2 if method=='power': Watt = dict(WJt.info.items() + {'Type':'WavRotPower'}.items()) Vatt = dict(VJ0t.info.items() + {'Type':'ScalRotPower'}.items()) return dwtArray(pWJt, info=Watt),dwtArray(pVJ0t, info=Vatt) cwsvar = np.cumsum(pWJt, axis=1)/N swsvar = np.cumsum(pVJ0t)/N if method=='cum': Watt = dict(WJt.info.items() + {'Type':'WavRotCumVar'}.items()) Vatt = dict(VJ0t.info.items() + {'Type':'ScalRotCumVar'}.items()) return dwtArray(cwsvar, info=Watt),dwtArray(swsvar, info=Vatt) # compute rotated cumulative variance cwsvarN = cwsvar[:,-1] swsvarN = swsvar[-1] t = np.arange(N, dtype=np.float64) rcwsvar = cwsvar - t*cwsvarN[:,np.newaxis]/(N-1) rswsvar = swsvar - t*swsvarN/(N-1) Watt = dict(WJt.info.items() + {'Type':'WavRotCumScVar'}.items()) Vatt = dict(VJ0t.info.items() + {'Type':'ScalRotCumScVar'}.items()) return dwtArray(rcwsvar, info=Watt),dwtArray(rswsvar, info=Vatt)
def swt(X, wtf='d4', nlevels='conservative', RetainVJ=False): """ function swt(X, wtf='d4', nlevels='conservative', RetainVJ=False) NAME swt -- Compute the (partial) stationary wavelet transform (SWT). INPUTS X -- set of observations (vector of length NX) wtf -- (optional) wavelet transform filter name (string, case-insensitve or wtf struct). Default: 'd4' nlevels -- (optional) maximum level J0 (integer) or method of calculating J0 (string). Valid values: integer>0 or a valid method name Default: 'conservative' RetainVJ -- (optional) boolean flag to retain V at each decomposition level Default: False OUTPUTS WJt -- SWT wavelet coefficents (J x NW array) dwtArray VJt -- SWT scaling coefficients ((1 or J) x NW vector) dwtArray DESCRIPTION swt calculates the wavelet and scaling coefficients using the stationary wavelet transform (SWT). The optional input arguments have default values: * wtf -- 'd4' filter * nlevels -- 'convservative' --> J0 < log2( N / (L-1) + 1) The output arguments include an info attribute with metadata. info is a dictionary with the following fields: * Transform -- name of transform ('SWT') * WTF -- name of wavelet transform filter or a wtf_s struct. * NX -- number of observations in original series (= length(X)) * NW -- number of wavelet coefficients * J0 -- number of levels of partial decompsition. * Aligned -- Boolean flag indicating whether coefficients are aligned with original series (1 = true) or not (0 = false). * RetainVJ -- Boolean flag indicating whether VJ scaling coefficients at all levels have been retained (1= true) or not (0 = false). EXAMPLE WJt, VJt = swt(X, 'd4', 6) NOTES pages 177-178 of P&W SEE ALSO swtj, swt_filter, swt_choose_nlevels, nargerr, argterr, dwtArray """ # Get a valid wavelet transform filter coefficients struct. wtf_s = wtfilter(wtf) wtfname = wtf_s.Name gt = wtf_s.g ht = wtf_s.h L = wtf_s.L # ensure X is a numpy array X = np.array(X) if len(X.shape)>1: raise ValueError('SWT: Input array must be one-dimensional') # N = length of original series N = X.size # If nlevels is an integer > 0, set J0 = nlevels. # otherwise, select J0 based on choice method specified. if isinstance(nlevels, str): J0 = swt_choose_nlevels(nlevels, wtfname, N) elif isinstance(nlevels, int): if nlevels > 0: J0 = nlevels else: raise ValueError('SWT:negativeJ0, nlevels must be an integer greater than 0.') else: raise ValueError('SWT:invalidNLevelsValue') if (J0 < 0): raise ValueError('SWT:negativeJ0') if (2**J0 > N): raise ValueError('SWT:LargeJ0', 'JO must be < log2(Number of samples).') # NW = length of the extended series = number of coefficients NW = X.size # Initialize the scale (Vin) for first level by setting it equal to X Vin = X # Pre-allocate memory. WJt = np.ndarray((J0, NW), dtype=np.float64)*np.nan if RetainVJ: VJt = np.ndarray((J0, NW), dtype=np.float64)*np.nan else: VJt = np.ndarray((NW), dtype=np.float64)*np.nan # Do the SWT. from swtj import swtj bw = np.ndarray((J0,2))*np.nan for j in range(J0): Wt_j, Vout = swtj(Vin, j+1, ht, gt) WJt[j,:] = Wt_j Vin = Vout if RetainVJ: VJt[j,:] = Vout # boundary values 198 L_j = equivalent_filter_width(L, j+1) bw[j,0] = min(L_j - 2, NW-1) #max index to the left #bw[j,1] = np.nan #Bc are only at the beginning if not RetainVJ: VJt[:] = Vout bv = bw[-1,:] else: bv = bw # Update attributes att = {'Transform':'SWT', 'WTF' : wtfname, 'N' : N, 'NW' : NW, 'J0' : J0, 'Aligned' : False, 'RetainVJ' : RetainVJ, 'Type' : 'Wavelet', 'BCs' : bw } WJt = dwtArray(WJt, info=att) att = {'Transform':'SWT', 'WTF' : wtfname, 'N' : N, 'NW' : NW, 'J0' : J0, 'Aligned' : False, 'RetainVJ' : RetainVJ, 'Type' : 'Scaling', 'BCs' : bv } VJt = dwtArray(VJt, info=att) return WJt, VJt
def swt_cir_shift(WJt, VJ0t, subtract_mean_VJ0t=True): """ shift_swt_coef -- shift the SWT wavelet and scaling coefficients. NAME shift_swt_coef -- Shift the SWT wavelet and scaling coefficients. INPUTS WJt = JxN dwtArray of SWT wavelet coefficents where N = number of time intervals, J = number of levels VJ0t = N dwtArray of SWT scaling coefficients at level J0. subtract_mean_VJ0t = (optional) subtract mean value of scaling coefficient from itself Default: True OUTPUTS W = shifted wavelet coefficients with boundary conditions (dwtArray) V = shifted scaling coefficients with boundary conditions (dwtArray) boundaries = demarcing the circularly shifted SWT coefficients influenced by the circularity conditions bw = Jx2 array with min/max indices of wavelet boundary coefficients bv = Jx2 array with min/max indices of scaling boundary coefficients DESCRIPTION The SWT coefficients are circularly shifted at each level so as to properly align the coefficients with the original data series. See P&W fig 183 SEE ALSO swt, swt_filter multi_yoffset_plot """ # check input if type(WJt) is not dwtArray: raise TypeError('Input must be a dwtArray') if WJt.info['Type'] is not 'Wavelet': raise TypeError('First input array does not contain Wavelet coefficients but {} coefficients'.format(WJt.info['Type'])) if type(VJ0t) is not dwtArray: raise TypeError('Input must be a dwtArray') if VJ0t.info['Type'] is not 'Scaling': raise TypeError('Second input array does not contain Scaling coefficients but {} coefficients'.format(VJ0t.info['Type'])) wtf_s = wtfilter(WJt.info['WTF']) L = wtf_s.L wtfname = WJt.info['WTF'] N = WJt.info['N'] NW = WJt.info['NW'] J0 = WJt.info['J0'] Nm = min(N,NW) if WJt.info['Aligned']: print ('WARNING (ante.swt.swt_cir_shift): Wavelet coefficients are already aligned') W = WJt else: if WJt!=dwtArray([]): W = np.ndarray(WJt.shape)*np.nan; bw = np.ndarray((J0,2))*np.nan for j in range(J0): # shift wavelet coefficients nuHj = advance_wavelet_filter(wtfname, j+1) W[j,:] = np.roll(WJt[j,:], nuHj) #Calculate circularly shifted wavelet coefficient boundary indices at jth level L_j = equivalent_filter_width(L, j+1) bw[j,0] = L_j - 2 - np.abs(nuHj) #max index to the left bw[j,1] = Nm - abs(nuHj) #min index to the right W = W[:,:Nm] # Update attributes att = dict(WJt.info.items() + {'Aligned':True, 'BCs' :bw }.items()) W = dwtArray(W, info=att) else: # if an empty array was given, do nothing and return it W = WJt if VJ0t.info['Aligned']: print ('WARNING (ante.swt.swt_cir_shift): Wavelet coefficients are already aligned') V = VJ0t else: V = np.ndarray(VJ0t.shape)*np.nan; bv = np.ndarray((2,))*np.nan # shift scaling coefficients if VJ0t!=dwtArray([]): nuGj = advance_scaling_filter(wtfname, J0) if subtract_mean_VJ0t: VJ0t = VJ0t - VJ0t.mean() V = np.roll(VJ0t, nuGj) bv[0] = L_j - 2 - np.abs(nuGj) #max index to the left bv[1] = Nm - np.abs(nuGj) #min index to the right # Update attributes att = dict(VJ0t.info.items() + {'Aligned':True, 'BCs' :bv }.items()) V = dwtArray(V, info=att) else: # if an empty array was given, do nothing and return it V = VJ0t return W,V
def iswt_details(WJt): """ iswt_details -- Calculate details via inverse stationary wavelet transform (ISWT). NAME iswt_details -- Calculate details via inverse stationary wavelet transform (ISWT). INPUTS WJt - NxJ array of SWT wavelet coefficents where N = number of time points J = number of levels. The array must be a dwtArray (containing the information on the transform) OUTPUT DJt - JxN dwtArray of reconstituted details of data series for J0 scales. att - structure containing ISWT transform attributes. DESCRIPTION The output parameter att is a structure with the following fields: name - name of transform (= 'SWT') wtfname - name of SWT wavelet filter npts - number of observations (= length(X)) J0 - number of levels EXAMPLE DJt = iswt_details(WJt) SEE ALSO iswtj, iswt, iswt_smooth, swt_filter, swt """ # Get a the wavelet transform filter coefficients. if type(WJt) is not dwtArray: raise TypeError('Input must be a dwtArray') if WJt.info['Type'] is not 'Wavelet': raise TypeError('Input array does not contain Wavelet coefficients but {} coefficients'.format(WJt.info['Type'])) wtfname = WJt.info['WTF'] wtf_s = wtfilter(wtfname) gt = wtf_s.g ht = wtf_s.h L = wtf_s.L J,N = WJt.shape J0 = J zeroj = np.zeros(N) DJt = np.zeros((J, N)) from swtj import iswtj for j in range(J0-1,-1,-1): Vin = zeroj Win = WJt[j,:] for jj in range(j,-1,-1): Vout = iswtj(Win, Vin, jj+1, ht, gt) Win = zeroj Vin = Vout DJt[j,:] = Vout # boundary values 199 bw = np.ndarray((J0,2), dtype=np.int16)*np.nan for j in range(J0): #Calculate wavelet coefficient boundary indices at jth level L_j = equivalent_filter_width(L, j+1) bw[j,0] = L_j-2; bw[j,1]= -L_j+1 # Update attributes att = dict(WJt.info.items() + {'Transform':'ISWT', 'Type' :'Detail', 'BCs' :bw}.items()) DJt = dwtArray(DJt, info=att) return DJt
def iswt_smooth(VJt): """ iswt_smooth -- Calculate smooths at J0 level via inverse stationary wavelet transform (ISWT). NAME iswt_smooth -- Calculate smooths at J0 level via inverse stationary wavelet transform (ISWT). INPUTS VJt = N dwtArray of SWT scaling coefficients at J0 level. OUTPUT SJOt = dwtArray of reconstituted smoothed data series. DESCRIPTION EXAMPLE SJt = iswt_smooth(VJt) SEE ALSO iswtj, iswt, iswt_details, swt_filter, swt """ # Get the wavelet transform filter coefficients. if type(VJt) is not dwtArray: raise TypeError('Input must be a dwtArray') if VJt.info['Type'] is not 'Scaling': raise TypeError('Input array does not contain Scaling coefficients but {} coefficients'.format(VJt.info['Type'])) wtfname = VJt.info['WTF'] J0 = VJt.info['J0'] wtf_s = wtfilter(wtfname) gt = wtf_s.g ht = wtf_s.h L = wtf_s.L if len(VJt.shape)>1: if VJt.info['RetainVJ']: VJt = VJt[-1,:] else: raise TypeError('The input is a multidimensional array but {} SWT\ has been computed with RetainVJ=False. \n') N = VJt.size # initialize arrays zeroj = np.zeros(N) Vin = VJt #import pyximport; pyximport.install() from swtj import iswtj for j in range(J0-1,-1,-1): Vout = iswtj(zeroj, Vin, j+1, ht, gt) Vin = Vout SJt = Vout # boundary values pag.199 P&W L_j = equivalent_filter_width(L, J0) bv = np.array([L_j-2, -L_j+1]) # Update attributes att = dict(VJt.info.items() + {'Transform':'ISWT', 'Type' :'Smooth', 'BCs' :bv}.items()) SJt = dwtArray(SJt, info=att) return SJt
def swt_rot_cum_wav_svar(WJt, VJ0t, method='power'): """ swt_cum_wav_svar -- Calculate cumulative sample variance of SWT wavelet coefficients. NAME swt_cum_wav_svar -- Calculate cumulative sample variance of SWT wavelet coefficients. INPUTS WJt - JxN dwtArray of SWT wavelet coefficents where N = number of time intervals J = number of levels they can be already rotated or not VJ0t - N dwtArray of SWT J0 scaling coefficents they can be already rotated or not method - variance estimate returned 'power' = |W^2|/N 'cum' = cumulative variance 'cumsc' = cumulative "scaled" (see pag.189) Default: 'power' OUTPUTS cwsvar - cumulative wavelet sample variance (dwtArray). DESCRIPTION 'cumsc' method is equivalent to the one on pag.189 of P&W . ALGORITHM cwsvar[j,t] = 1/N * sum( WJt^2 subscript(j,u+nuH_j mod N)) for t = 0,N-1 at jth level for j in range(J): rcwsvar[j,:] = cswvar[j,:] - t*cwsvarN[j]/(N-1.) SEE ALSO swt_cir_shift, swt """ if method not in ('power', 'cum', 'cumsc'): raise ValueError('Valid methods are: "power", "cum" or "cumsc"') # check input if type(WJt) is not dwtArray: raise TypeError('Input must be a dwtArray') if WJt.info['Type'] is not 'Wavelet': raise TypeError( 'First input array does not contain Wavelet coefficients but {} coefficients' .format(WJt.info['Type'])) if type(VJ0t) is not dwtArray: raise TypeError('Input must be a dwtArray') if VJ0t.info['Type'] is not 'Scaling': raise TypeError( 'Second input array does not contain Scaling coefficients but {} coefficients' .format(VJ0t.info['Type'])) # get dimensions try: J, N = WJt.shape except ValueError: N = WJt.size J = 1 if len(VJ0t.shape) > 1: raise ValueError('Only J0 level scaling coefficient should be given') # rotate if they are not yet aligned WJt, VJ0t = swt_cir_shift( WJt, VJ0t) # the check for rotation is done in swt_cir_shift pWJt = WJt**2 pVJ0t = VJ0t**2 if method == 'power': Watt = dict(WJt.info.items() + {'Type': 'WavRotPower'}.items()) Vatt = dict(VJ0t.info.items() + {'Type': 'ScalRotPower'}.items()) return dwtArray(pWJt, info=Watt), dwtArray(pVJ0t, info=Vatt) cwsvar = np.cumsum(pWJt, axis=1) / N swsvar = np.cumsum(pVJ0t) / N if method == 'cum': Watt = dict(WJt.info.items() + {'Type': 'WavRotCumVar'}.items()) Vatt = dict(VJ0t.info.items() + {'Type': 'ScalRotCumVar'}.items()) return dwtArray(cwsvar, info=Watt), dwtArray(swsvar, info=Vatt) # compute rotated cumulative variance cwsvarN = cwsvar[:, -1] swsvarN = swsvar[-1] t = np.arange(N, dtype=np.float64) rcwsvar = cwsvar - t * cwsvarN[:, np.newaxis] / (N - 1) rswsvar = swsvar - t * swsvarN / (N - 1) Watt = dict(WJt.info.items() + {'Type': 'WavRotCumScVar'}.items()) Vatt = dict(VJ0t.info.items() + {'Type': 'ScalRotCumScVar'}.items()) return dwtArray(rcwsvar, info=Watt), dwtArray(rswsvar, info=Vatt)
def swt(X, wtf='d4', nlevels='conservative', RetainVJ=False): """ function swt(X, wtf='d4', nlevels='conservative', RetainVJ=False) NAME swt -- Compute the (partial) stationary wavelet transform (SWT). INPUTS X -- set of observations (vector of length NX) wtf -- (optional) wavelet transform filter name (string, case-insensitve or wtf struct). Default: 'd4' nlevels -- (optional) maximum level J0 (integer) or method of calculating J0 (string). Valid values: integer>0 or a valid method name Default: 'conservative' RetainVJ -- (optional) boolean flag to retain V at each decomposition level Default: False OUTPUTS WJt -- SWT wavelet coefficents (J x NW array) dwtArray VJt -- SWT scaling coefficients ((1 or J) x NW vector) dwtArray DESCRIPTION swt calculates the wavelet and scaling coefficients using the stationary wavelet transform (SWT). The optional input arguments have default values: * wtf -- 'd4' filter * nlevels -- 'convservative' --> J0 < log2( N / (L-1) + 1) The output arguments include an info attribute with metadata. info is a dictionary with the following fields: * Transform -- name of transform ('SWT') * WTF -- name of wavelet transform filter or a wtf_s struct. * NX -- number of observations in original series (= length(X)) * NW -- number of wavelet coefficients * J0 -- number of levels of partial decompsition. * Aligned -- Boolean flag indicating whether coefficients are aligned with original series (1 = true) or not (0 = false). * RetainVJ -- Boolean flag indicating whether VJ scaling coefficients at all levels have been retained (1= true) or not (0 = false). EXAMPLE WJt, VJt = swt(X, 'd4', 6) NOTES pages 177-178 of P&W SEE ALSO swtj, swt_filter, swt_choose_nlevels, nargerr, argterr, dwtArray """ # Get a valid wavelet transform filter coefficients struct. wtf_s = wtfilter(wtf) wtfname = wtf_s.Name gt = wtf_s.g ht = wtf_s.h L = wtf_s.L # ensure X is a numpy array X = np.array(X) if len(X.shape) > 1: raise ValueError('SWT: Input array must be one-dimensional') # N = length of original series N = X.size # If nlevels is an integer > 0, set J0 = nlevels. # otherwise, select J0 based on choice method specified. if isinstance(nlevels, str): J0 = swt_choose_nlevels(nlevels, wtfname, N) elif isinstance(nlevels, int): if nlevels > 0: J0 = nlevels else: raise ValueError( 'SWT:negativeJ0, nlevels must be an integer greater than 0.') else: raise ValueError('SWT:invalidNLevelsValue') if (J0 < 0): raise ValueError('SWT:negativeJ0') if (2**J0 > N): raise ValueError('SWT:LargeJ0', 'JO must be < log2(Number of samples).') # NW = length of the extended series = number of coefficients NW = X.size # Initialize the scale (Vin) for first level by setting it equal to X Vin = X # Pre-allocate memory. WJt = np.ndarray((J0, NW), dtype=np.float64) * np.nan if RetainVJ: VJt = np.ndarray((J0, NW), dtype=np.float64) * np.nan else: VJt = np.ndarray((NW), dtype=np.float64) * np.nan # Do the SWT. from swtj import swtj bw = np.ndarray((J0, 2)) * np.nan for j in range(J0): Wt_j, Vout = swtj(Vin, j + 1, ht, gt) WJt[j, :] = Wt_j Vin = Vout if RetainVJ: VJt[j, :] = Vout # boundary values 198 L_j = equivalent_filter_width(L, j + 1) bw[j, 0] = min(L_j - 2, NW - 1) #max index to the left #bw[j,1] = np.nan #Bc are only at the beginning if not RetainVJ: VJt[:] = Vout bv = bw[-1, :] else: bv = bw # Update attributes att = { 'Transform': 'SWT', 'WTF': wtfname, 'N': N, 'NW': NW, 'J0': J0, 'Aligned': False, 'RetainVJ': RetainVJ, 'Type': 'Wavelet', 'BCs': bw } WJt = dwtArray(WJt, info=att) att = { 'Transform': 'SWT', 'WTF': wtfname, 'N': N, 'NW': NW, 'J0': J0, 'Aligned': False, 'RetainVJ': RetainVJ, 'Type': 'Scaling', 'BCs': bv } VJt = dwtArray(VJt, info=att) return WJt, VJt
def swt_cir_shift(WJt, VJ0t, subtract_mean_VJ0t=True): """ shift_swt_coef -- shift the SWT wavelet and scaling coefficients. NAME shift_swt_coef -- Shift the SWT wavelet and scaling coefficients. INPUTS WJt = JxN dwtArray of SWT wavelet coefficents where N = number of time intervals, J = number of levels VJ0t = N dwtArray of SWT scaling coefficients at level J0. subtract_mean_VJ0t = (optional) subtract mean value of scaling coefficient from itself Default: True OUTPUTS W = shifted wavelet coefficients with boundary conditions (dwtArray) V = shifted scaling coefficients with boundary conditions (dwtArray) boundaries = demarcing the circularly shifted SWT coefficients influenced by the circularity conditions bw = Jx2 array with min/max indices of wavelet boundary coefficients bv = Jx2 array with min/max indices of scaling boundary coefficients DESCRIPTION The SWT coefficients are circularly shifted at each level so as to properly align the coefficients with the original data series. See P&W fig 183 SEE ALSO swt, swt_filter multi_yoffset_plot """ # check input if type(WJt) is not dwtArray: raise TypeError('Input must be a dwtArray') if WJt.info['Type'] is not 'Wavelet': raise TypeError( 'First input array does not contain Wavelet coefficients but {} coefficients' .format(WJt.info['Type'])) if type(VJ0t) is not dwtArray: raise TypeError('Input must be a dwtArray') if VJ0t.info['Type'] is not 'Scaling': raise TypeError( 'Second input array does not contain Scaling coefficients but {} coefficients' .format(VJ0t.info['Type'])) wtf_s = wtfilter(WJt.info['WTF']) L = wtf_s.L wtfname = WJt.info['WTF'] N = WJt.info['N'] NW = WJt.info['NW'] J0 = WJt.info['J0'] Nm = min(N, NW) if WJt.info['Aligned']: print( 'WARNING (ante.swt.swt_cir_shift): Wavelet coefficients are already aligned' ) W = WJt else: if WJt != dwtArray([]): W = np.ndarray(WJt.shape) * np.nan bw = np.ndarray((J0, 2)) * np.nan for j in range(J0): # shift wavelet coefficients nuHj = advance_wavelet_filter(wtfname, j + 1) W[j, :] = np.roll(WJt[j, :], nuHj) #Calculate circularly shifted wavelet coefficient boundary indices at jth level L_j = equivalent_filter_width(L, j + 1) bw[j, 0] = L_j - 2 - np.abs(nuHj) #max index to the left bw[j, 1] = Nm - abs(nuHj) #min index to the right W = W[:, :Nm] # Update attributes att = dict(WJt.info.items() + {'Aligned': True, 'BCs': bw}.items()) W = dwtArray(W, info=att) else: # if an empty array was given, do nothing and return it W = WJt if VJ0t.info['Aligned']: print( 'WARNING (ante.swt.swt_cir_shift): Wavelet coefficients are already aligned' ) V = VJ0t else: V = np.ndarray(VJ0t.shape) * np.nan bv = np.ndarray((2, )) * np.nan # shift scaling coefficients if VJ0t != dwtArray([]): nuGj = advance_scaling_filter(wtfname, J0) if subtract_mean_VJ0t: VJ0t = VJ0t - VJ0t.mean() V = np.roll(VJ0t, nuGj) bv[0] = L_j - 2 - np.abs(nuGj) #max index to the left bv[1] = Nm - np.abs(nuGj) #min index to the right # Update attributes att = dict(VJ0t.info.items() + { 'Aligned': True, 'BCs': bv }.items()) V = dwtArray(V, info=att) else: # if an empty array was given, do nothing and return it V = VJ0t return W, V
def iswt_smooth(VJt): """ iswt_smooth -- Calculate smooths at J0 level via inverse stationary wavelet transform (ISWT). NAME iswt_smooth -- Calculate smooths at J0 level via inverse stationary wavelet transform (ISWT). INPUTS VJt = N dwtArray of SWT scaling coefficients at J0 level. OUTPUT SJOt = dwtArray of reconstituted smoothed data series. DESCRIPTION EXAMPLE SJt = iswt_smooth(VJt) SEE ALSO iswtj, iswt, iswt_details, swt_filter, swt """ # Get the wavelet transform filter coefficients. if type(VJt) is not dwtArray: raise TypeError('Input must be a dwtArray') if VJt.info['Type'] is not 'Scaling': raise TypeError( 'Input array does not contain Scaling coefficients but {} coefficients' .format(VJt.info['Type'])) wtfname = VJt.info['WTF'] J0 = VJt.info['J0'] wtf_s = wtfilter(wtfname) gt = wtf_s.g ht = wtf_s.h L = wtf_s.L if len(VJt.shape) > 1: if VJt.info['RetainVJ']: VJt = VJt[-1, :] else: raise TypeError('The input is a multidimensional array but {} SWT\ has been computed with RetainVJ=False. \n') N = VJt.size # initialize arrays zeroj = np.zeros(N) Vin = VJt #import pyximport; pyximport.install() from swtj import iswtj for j in range(J0 - 1, -1, -1): Vout = iswtj(zeroj, Vin, j + 1, ht, gt) Vin = Vout SJt = Vout # boundary values pag.199 P&W L_j = equivalent_filter_width(L, J0) bv = np.array([L_j - 2, -L_j + 1]) # Update attributes att = dict(VJt.info.items() + { 'Transform': 'ISWT', 'Type': 'Smooth', 'BCs': bv }.items()) SJt = dwtArray(SJt, info=att) return SJt
def iswt_details(WJt): """ iswt_details -- Calculate details via inverse stationary wavelet transform (ISWT). NAME iswt_details -- Calculate details via inverse stationary wavelet transform (ISWT). INPUTS WJt - NxJ array of SWT wavelet coefficents where N = number of time points J = number of levels. The array must be a dwtArray (containing the information on the transform) OUTPUT DJt - JxN dwtArray of reconstituted details of data series for J0 scales. att - structure containing ISWT transform attributes. DESCRIPTION The output parameter att is a structure with the following fields: name - name of transform (= 'SWT') wtfname - name of SWT wavelet filter npts - number of observations (= length(X)) J0 - number of levels EXAMPLE DJt = iswt_details(WJt) SEE ALSO iswtj, iswt, iswt_smooth, swt_filter, swt """ # Get a the wavelet transform filter coefficients. if type(WJt) is not dwtArray: raise TypeError('Input must be a dwtArray') if WJt.info['Type'] is not 'Wavelet': raise TypeError( 'Input array does not contain Wavelet coefficients but {} coefficients' .format(WJt.info['Type'])) wtfname = WJt.info['WTF'] wtf_s = wtfilter(wtfname) gt = wtf_s.g ht = wtf_s.h L = wtf_s.L J, N = WJt.shape J0 = J zeroj = np.zeros(N) DJt = np.zeros((J, N)) from swtj import iswtj for j in range(J0 - 1, -1, -1): Vin = zeroj Win = WJt[j, :] for jj in range(j, -1, -1): Vout = iswtj(Win, Vin, jj + 1, ht, gt) Win = zeroj Vin = Vout DJt[j, :] = Vout # boundary values 199 bw = np.ndarray((J0, 2), dtype=np.int16) * np.nan for j in range(J0): #Calculate wavelet coefficient boundary indices at jth level L_j = equivalent_filter_width(L, j + 1) bw[j, 0] = L_j - 2 bw[j, 1] = -L_j + 1 # Update attributes att = dict(WJt.info.items() + { 'Transform': 'ISWT', 'Type': 'Detail', 'BCs': bw }.items()) DJt = dwtArray(DJt, info=att) return DJt