def linedetection(): n = 716 dt = 1.0e-3 df = 1.0 / (dt * n) npi = 4.0 nwin = 10 # line and noise components fline = 50.0 aline = 10.0 noise_amplitude = 1.0 t = np.arange(n) * dt lines = np.array([fline, fline + 2.0 * df]) nlines = len(lines) y = noise_amplitude * normal(size = n) \ + aline * np.cos(2.0 * pi * fline * t) r = pymutt.mtft(series = y, dt = dt, npi = npi, nwin = nwin, kind = 1, paddedlen = 10 * n, dodof = 1, ) Fsortidx = r['F'].argsort() lidx = Fsortidx[-1] linefs = [r['df'] * lidx] # print >> sys.stderr, (linefs, r['df'], n * r['df']) r = pymutt.mtft(series = y, dt = dt, npi = npi, nwin = nwin, kind = 1, paddedlen = 10 * n, dodof = 1, lines = np.array(linefs), ) f = r['df'] * np.arange(len(r['power'])) setout = file('lineprocmtft.dat', 'w') setheader(setout, title = 'line + noise', subtitle = "npi = %.0f nwin = %d" % (npi, nwin) ) for psdkey in ['power', 'reshaped', 'F']: if not r.has_key(psdkey): continue setdata(setout, f, r[psdkey], legend = psdkey) setout.close()
def mtanalyze(data, dt = 1.0, kind = 1, # adaptive: 2 for vanilla hi-res npi = 3.0, nwin = 5, # s.b. 2 * npi - 1 padby = 8, # pad to padby * power-of-2-holding-data nlines = 0, # number of lines to find linedomain = None, # could be a range of frequencies to search doplot = 0, title = None, title2 = None, verbose = 0, ): if padby and padby > 1: paddedlen = 2 while paddedlen < len(data): paddedlen *= 2 paddedlen *= padby else: paddedlen = 0 if verbose: print >> sys.stderr, "original length: %d padded to: %d" \ % (len(data), paddedlen) r = pymutt.mtft(data, dt = dt, npi = npi, nwin = nwin, paddedlen = paddedlen, dodof = (nlines > 0)) r['f'] = r['df'] * np.arange(len(r['power'])) if nlines: # we operate on a copy of r['F'] so we can pass the original up # unaltered Fcpy = np.array(r['F'], copy = 1) flines = [] Fmin = Fcpy.min() - 1.0 # For each line, find the maximum current value of the F-test. # Then zero the F-test values in the region fline +- W/2 before # searching for the next largest value. if verbose: print >> sys.stderr, "\nspectral lines:" while len(flines) < nlines: idxfmax = np.argsort(Fcpy)[-1] fline = r['df'] * idxfmax if not linedomain or \ (fline >= linedomain[0] and fline <= linedomain[1]): flines.append(fline) if verbose: print >> sys.stderr, "%5d %13.6e" % (len(flines), fline) wl = max(0, int(idxfmax - round(0.5 * r['W'] / r['df']))) wr = min(r['n'] - 1, int(idxfmax + round(0.5 * r['W'] / r['df']))) Fcpy[wl:wr] = Fmin if len(flines) > 0: reducedr = pymutt.mtft(data, dt = dt, npi = npi, nwin = nwin, kind = kind, paddedlen = paddedlen, dodof = 1, lines = np.array(flines), ) # added reshaped spectrum values to r r['reshaped'] = reducedr['reshaped'] r['linea'] = reducedr['linea'] r['linevar'] = reducedr['linevar'] if doplot and mpl: if not linedomain: il = 0 ir = r['n'] - 1 else: il = int(floor(linedomain[0] / r['df'])) ir = int(ceil(linedomain[1] / r['df'])) if nlines: mpl.subplot(212) if title2: mpl.title(title2) mpl.plot(r['f'][il:ir], r['F'][il:ir]) mpl.ylabel('F') mpl.xlabel('frequency') if nlines: mpl.subplot(211) if title: mpl.title(title) mpl.plot(r['f'][il:ir], 10.0 * np.log10(r['power'][il:ir])) mpl.ylabel('dB') if r.has_key('reshaped'): mpl.plot(r['f'][il:ir], 10.0 * np.log10(reducedr['reshaped'][il:ir])) mpl.show() return r
# # standard dataset: sine wave at 11.5 Hz plus noise (but it could be anything) # dt = 0.01 n = 430 t = dt * np.arange(n) data = np.random.randn(n) + 0.6 * np.sin(2.0 * 3.141592654 * 11.5 * t) # mpl.plot(data) # mpl.figure() # # simplest processing: assume dt = 1 so frequency domain is [0, 0.5] # r = pymutt.mtft(data) # mpl.plot(r['power']) # # next simplest: use correct dt so frequency has true domain and use # correct frequency in the plot # r = pymutt.mtft(data, dt = dt ) f = np.arange(r['nspec']) * r['df'] # mpl.plot(f, r['power']) #
def main(argv = None): import getopt import traceback if argv is None: argv = sys.argv try: npi = 4.0 nwin = 6 kind = 2 nlines_to_find = 2 padfactor = 8 arglist = "vhW:K:k:l:z:" try: opts, args = getopt.getopt(argv[1:], arglist) except getopt.error, msg: raise Usage(msg) for opt, v in opts: if opt == "-v": pass elif opt == "-h": print >> sys.stdout, __doc__ return 0 elif opt == "-W": npi = float(v) elif opt == "-K": nwin = int(v) elif opt == "-k": kind = int(v) elif opt == "-z": padfactor = int(v) elif opt == "-l": nlines_to_find = int(v) lines = [] dodof = 1 doweights = 1 seriesname = args[0] if len(args) > 0 else "willamette" ts, dt, dtu = getseries(seriesname) serieslength = len(ts) paddedlen = 2 while paddedlen < serieslength: paddedlen *= 2 paddedlen *= padfactor print >> sys.stdout, "dataset %s has %d (%d) samples at %s %s" \ % (seriesname, len(ts), paddedlen, dt, dtu) print >> sys.stdout, " npi: %.1f K: %d lines: %d %s" \ % (npi, nwin, nlines_to_find, ("?", "high-res", "adaptive")[kind]) ts -= nx.mean(ts) plotseries(ts, dx = dt, xunits = dtu, title = seriesname) r = pymutt.mtft(series = ts, dt = dt, npi = npi, nwin = nwin, kind = kind, paddedlen = paddedlen, dodof = dodof, doweights = doweights, lines = nx.array(lines), ) show_contents(r, "original") basetitle = seriesname + (" W %.1f K %d a %d n %d (%d)" % (r['npi'], r['nwin'], r['kind'], len(ts), r['n'])) mtpanel(r, title = basetitle + ": original") tlen = len(ts) t = dt * nx.arange(tlen) A = nx.zeros((tlen, 2 * nlines_to_find + 1)) A[:,0] = 1 flines = [] Fcpy = nx.array(r['F'], copy = 1) for l in range(nlines_to_find): idxfmax = nx.argsort(Fcpy)[-1] fline = r['df'] * idxfmax flines.append(fline) ir = max(0, int(idxfmax + round(r['W'] / r['df']))) il = min(r['n'] - 1, int(idxfmax - round(r['W'] / r['df']))) Fcpy[il:ir] = 0.0 reducedr = pymutt.mtft(series = ts, dt = dt, npi = npi, nwin = nwin, kind = kind, paddedlen = paddedlen, dodof = dodof, lines = nx.array(flines)) show_contents(reducedr, "reshaped") if nlines_to_find > 0: if 0: plotseries(ts, dx = dt, xunits = dtu, title = seriesname + ": reshaped") mtpanel(reducedr, title = basetitle + ": reshaped") mpl.show() return 0
def doit(verbose = 0): # pick a miscellaneous length and then find a much bigger power-of-2 n = 716 dt = 1.0 df = 1.0 / (dt * n) pow2 = ceil(log(5 * n) / log(2.0)) paddedlen = int(pow(2, pow2)) print __doc__ print "here are the actual results for this run:\n" print " test series length padded from %d to %d" % (n, paddedlen) # line and noise components fline = 50 * df aline = 10.0 noise_amplitude = 1.0 t = np.arange(n) * dt lines = np.array([fline, fline + 4.0 * df]) nlines = len(lines) suma = complex(0.0, 0.0) * np.zeros([nlines]) sumF = None sumv = np.zeros([nlines]) trials = 20 print " averaging over %d trials" % trials for i in range(trials): y = noise_amplitude * normal(size = n) \ + aline * np.cos(2.0 * pi * fline * t) r = pymutt.mtft(series = y, dt = dt, npi = 2, nwin = 8, kind = 1, paddedlen = paddedlen, dodof = 1, lines = lines, ) suma += r['linea'] sumv += r['linevar'] if sumF is None: sumF = r['F'] else: sumF += r['F'] print " frequency real imag abs F line var" for i, f in enumerate(lines): amp = suma[i] / trials var = sumv[i] / trials ifrq = int(round(f / r['df'])) Ftest = sumF[ifrq] / trials print " %8.5f %8.3f %8.3f %8.4f %8.1f %10.3e" \ % (f, amp.real, amp.imag, abs(amp), Ftest, var) return 0
def filteredprocess(): n = 937 dt = 1e-3 fu = 80.0 fs = 90.0 yr = bandlimited(n, dt, fu, fs) setout = file('ranproc.dat', 'w') setheader(setout, title = 'filtered normal series', subtitle = "fpass = %.1f fstop = %.1f" % (fu, fs) ) setdata(setout, dt * np.arange(n), yr, legend = 'y(t)') setout.close() npi = 4.0 nwin = 10 setout = file('ranprocmtft.dat', 'w') setheader(setout, title = 'filtered normal series', subtitle = "npi = %.0f nwin = %d" % (npi, nwin) ) r = pymutt.mtft(series = yr, dt = dt, npi = npi, nwin = nwin, kind = 1, paddedlen = 4 * n, dodof = 1, ) f = r['df'] * np.arange(len(r['power'])) for psdkey in ['power', 'dof']: if not r.has_key(psdkey): continue setdata(setout, f, r[psdkey], legend = 'hires ' + psdkey) r = pymutt.mtft(series = yr, dt = dt, npi = npi, nwin = nwin, kind = 2, paddedlen = 4 * n, dodof = 1, ) for psdkey in ['power', 'dof']: if not r.has_key(psdkey): continue setdata(setout, f, r[psdkey], legend = 'adaptive ' + psdkey) yrp = dt * abs(dft.rfft(yr, n = n)) ** 2 df = 1.0 / (n * dt) f = df * np.arange(len(yrp)) setdata(setout, f, yrp / n, legend = 'raw') tscale = 1.0 /np.hanning(n).mean() yrph = dt * abs(dft.rfft(tscale * np.hanning(n) * yr, n = n)) ** 2 setdata(setout, f, yrph / n, legend = 'hanning taper') setout.close()
def doit(verbose = 0): '''This code reproduces figure 512 in Percival and Walden. It (1) analyzes the time series and applies the F-test for spectral lines, (2) extracts the two lines with largest F-test values, and (3) computes the reshaped spectrum. It then displays the F-test and the original and reshaped spectra as in P&W figure 512. ''' print doit.__doc__ global dt, data ts = np.array(data) ts -= ts.mean() paddedlen = 1024 r = pymutt.mtft(series = ts, dt = dt, npi = 4, nwin = 5, kind = 1, paddedlen = paddedlen, dodof = 1, ) Fcpy = np.array(r['F'], copy = 1) flines = [] nlines_to_find = 2 # For each line, find the maximum current value of the F-test. # Then zero the F-test values in the region fline +- W/2 before # searching for the next largest value. for l in range(nlines_to_find): idxfmax = np.argsort(Fcpy)[-1] fline = r['df'] * idxfmax flines.append(fline) ir = max(0, int(idxfmax + round(0.5 * r['W'] / r['df']))) il = min(r['n'] - 1, int(idxfmax - round(0.5 * r['W'] / r['df']))) Fcpy[il:ir] = 0.0 reducedr = pymutt.mtft(series = ts, dt = dt, npi = 4, nwin = 5, kind = 2, paddedlen = paddedlen, dodof = 1, lines = np.array(flines), ) f = r['df'] * np.arange(len(r['power'])) mpl.subplot(211) mpl.title("Compare with Percival and Walden, figure 512") mpl.plot(f, r['F']) for level in (8.6, 18.5): y = level + 0.0 * r['power'] mpl.plot(f, y) mpl.ylabel("F-test") mpl.subplot(212) mpl.plot(f, 10.0 * np.log10(r['power'])) mpl.plot(f, 10.0 * np.log10(reducedr['reshaped'])) mpl.xlabel("f (cycles/year)") mpl.ylabel("dB") mpl.show()