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
def cum4x(w, x, y, z, maxlag=0, nsamp=0, overlap=0, flag='biased', k1=0, k2=0): """ Fourth-order cross-cumulants. Parameters: w,x,y,z - data vectors/matrices with identical dimensions if w,x,y,z are matrices, rather than vectors, columns are assumed to correspond to independent realizations, overlap is set to 0, and samp_seg to the row dimension. maxlag - maximum lag to be computed [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', biased estimates are computed [default] 'unbiased', unbiased estimates are computed. k1,k2 : the fixed lags in C4(m,k1,k2) defaults to 0 Output: y_cum: estimated fourth-order cross cumulant, c4(t1,t2,t3) := cum( w^*(t), x(t+t1), y(t+t2), z^*(t+t3) ) """ (lx, nrecs) = w.shape if (lx, nrecs) != x.shape or (lx, nrecs) != y.shape or (lx, nrecs) != z.shape: raise ValueError('w,x,y,z should have identical dimensions') if lx == 1: lx = nrecs nrecs = 1 if maxlag < 0: raise ValueError('"maxlag" must be non-negative ') if nrecs > 1: nsamp = lx if nsamp <= 0 or nsamp > lx: nsamp = lx if nrecs > 1: overlap = 0 overlap = max(0, min(overlap, 99)) overlap0 = overlap overlap = np.fix(overlap / 100 * nsamp) nadvance = nsamp - overlap if nrecs == 1: nrecs = np.fix((lx - overlap) / nadvance) # 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 sc1 = 1 / nsamp sc2 = sc1 sc12 = sc1 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 sc1 = 1 / (nsamp - abs(k1)) sc2 = 1 / (nsamp - abs(k2)) sc12 = 1 / (nsamp - abs(k1 - k2)) scale = scale.reshape(-1, 1) # estimate second- and fourth-order moments combine y_cum = np.zeros([2 * maxlag + 1, 1]) rind = np.arange(-maxlag, maxlag + 1) ind = np.arange(nsamp) print nrecs for i in xrange(nrecs): tmp = y_cum * 0 R_zy = 0 R_wy = 0 M_wz = 0 ws = w[ind] ws = ws - np.mean(ws) xs = x[ind] xs = xs - np.mean(xs) ys = y[ind] ys = ys - np.mean(ys) cys = np.conj(ys) zs = z[ind] zs = zs - np.mean(zs) ziv = xs * 0 # create the "IV" matrix: offset for second lag if k1 >= 0: ziv[0:nsamp - k1] = ws[0:nsamp - k1] * cys[k1:nsamp] R_wy = R_wy + np.dot(ws[0:nsamp - k1].T, ys[k1:nsamp]) else: ziv[-k1:nsamp] = ws[-k1:nsamp] * cys[0:nsamp + k1] R_wy = R_wy + np.dot(ws[-k1:nsamp].T, ys[0:nsamp + k1]) # create the "IV" matrix: offset for third lag if k2 > 2: ziv[0:nsamp - k2] = ziv[0:nsamp - k2] * zs[k2:nsamp] ziv[nsamp - k2:nsamp] = np.zeros([k2, 1]) M_wz = M_wz + np.dot(ws[0:nsamp - k2].T, zs[k2:nsamp]) else: ziv[-k2:nsamp] = ziv[-k2:nsamp] * zs[0:nsamp + k2] ziv[0:-k2] = np.zeros([-k2, 1]) M_wz = M_wz + np.dot(ws[-k2:nsamp].T, zs[0:nsamp - k2]) if k1 - k2 >= 0: R_zy = R_zy + np.dot(zs[0:nsamp - k1 + k2].T, ys[k1 - k2:nsamp]) else: R_zy = R_zy + np.dot(zs[-k1 + k2:nsamp].T, ys[0:nsamp - k2 + k1]) tmp[zlag] = tmp[zlag] + np.dot(ziv.T, xs) for k in xrange(1, maxlag + 1): tmp[zlag - k] = tmp[zlag - k] + np.dot(ziv[k:nsamp].T, xs[0:nsamp - k]) tmp[zlag + k] = tmp[zlag + k] + np.dot(ziv[0:nsamp - k].T, xs[k:nsamp]) print y_cum.shape y_cum = y_cum + tmp * scale # fourth-order moment estimates done print y_cum.shape R_wx = cum2x(ws, xs, maxlag, nsamp, overlap0, flag) R_zx = cum2x(zs, xs, maxlag + abs(k2), nsamp, overlap0, flag) M_yx = cum2x(cys, xs, maxlag + abs(k1), nsamp, overlap0, flag) y_cum = y_cum - R_zy * R_wx * sc12 - \ R_wy * R_zx[rind - k2 + maxlag + abs(k2)] * sc1 - \ M_wz.T * M_yx[rind - k1 + maxlag + abs(k1)] * sc2 ind = ind + int(nadvance) y_cum = y_cum / nrecs return y_cum
def cum4x(w, x, y, z, maxlag=0, nsamp=0, overlap=0, flag='biased', k1=0, k2=0): """ Fourth-order cross-cumulants. Parameters: w,x,y,z - data vectors/matrices with identical dimensions if w,x,y,z are matrices, rather than vectors, columns are assumed to correspond to independent realizations, overlap is set to 0, and samp_seg to the row dimension. maxlag - maximum lag to be computed [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', biased estimates are computed [default] 'unbiased', unbiased estimates are computed. k1,k2 : the fixed lags in C4(m,k1,k2) defaults to 0 Output: y_cum: estimated fourth-order cross cumulant, c4(t1,t2,t3) := cum( w^*(t), x(t+t1), y(t+t2), z^*(t+t3) ) """ (lx, nrecs) = w.shape if (lx, nrecs) != x.shape or (lx, nrecs) != y.shape or (lx, nrecs) != z.shape: raise ValueError('w,x,y,z should have identical dimensions') if lx == 1: lx = nrecs nrecs = 1 if maxlag < 0: raise ValueError('"maxlag" must be non-negative ') if nrecs > 1: nsamp = lx if nsamp <= 0 or nsamp > lx: nsamp = lx if nrecs > 1: overlap = 0 overlap = max(0,min(overlap,99)) overlap0 = overlap overlap = np.fix(overlap/100 * nsamp) nadvance = nsamp - overlap if nrecs == 1: nrecs = np.fix((lx - overlap)/nadvance) # 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 sc1 = 1/nsamp sc2 = sc1 sc12 = sc1 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 sc1 = 1 / (nsamp - abs(k1)) sc2 = 1 / (nsamp - abs(k2)) sc12 = 1 / (nsamp - abs(k1 - k2)) scale = scale.reshape(-1,1) # estimate second- and fourth-order moments combine y_cum = np.zeros([2*maxlag+1, 1]) rind = np.arange(-maxlag, maxlag+1) ind = np.arange(nsamp) print nrecs for i in xrange(nrecs): tmp = y_cum * 0 R_zy = 0 R_wy = 0 M_wz = 0 ws = w[ind] ws = ws - np.mean(ws) xs = x[ind] xs = xs - np.mean(xs) ys = y[ind] ys = ys - np.mean(ys) cys = np.conj(ys) zs = z[ind] zs = zs - np.mean(zs) ziv = xs * 0 # create the "IV" matrix: offset for second lag if k1 >= 0: ziv[0:nsamp-k1] = ws[0:nsamp-k1] * cys[k1:nsamp] R_wy = R_wy + np.dot(ws[0:nsamp-k1].T, ys[k1:nsamp]) else: ziv[-k1:nsamp] = ws[-k1:nsamp] * cys[0:nsamp+k1] R_wy = R_wy + np.dot(ws[-k1:nsamp].T, ys[0:nsamp+k1]) # create the "IV" matrix: offset for third lag if k2 > 2: ziv[0:nsamp-k2] = ziv[0:nsamp-k2] * zs[k2:nsamp] ziv[nsamp-k2:nsamp] = np.zeros([k2, 1]) M_wz = M_wz + np.dot(ws[0:nsamp-k2].T, zs[k2:nsamp]) else: ziv[-k2:nsamp] = ziv[-k2:nsamp] * zs[0:nsamp+k2] ziv[0:-k2] = np.zeros([-k2, 1]) M_wz = M_wz + np.dot(ws[-k2:nsamp].T, zs[0:nsamp-k2]) if k1-k2 >= 0: R_zy = R_zy + np.dot(zs[0:nsamp-k1+k2].T, ys[k1-k2:nsamp]) else: R_zy = R_zy + np.dot(zs[-k1+k2:nsamp].T, ys[0:nsamp-k2+k1]) tmp[zlag] = tmp[zlag] + np.dot(ziv.T, xs) for k in xrange(1, maxlag+1): tmp[zlag-k] = tmp[zlag-k] + np.dot(ziv[k:nsamp].T, xs[0:nsamp-k]) tmp[zlag+k] = tmp[zlag+k] + np.dot(ziv[0:nsamp-k].T, xs[k:nsamp]) print y_cum.shape y_cum = y_cum + tmp * scale # fourth-order moment estimates done print y_cum.shape R_wx = cum2x(ws, xs, maxlag, nsamp, overlap0, flag) R_zx = cum2x(zs, xs, maxlag+abs(k2), nsamp, overlap0, flag) M_yx = cum2x(cys, xs, maxlag+abs(k1), nsamp, overlap0, flag) y_cum = y_cum - R_zy * R_wx * sc12 - \ R_wy * R_zx[rind - k2 + maxlag + abs(k2)] * sc1 - \ M_wz.T * M_yx[rind - k1 + maxlag + abs(k1)] * sc2 ind = ind + int(nadvance) y_cum = y_cum / nrecs return y_cum