def required_signal_power(power, n=1, confidence=0.99): """ required_signal_power(power, n=1, confidence=0.99): Return the required power of a signal that will cause at least a power 'power' in a power spectrum a fraction 'confidence' of the time. This is the inverse of equation 16 in Groth, 1975, with solves for P_signal. If called with 'power' = P_detect the result is the search sensitivity. If called with 'power' = P_max, then the result is the upper limit on the signal power in the power spectrum. """ prob = 1.0 - confidence def func(x, power=power, prob=prob, n=n): return prob_power_series(power, x, n) - prob def dfunc(x, power=power, n=n): return power_probability(power, x, n) P_signal = newton_raphson(func, dfunc, 0.0001, 100.0) return P_signal
def measure_phase(profile, template, sigma, fwhm): """ measure_phase(profile, template, sigma, fwhm): TOA measurement technique from J. H. Taylor's talk _Pulsar_Timing_and_Relativistic_Gravity_. Routine takes two profiles, the first measured and the second a high S/N template and determines the phase offset of 'profile' from 'template'. Both profiles must have the same number of points. 'sigma' denotes the RMS noise level of the 'profile'. 'fwhm' is the approximate width of the template pulse (0-1). The phase returned is cyclic (i.e. from 0-1). The routine returns a tuple comtaining (tau, tau_err, b, b_err, a). Where 'tau' is the phase, 'B' is the scaling factor, and 'a' is the DC offset. The error values are estimates of the 1 sigma errors. """ from simple_roots import newton_raphson N = len(profile) if not (N == len(template)): print "Lengths of 'profile' and 'template' must" print " be equal in measure_phase()." return 0.0 ft = rfft(profile) p0 = ft[0].real # Nyquist freq ft[0] = complex(ft[0].imag, 0.0) P_k = abs(ft) frotate(P_k, len(ft), 1) Theta_k = np.arctan2(-ft.imag, ft.real) frotate(Theta_k, len(ft), 1) ft = rfft(template) s0 = ft[0].real # Nyquist freq ft[0] = complex(ft[0].imag, 0.0) S_k = abs(ft) frotate(S_k, len(ft), 1) Phi_k = np.arctan2(-ft.imag, ft.real) frotate(Phi_k, len(ft), 1) # Estimate of the noise sigma (This needs to be checked) # Note: Checked 10 Jul 2000. Looks OK. sig = sigma * np.sqrt(N) k = np.arange(len(ft), dtype='d') + 1.0 def fn(tau, k=k, p=P_k, s=S_k, theta=Theta_k, phi=Phi_k): # Since Nyquist freq always has phase = 0.0 k[-1] = 0.0 return np.add.reduce(k * p * s * np.sin(phi - theta + k * tau)) def dfn(tau, k=k, p=P_k, s=S_k, theta=Theta_k, phi=Phi_k): # Since Nyquist freq always has phase = 0.0 k[-1] = 0.0 return np.add.reduce(k * k * p * s * np.cos(phi - theta + k * tau)) numphases = 200 ddchidt = np.zeros(numphases, 'd') phases = np.arange(numphases, dtype='d') / \ float(numphases-1) * TWOPI - PI for i in np.arange(numphases): ddchidt[i] = dfn(phases[i]) maxdphase = phases[np.argmax(ddchidt)] + \ 0.5 * TWOPI / (numphases - 1.0) # Solve for tau tau = newton_raphson(fn, dfn, maxdphase - 0.5 * fwhm * TWOPI, maxdphase + 0.5 * fwhm * TWOPI) # Solve for b c = P_k * S_k * np.cos(Phi_k - Theta_k + k * tau) d = np.add.reduce(S_k**2.0) b = np.add.reduce(c) / d # tau sigma tau_err = sig * np.sqrt(1.0 / (2.0 * b * np.add.reduce(k**2.0 * c))) # b sigma (Note: This seems to be an underestimate...) b_err = sig * np.sqrt(1.0 / (2.0 * d)) # Solve for a a = (p0 - b * s0) / float(N) return (tau / TWOPI, tau_err / TWOPI, b, b_err, a)
def measure_phase(profile, template, sigma, fwhm): """ measure_phase(profile, template, sigma, fwhm): TOA measurement technique from J. H. Taylor's talk _Pulsar_Timing_and_Relativistic_Gravity_. Routine takes two profiles, the first measured and the second a high S/N template and determines the phase offset of 'profile' from 'template'. Both profiles must have the same number of points. 'sigma' denotes the RMS noise level of the 'profile'. 'fwhm' is the approximate width of the template pulse (0-1). The phase returned is cyclic (i.e. from 0-1). The routine returns a tuple comtaining (tau, tau_err, b, b_err, a). Where 'tau' is the phase, 'B' is the scaling factor, and 'a' is the DC offset. The error values are estimates of the 1 sigma errors. """ from simple_roots import newton_raphson N = len(profile) if not (N == len(template)): print "Lengths of 'profile' and 'template' must" print " be equal in measure_phase()." return 0.0 ft = rfft(profile) p0 = ft[0].real # Nyquist freq ft[0] = complex(ft[0].imag, 0.0) P_k = abs(ft) frotate(P_k, len(ft), 1) Theta_k = Num.arctan2(-ft.imag, ft.real) frotate(Theta_k, len(ft), 1) ft = rfft(template) s0 = ft[0].real # Nyquist freq ft[0] = complex(ft[0].imag, 0.0) S_k = abs(ft) frotate(S_k, len(ft), 1) Phi_k = Num.arctan2(-ft.imag, ft.real) frotate(Phi_k, len(ft), 1) # Estimate of the noise sigma (This needs to be checked) # Note: Checked 10 Jul 2000. Looks OK. sig = sigma * Num.sqrt(N) k = Num.arange(len(ft), dtype='d') + 1.0 def fn(tau, k=k, p=P_k, s=S_k, theta=Theta_k, phi=Phi_k): # Since Nyquist freq always has phase = 0.0 k[-1] = 0.0 return Num.add.reduce(k * p * s * Num.sin(phi - theta + k * tau)) def dfn(tau, k=k, p=P_k, s=S_k, theta=Theta_k, phi=Phi_k): # Since Nyquist freq always has phase = 0.0 k[-1] = 0.0 return Num.add.reduce(k * k * p * s * Num.cos(phi - theta + k * tau)) numphases = 200 ddchidt = Num.zeros(numphases, 'd') phases = Num.arange(numphases, dtype='d') / \ float(numphases-1) * TWOPI - PI for i in Num.arange(numphases): ddchidt[i] = dfn(phases[i]) maxdphase = phases[Num.argmax(ddchidt)] + \ 0.5 * TWOPI / (numphases - 1.0) # Solve for tau tau = newton_raphson(fn, dfn, maxdphase - 0.5 * fwhm * TWOPI, maxdphase + 0.5 * fwhm * TWOPI) # Solve for b c = P_k * S_k * Num.cos(Phi_k - Theta_k + k * tau) d = Num.add.reduce(S_k**2.0) b = Num.add.reduce(c) / d # tau sigma tau_err = sig * Num.sqrt(1.0 / (2.0 * b * Num.add.reduce(k**2.0 * c))) # b sigma (Note: This seems to be an underestimate...) b_err = sig * Num.sqrt(1.0 / (2.0 * d)) # Solve for a a = (p0 - b * s0) / float(N) return (tau / TWOPI, tau_err / TWOPI, b, b_err, a)
if (0): # Use the following to generate the xs from simple_roots import newton_raphson rval = 0.0 rs = Num.arange(n+1, dtype=Num.float)/n xs = Num.zeros(n+1, dtype=Num.float) def func(x): return Num.sin(2.0*Num.pi*x)/(2.0*Num.pi) + x - rval def dfunc(x): return Num.cos(2.0*Num.pi*x) + 1 for (ii, rval) in enumerate(rs[:-1]): if (ii==n/2): xs[ii] = 0.5 else: xs[ii] = newton_raphson(func, dfunc, 0.0, 1.0) xs[0] = 0.0 xs[n] = 1.0 cPickle.dump(xs, file("cosine_rand.pickle", "w"), 1) else: pfile = os.path.join(os.environ['PRESTO'], "lib", "python", "cosine_rand.pickle") xs = cPickle.load(file(pfile)) def cosine_rand(num): """cosine_rand(num): Return num phases that are randomly distributed as per a sinusoid with maximum at phase=0 (0 < phase < 1). """ rands = n*Num.random.random(num) indices = rands.astype(Num.int) fracts = rands-indices