def test(): y = sio.loadmat(here(__file__) + '/demo/ma1.mat')['y'] # The right results are: # "biased": [-0.12250513 0.35963613 1.00586945 0.35963613 -0.12250513] # "unbiaed": [-0.12444965 0.36246791 1.00586945 0.36246791 -0.12444965] print cum2est(y, 2, 128, 0, 'unbiased') print cum2est(y, 2, 128, 0, 'biased') # For the 3rd cumulant: # "biased": [-0.18203039 0.07751503 0.67113035 0.729953 0.07751503] # "unbiased": [-0.18639911 0.07874543 0.67641484 0.74153955 0.07937539] print cum3est(y, 2, 128, 0, 'biased', 1) print cum3est(y, 2, 128, 0, 'unbiased', 1) # For testing the 4th-order cumulant # "biased": [-0.03642083 0.4755026 0.6352588 1.38975232 0.83791117 0.41641134 -0.97386322] # "unbiased": [-0.04011388 0.48736793 0.64948927 1.40734633 0.8445089 0.42303979 -0.99724968] print cum4est(y, 3, 128, 0, 'biased', 1, 1) print cum4est(y, 3, 128, 0, 'unbiased', 1, 1)
def cumest(y, norder=2, maxlag=0 ,nsamp=None, overlap=0, flag='biased' ,k1=0, k2=0): """ Second-, third- or fourth-order cumulants. Parameters: y - time-series - should be a vector norder - cumulant order: 2, 3 or 4 [default = 2] maxlag - maximum cumulant lag to compute [default = 0] samp_seg - samples per segment [default = data_length] overlap - percentage overlap of segments [default = 0] overlap is clipped to the allowed range of [0,99]. flag - 'biased' or 'unbiased' [default = 'biased'] k1,k2 - specify the slice of 3rd or 4th order cumulants Output: y_cum - C2(m) or C3(m,k1) or C4(m,k1,k2), -maxlag <= m <= maxlag depending upon the cumulant order selected """ (ksamp, nrecs) = y.shape if ksamp == 1: ksamp = nrecs nrecs = 1 if norder < 2 or norder > 4: raise ValueError('cumulant order must be 2, 3 or 4') if maxlag < 0: raise ValueError('"maxlag" must be non-negative') if nrecs > 1: nsamp = ksamp if nsamp <= 0 or nsamp > ksamp: nsamp = ksamp if nrecs > 1: overlap = 0 overlap = max(0,min(overlap,99)) # estimate the cumulants if norder == 2: y_cum = cum2est(y, maxlag, nsamp, overlap, flag) elif norder == 3: y_cum = cum3est(y, maxlag, nsamp, overlap, flag, k1) elif norder == 4: y_cum = cum3est(y, maxlag, nsamp, overlap, flag, k1, k2) return y_cum
def cum4est(y, maxlag=0, nsamp=0, overlap=0, flag='biased', k1=0, k2=0): """ CUM4EST Fourth-order cumulants. Parameters: Should be invoked via CUMEST for proper parameter checks y_cum = cum4est (y, maxlag, samp_seg, overlap, flag, k1, k2) Computes sample estimates of fourth-order cumulants via the overlapped segment method. y_cum = cum4est (y, maxlag, samp_seg, overlap, flag, k1, k2) y: input data vector (column) maxlag: maximum lag samp_seg: samples per segment overlap: percentage overlap of segments flag : 'biased', biased estimates are computed : 'unbiased', unbiased estimates are computed. k1,k2 : the fixed lags in C3(m,k1) or C4(m,k1,k2) Output: y_cum : estimated fourth-order cumulant slice C4(m,k1,k2) -maxlag <= m <= maxlag """ (n1, n2) = shape(y, 2) N = n1*n2 overlap0 = overlap overlap = np.fix(overlap/100 * nsamp) nrecord = np.fix((N - overlap)/(nsamp - overlap)) nadvance = nsamp - overlap # scale factors for unbiased estimates nlags = 2 * maxlag + 1 zlag = maxlag tmp = np.zeros([nlags,1]) if flag == 'biased': scale = np.ones([nlags,1])/nsamp else: ind = np.arange(-maxlag, maxlag+1).T kmin = min(0, min(k1, k2)) kmax = max(0,max(k1, k2)) scale = nsamp - np.maximum(ind, kmax) + np.minimum(ind, kmin) scale = np.ones(nlags) / scale scale = scale.reshape(-1,1) mlag = maxlag + max(abs(k1), abs(k2)) mlag = max(mlag, abs(k1-k2) ) mlag1 = mlag + 1 nlag = maxlag m2k2 = np.zeros([2*maxlag+1,1]) if np.any(np.any(np.imag(y) != 0)): complex_flag = 1 else: complex_flag = 0 # estimate second- and fourth-order moments combine y_cum = np.zeros([2*maxlag+1, 1]) R_yy = np.zeros([2*mlag+1, 1]) ind = np.arange(nsamp) for i in xrange(nrecord): tmp = np.zeros([2*maxlag+1, 1]) x = y[ind] x = x.ravel(order='F') - np.mean(x) z = x * 0 cx = np.conj(x) # create the "IV" matrix: offset for second lag if k1 >= 0: z[0:nsamp-k1] = x[0:nsamp-k1] * cx[k1:nsamp] else: z[-k1:nsamp] = x[-k1:nsamp] * cx[0:nsamp+k1] # create the "IV" matrix: offset for third lag if k2 >= 0: z[0:nsamp-k2] = z[0:nsamp-k2] * x[k2:nsamp] z[nsamp-k2:nsamp] = np.zeros([k2, 1]) else: z[-k2:nsamp] = z[-k2:nsamp] * x[0:nsamp+k2] z[0:-k2] = np.zeros([-k2, 1]) tmp[zlag] = tmp[zlag] + np.dot(z.T, x) for k in xrange(1, maxlag+1): tmp[zlag-k] = tmp[zlag-k] + np.dot(z[k:nsamp].T, x[0:nsamp-k]) tmp[zlag+k] = tmp[zlag+k] + np.dot(z[0:nsamp-k].T, x[k:nsamp]) y_cum = y_cum + tmp * scale R_yy = cum2est(x, mlag, nsamp, overlap0, flag) # We need E x(t)x(t+tau) stuff also: if complex_flag: M_yy = cum2x(np.conj(x), x, mlag, nsamp, overlap0, flag) else: M_yy = R_yy y_cum = y_cum - \ R_yy[mlag1+k1-1] * R_yy[mlag1-k2-nlag-1:mlag1-k2+nlag] - \ R_yy[k1-k2+mlag1-1] * R_yy[mlag1-nlag-1:mlag1+nlag] - \ M_yy[mlag1+k2-1].T * M_yy[mlag1-k1-nlag-1:mlag1-k1+nlag] ind = ind + int(nadvance) y_cum = y_cum / nrecord return y_cum