def simulate_like(x, dt, nsim=1, seed=None): """simulate nsim light curve arrays like x powerlaw parameters are the average Use seed to create the same underlying light curve that is sampled through a different poisson noise. This allows zero lag light curves with perfect coherence to be simulated """ # 2.2018e+00 2.2170e-01 2.4064e-01 -2.0275e-01 "PhoIndex " # 3.9876e-09 4.3754e-09 5.2287e-09 -3.5220e-09 "norm " psdpar = [1.36e-10, -2.548] nx = len(x) mux = np.nanmean(x) inan = np.isnan(x) sim = az.SimLC(seed) # use the break from Papadakis+95 sim.add_model('broken_powerlaw', [psdpar[0], -1, psdpar[1], 1e-7]) ns = max([2, nsim]) y = [] for ii in range(ns // 2 + 1): sim.simulate(nx * 2, dt, mux, 'rms') y += np.split(sim.x, 2) y = sim.add_noise(np.array(y), seed=None, dt=dt)[:nsim] y[:, inan] = np.nan return y
def calculate_psd__1(): """""" """Simple powerlaw psd, no poisson noise, no binning, no bias correction TEST: calls to fft functions """ n = 512 dt = 1.0 mu = 100.0 nsim = 200 sim = az.SimLC(seed=344551) sim.add_model('powerlaw', [1e-2, -2]) psd = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n, dt, mu, norm='var') psd.append(az.LCurve.calculate_psd(sim.x, dt, 'var')) psd = np.array(psd) fq = psd[0, 0] p = psd[:, 1].mean(0) ps = psd[:, 1].std(0) plt.rcParams['figure.figsize'] = [4, 6] plt.rcParams['font.size'] = 7 os.system('mkdir -p png') plt.errorbar(fq, p, ps, fmt='o') plt.xscale('log') plt.yscale('log') plt.plot(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:]) plt.savefig('png/calculate_psd__1.png')
def test_adding_step(self): sim = az.SimLC() sim.add_model('step', [[2 / 12, 4. / 12, 8 / 12.], [2., 1]]) freq = np.arange(1, 12) / 12. p = sim.calculate_model(freq) pp = np.array([2] * 4 + [1.] * 7) np.testing.assert_array_almost_equal(p, pp)
def _simulate_lc(seed=34789, return_sim=False, dolag=False): """Simulate light curves and split them to segments Args: seed: random seed return_sim: return SimLC object dolag: do lags too? Returns: t, r, e: where each is a list of arrays """ # input # n = sim_input['n'] dt = sim_input['dt'] mean = sim_input['mean'] psdpar = sim_input['psdpar'] norm = sim_input['norm'] gnoise = sim_input['gnoise'] seglen = sim_input['seglen'] sim = az.SimLC(seed=seed) sim.add_model(*psdpar) sim.simulate(16 * n, dt / 4, mean, norm) if dolag: lag, phase = sim_input['lag'], sim_input['phase'] sim.add_model('constant', lag, lag=True) sim.apply_lag(phase) if return_sim: return sim r = sim.x[4 * n:8 * n].reshape((n, 4)).mean(1) t = sim.t[4 * n:8 * n].reshape((n, 4)).mean(1) if dolag: s = sim.y[4 * n:8 * n].reshape((n, 4)).mean(1) #plt.plot(sim.t, sim.x, sim.t, sim.y); plt.show();exit(0) if gnoise is None: # poisson noise # raise NotImplemented else: # gaussian noise # r += np.random.randn(n) * gnoise e = np.ones(n) * gnoise if dolag: s += np.random.randn(n) * gnoise # split to segments # r, idx = az.misc.split_array(r, seglen, index=True) t = [t[i] for i in idx] e = [e[i] for i in idx] if dolag: s = [s[i] for i in idx] if dolag: t = [list(x) for x in zip(t, t)] r = [list(x) for x in zip(r, s)] e = [list(x) for x in zip(e, e)] return t, r, e
def test_lag_array(self): sim = az.SimLC() sim.add_model('powerlaw', [1e-2, -2]) n, mu = 64, 100. sim.simulate(n, 1.0, mu, norm='var') lag = np.zeros(len(sim.x) // 2 + 1) + 4 y = sim.lag_array(sim.x, lag, False, sim.normalized_psd[0]) np.testing.assert_array_almost_equal(sim.x[:-4], y[4:])
def bin_psd__1(): """Simple powerlaw psd, no poisson noise, BINNING, no noise leak TEST: linear vs log binning SUMMARY: 1- logavg does not do better than linear. The applied bias from Papadakis over-corrects the values when averaging a small number of frequencies. It only helps with lowest frequency when averaging >10 bins """ n = 2**12 dt = 1.0 mu = 100.0 nsim = 200 bins = [2, 5, 10, 20, 50] sim = az.SimLC(seed=349851) sim.add_model('powerlaw', [1e-2, -2.]) psd = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n, dt, mu, norm='var') p = az.LCurve.calculate_psd(sim.x[:n], dt, 'var') pb = [] for b in bins: p1 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, logavg=False)[:3] p2 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, logavg=True)[:3] pb.append([p1, p2]) psd.append(pb) plt.rcParams['figure.figsize'] = [14, 4] plt.rcParams['font.size'] = 7 for ib in range(len(bins)): pb = np.array([x[ib] for x in psd]) fq = pb[0, 0, 0] p = np.mean(pb[:, :, 1], 0) ps = np.std(pb[:, :, 1], 0) ax = plt.subplot(1, len(bins), ib + 1) plt.loglog(fq, p[0], '-', color='C0', label='lin, mean') plt.loglog(fq, p[1], '-.', color='C1', label='log, mean') plt.plot(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:], color='C2') plt.legend() plt.title('bin:%d' % bins[ib]) plt.savefig('png/bin_psd__1.png')
def test_apply_lag(self): sim = az.SimLC() sim.add_model('powerlaw', [1e-2, -2]) n, mu = 64, 100. sim.simulate(n, 1.0, mu, norm='var') sim.add_model('constant', 4, lag=True) sim.apply_lag(phase=False) np.testing.assert_array_almost_equal(sim.x[:-4], sim.y[4:])
def phase__1(): """Constant phase lag, no binning, no noise, RED NOISE LEAK TEST: phases from segments without noise, i.e with leak SUMMARY: 1. taper helps alot! both in the scatter and bias """ n = 2**12 dt = 1.0 mu = 100.0 lag = 0.5 nsim = 200 sim = az.SimLC(seed=463284) sim.add_model('powerlaw', [1e-2, -2.]) sim.add_model('constant', lag, lag=True) lag = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') sim.apply_lag(phase=True) l1 = az.LCurve.calculate_lag(sim.y[:n], sim.x[:n], dt, phase=True) l2 = az.LCurve.calculate_lag(sim.y[:n], sim.x[:n], dt, phase=True, taper=True) lag.append([l1, l2]) lag = np.array(lag) fq = lag[0, 0, 0] l = lag[:, :, 1].mean(0) lp = np.percentile(lag[:, :, 1], [50, 16, 100 - 16], 0) plt.rcParams['figure.figsize'] = [8, 4] plt.rcParams['font.size'] = 7 ax = plt.subplot(121) plt.plot(fq, lp[0, 0], color='C0') plt.title('no-taper') plt.fill_between(fq, lp[1, 0], lp[2, 0], alpha=0.5, color='C1') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') ax = plt.subplot(122) plt.plot(fq, lp[0, 1], color='C0') plt.title('taper') plt.fill_between(fq, lp[1, 1], lp[2, 1], alpha=0.5, color='C1') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') plt.savefig('png/phase__1.png')
def calculate_psd__3(): """Simple powerlaw psd, no poisson noise, no binning, RED NOISE LEAK Use psd index of -3 for extreme effect TEST: tapering SUMMARY: 1- Where there is red noise leak, tapering clearly helps. 2- The median of the simulations is slightly biased, while the mean is not 3- The effect is strongest when gamma >~2 """ n = 512 dt = 1.0 mu = 100.0 nsim = 200 sim = az.SimLC(seed=349851) sim.add_model('powerlaw', [1e-2, -2.5]) psd = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') p1 = az.LCurve.calculate_psd(sim.x[:n], dt, 'var') p2 = az.LCurve.calculate_psd(sim.x[:n], dt, 'var', taper=True) psd.append([p1, p2]) psd = np.array(psd) fq = psd[0, 0, 0] p = np.mean(psd[:, :, 1], 0) pmd = np.median(psd[:, :, 1], 0) ps = np.std(psd[:, :, 1], 0) plt.rcParams['figure.figsize'] = [5, 5] plt.rcParams['font.size'] = 7 os.system('mkdir -p png') plt.loglog(fq, p[0], 'o', color='C0', alpha=0.3, label='no-taper, mean') plt.loglog(fq, pmd[0], 's', color='C3', alpha=0.3, label='no-taper, median') plt.loglog(fq, p[1], 'o', color='C1', alpha=0.3, label='with-taper') plt.loglog(fq, pmd[1], 's', color='C4', alpha=0.3, label='with-taper, median') plt.plot(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:], color='C2') plt.legend() plt.savefig('png/calculate_psd__3.png')
def test_broekn_powerlaw_psd(self): sim = az.SimLC() sim.add_model('broken_powerlaw', [1e-2, -1, -2, 0.5]) freq = np.arange(1, 6) / 6. p = sim.calculate_model(freq) pp = np.zeros_like(freq) ii = freq < 0.5 pp[ii] = (freq[ii] / 0.5)**-1 pp[~ii] = (freq[~ii] / 0.5)**-2 pp *= 1e-2 * 0.5**-2 np.testing.assert_array_almost_equal(p, pp)
def phase__2(): """Constant phase lag, no binning, NOISE, RED NOISE LEAK TEST: phases from segments (i.e. leak) with noise, SUMMARY: 1. again, taper helps alot! The scatter is very small in intermediate frequencies not affected by noise, unlike in no-tpaer case. """ n = 2**12 dt = 1.0 mu = 100.0 lag = 0.5 nsim = 200 sim = az.SimLC(seed=4634) sim.add_model('powerlaw', [1e-2, -2.]) sim.add_model('constant', lag, lag=True) lag = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') sim.apply_lag(phase=True) scale_fac = 100 x = np.random.poisson(sim.x[:n] * scale_fac) / scale_fac y = np.random.poisson(sim.y[:n] * scale_fac) / scale_fac l1 = az.LCurve.calculate_lag(y, x, dt, phase=True) l2 = az.LCurve.calculate_lag(y, x, dt, phase=True, taper=True) lag.append([l1, l2]) lag = np.array(lag) fq = lag[0, 0, 0] l = lag[:, :, 1].mean(0) lp = np.percentile(lag[:, :, 1], [50, 16, 100 - 16], 0) plt.rcParams['figure.figsize'] = [8, 4] plt.rcParams['font.size'] = 7 ax = plt.subplot(121) plt.plot(fq, lp[0, 0], color='C0') plt.title('no-taper') plt.fill_between(fq, lp[1, 0], lp[2, 0], alpha=0.5, color='C1') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') ax = plt.subplot(122) plt.plot(fq, lp[0, 1], color='C0') plt.title('taper') plt.fill_between(fq, lp[1, 1], lp[2, 1], alpha=0.5, color='C1') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') plt.savefig('png/phase__2.png')
def test_simulate(self): sim = az.SimLC() sim.add_model('powerlaw', [1e-2, -2]) n, mu = 128, 100. norms = ['var', 'leahy', 'rms'] expos = [0, 1, 2] for norm, expo in zip(norms, expos): sim.simulate(n, 1.0, mu, norm=norm) p = (2. / (n * mu**expo)) * np.abs(np.fft.rfft(sim.x))**2 np.testing.assert_almost_equal( (p[1:] / sim.normalized_psd[1][1:]).mean(), 1, 0)
def test_calculate_lag(self): sim = az.SimLC() norm = 'rms' expo = 2 sim.add_model('powerlaw', [1e-4, -2]) n, mu = 128, 100. sim.simulate(n, 1.0, mu, norm=norm) sim.add_model('constant', 6, lag=True) sim.apply_lag(phase=False) p = az.LCurve.calculate_lag(sim.y, sim.x, 1.0, fqbin=None, taper=False) np.testing.assert_array_almost_equal(sim.normalized_lag[0][1:-1], p[0]) # do the first 5 before the oscillation kicks in. np.testing.assert_array_almost_equal(np.zeros(5) + 6, p[1][:5])
def calculate_psd__2(): """""" """Simple powerlaw psd, POISSON/GAUSS noise, no binning, no bias correction TEST: noise level estimates """ n = 512 dt = 1.0 mu = 100.0 nsim = 200 sim = az.SimLC(seed=34451) sim.add_model('powerlaw', [1e-2, -2]) psd = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n, dt, mu, norm='var') x = np.random.poisson(sim.x) p1 = az.LCurve.calculate_psd(x, dt, 'var') x = np.random.normal(sim.x, mu * 0.01) p2 = az.LCurve.calculate_psd(x, dt, 'var', rerr=x * 0 + mu * 0.01) psd.append([p1, p2]) psd = np.array(psd) fq = psd[0, 0, 0] p = psd[:, :, 1].mean(0) ps = psd[:, :, 1].std(0) pn = psd[:, :, 2].mean(0) plt.rcParams['figure.figsize'] = [5, 5] plt.rcParams['font.size'] = 7 os.system('mkdir -p png') plt.loglog(fq, p[0], 'o', color='C0', alpha=0.3) plt.plot(fq, pn[0], color='C0') plt.loglog(fq, p[1], 'o', color='C1', alpha=0.3) plt.plot(fq, pn[1], color='C1') plt.plot(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:], color='C2') plt.savefig('png/calculate_psd__2.png')
def simulate_lc(n, dt, mu, lag, seed=3343, bkp=None, phase=True): np.random.seed(seed) sim = az.SimLC(32) if bkp is None: bkp = [1e-4, -1, -2, 5e-2] sim.add_model('broken_powerlaw', bkp) sim.add_model('constant', lag, lag=True) sim.simulate(n*3, dt, mu, 'rms') sim.apply_lag(phase=phase) tarr, rarr, sarr = sim.t[:n], sim.x[:n], sim.y[:n] #plt.plot(tarr, rarr, tarr, sarr) rarr = np.random.poisson(rarr) sarr = np.random.poisson(sarr) rerr = rarr*0 + np.mean(rarr**0.5) serr = sarr*0 + np.mean(sarr**0.5) #plt.errorbar(tarr, rarr, rerr, alpha=0.4) #lt.errorbar(tarr, sarr, serr, alpha=0.4) #plt.show() return tarr, rarr, rerr, sarr, serr, sim
def test_psdf_sim__pl(): # works with bias and the factor of 2 # or with no-bias and without the fator of 2 nsim = 100 n, dt, mu, lag = 2**8, 1.0, 10000, 1.0 sim = az.SimLC(323) sim.add_model('powerlaw', [1e-4, -2]) #sim.add_model('bending_powerlaw', [1e-4, -2, 5e-2]) fql = np.array([0.5/n, 1]) p0 = np.array([-9., -2.]) p0 = np.array([-9., -2., -4.5]) P = [] for isim in range(1, nsim+1): sim.simulate(n, dt, mu, 'rms') tarr, rarr = sim.t[:n], sim.x[:n] rerr = rarr *0 #rarr = np.random.poisson(rarr) #rerr = rarr*0 + np.mean(rarr**0.5) pmod = fqlag.Psdf(tarr, rarr, rerr, fql, 'bpl', dt=None) p = maximize(pmod, p0) P.append(p) P = np.array(P) #from IPython import embed; embed();exit(0) f,fp = sim.normalized_psd #plt.semilogx(f[1:-1], np.log(fp[1:-1])) plt.loglog(f[1:-1], fp[1:-1]) fq = np.logspace(np.log10(fql[0]), np.log10(fql[-1]), 40) pp = np.array([pmod.psd_func(fq, x[0]) for x in P]) pm,ps = pp.mean(0), pp.std(0) plt.fill_between(fq, pm-ps, pm+ps, alpha=0.5) plt.show()
def test_psd_sim(): # no bias needed. works without the fator of 2 # so not using the factor of 2 is the correct way, and when doing the logs # no bias correction is needed nsim = 20 n, dt, mu, lag = 2**8, 1.0, 10000, 1.0 sim = az.SimLC(323) sim.add_model('broken_powerlaw', [1e-4, -1, -2, 1e-3]) fql = np.concatenate([[0.1/n], np.logspace(np.log10(1.1/n), np.log10(0.4), 7)[1:], [2.]]) p0 = fql[1:]*0+0.1 P = [] for isim in range(1, nsim+1): sim.simulate(n, dt, mu, 'rms') tarr, rarr = sim.t[:n], sim.x[:n] rerr = rarr *0 #rarr = np.random.poisson(rarr) #rerr = rarr*0 + np.mean(rarr**0.5) #pmod = fqlag.lPsd(tarr, rarr, rerr, fql) pmod = fqlag.Psd(tarr, rarr, rerr, fql) p = maximize(pmod, p0) P.append(p) P = np.array(P) #from IPython import embed; embed();exit(0) f,fp = sim.normalized_psd #plt.semilogx(f[1:-1], np.log(fp[1:-1])) plt.loglog(f[1:-1], fp[1:-1]) fq = (fql[1:] + fql[:-1])/2 plt.errorbar(fq, P.mean(0), P.std(0), fmt='o-') plt.show()
def phase__3(): """Constant phase lag, BINNING, NOISE, RED NOISE LEAK TEST: leak with binning SUMMARY: 1. no-taper is biased. 2. taper has less scatter in intermediate frequencies and is not biased. """ n = 2**12 dt = 1.0 mu = 100.0 lag = 0.5 nsim = 200 bins = [2, 5, 10, 20, 50] sim = az.SimLC(seed=463444) sim.add_model('powerlaw', [1e-2, -2.]) sim.add_model('constant', lag, lag=True) lag = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') sim.apply_lag(phase=True) scale_fac = 100 x = np.random.poisson(sim.x[:n] * scale_fac) / scale_fac y = np.random.poisson(sim.y[:n] * scale_fac) / scale_fac lb = [] for b in bins: l1 = az.LCurve.calculate_lag(y, x, dt, phase=True, fqbin={'by_n': [b, 1]}, rerr=(y / scale_fac)**0.5, Rerr=(x / scale_fac)**0.5) l2 = az.LCurve.calculate_lag(y, x, dt, phase=True, taper=True, fqbin={'by_n': [b, 1]}, rerr=(y / scale_fac)**0.5, Rerr=(x / scale_fac)**0.5) lb.append([l1, l2]) lag.append(lb) plt.rcParams['figure.figsize'] = [14, 10] plt.rcParams['font.size'] = 7 for ib in range(len(bins)): lb = np.array([[m[:3] for m in l[ib]] for l in lag]) fq = lb[0, 0, 0] lp = np.percentile(lb[:, :, 1], [50, 16, 100 - 16], 0) ax = plt.subplot(2, len(bins), ib + 1) plt.plot(fq, lp[0, 0], color='C0', lw=0.5) plt.fill_between(fq, lp[1, 0], lp[2, 0], alpha=0.5, color='C1') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') ax.set_ylim([-1, 1]) plt.title('bin: %d, no-taper' % bins[ib]) ax = plt.subplot(2, len(bins), len(bins) + ib + 1) plt.plot(fq, lp[0, 1], color='C0', lw=0.5) plt.title('taper') plt.fill_between(fq, lp[1, 1], lp[2, 1], alpha=0.5, color='C1') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') ax.set_ylim([-1, 1]) plt.savefig('png/phase__3.png')
def test_powerlaw_psd(self): sim = az.SimLC() sim.add_model('powerlaw', [1e-2, -2]) freq = np.arange(1, 6) / 6. p = sim.calculate_model(freq) np.testing.assert_array_almost_equal(p, 1e-2 * freq**-2)
def bin_psd__2(): """Simple powerlaw psd, no poisson noise, BINNING, LEAK TEST: linear vs log binning, with leak/tapering SUMMARY: 1- Similar to bin_psd__1. logavg is overall slightly better than linear at the lowerst frequencies, but it is biased when num. of averaged freq is <~+10 2- taper is always better as we saw in calculate_psd simulations. """ n = 2**12 dt = 1.0 mu = 100.0 nsim = 200 bins = [2, 10, 50] sim = az.SimLC(seed=351) sim.add_model('powerlaw', [1e-2, -2.]) psd = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') p = az.LCurve.calculate_psd(sim.x[:n], dt, 'var') psd.append([]) pb = [] for b in bins: p1 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, logavg=False)[:3] p2 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, logavg=True)[:3] pb.append([p1, p2]) psd[-1].append(pb) pb = [] p = az.LCurve.calculate_psd(sim.x[:n], dt, 'var', taper=True) for b in bins: p1 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, logavg=False)[:3] p2 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, logavg=True)[:3] pb.append([p1, p2]) psd[-1].append(pb) plt.rcParams['figure.figsize'] = [14, 4] plt.rcParams['font.size'] = 7 for ib in range(len(bins)): pb = np.array([[y[ib] for y in x] for x in psd]) fq = pb[0, 0, 0, 0] p = np.mean(pb[:, :, :, 1], 0) ps = np.std(pb[:, :, :, 1], 0) ax = plt.subplot(1, len(bins), ib + 1) plt.loglog(fq, p[0, 0], '-', color='C0', label='lin, no-taper') plt.loglog(fq, p[0, 1], '-.', color='C1', label='log, no-taper') plt.loglog(fq, p[1, 0], '-', color='C2', label='lin, taper') plt.loglog(fq, p[1, 1], '-.', color='C3', label='log, taper') plt.plot(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:], color='C4') plt.legend() plt.title('bin:%d' % bins[ib]) plt.savefig('png/bin_psd__2.png')
def simulate_psdf_cython_3(): """Run a simple plag psdf simulation. do_sig=0; ifunc=13 PL + LOR """ # input # n = sim_input['n'] dt = sim_input['dt'] mean = sim_input['mean'] norm = sim_input['norm'] gnoise = sim_input['gnoise'] seglen = sim_input['seglen'] psdpar = [['powerlaw', [0.08, -2]], ['lorentz', [50, 8e-2, 1e-2]]] sim = az.SimLC(seed=None) sim.add_model(*psdpar[0]) sim.add_model(psdpar[1][0], psdpar[1][1], clear=False) # plt.ion();embed();exit(0) # sim.simulate(16*n, dt/4, mean, norm) # fm, pm = sim.psd_model[:,1:] inorm = 0 if norm == 'var' else 1 if norm == 'leahy' else 2 sims = [] for isim in range(1, args.nsim + 1): az.misc.print_progress(isim, args.nsim + 1, isim == args.nsim) # simulate lc # sim.simulate(16 * n, dt / 4, mean, norm) r = sim.x[4 * n:8 * n].reshape((n, 4)).mean(1) t = sim.t[4 * n:8 * n].reshape((n, 4)).mean(1) r += np.random.randn(n) * gnoise e = np.ones(n) * gnoise R, idx = az.misc.split_array(r, seglen, index=True) T = [t[i] for i in idx] E = [e[i] for i in idx] # get frequncy bins # fqL, fq = _get_fqL(T) fqL = fqL[[0, -1]] model = plag._plag.psdf(T[0], R[0], E[0], dt, fqL, inorm, 0, 13, 50) p0 = np.array([0.1, -2, 3, -2.5, -3.5]) #res = opt.minimize(neg_lnlike, p0, args=(model,), method='Powell') res = opt.minimize(neg_dlnlike, p0, args=(model, ), jac=True, method='L-BFGS-B', bounds=[(-5, 5)] * 5) sims.append(res.x) sims = np.array(sims) smod = np.array([model.calculate_model(s) for s in sims]) fs = smod[0, 0] ms, ss = smod[:, 1].mean(0), smod[:, 1].std(0) fm, pm = sim.normalized_psd[:, 1:] ii = np.logical_and(fm > fqL[0], fm < fqL[-1]) fm, pm = fm[ii], pm[ii] plt.semilogx(fm, np.log(pm), lw=4) plt.fill_between(fs, np.log(ms - ss), np.log(ms + ss), alpha=0.4) plt.savefig('psdf_cython_3.png') np.savez('psdf_cython_3.npz', sims=sims, fqL=fqL, sim_input=sim_input, smod=smod)
def test_calculate_lag__sim(self): """Do simple lc simulations and calculated lag Note: 1- No poisson noise is included in the following. 2- Red noise leak can affect lag measurements too. The main effect is that when using steep powerlaw PSD, the lag is underestimated (closer to zero). The effect goes away when using a broken powerlaw PSD. This is the wether binning is used or not. 3- Tapering the light curve with some function (e.g. hanning) reduces the bias significantly except at the lowest frequencies. where it remains. This is true wether binning is used or not. 4- The bias in the lowest frequency is reduced by averaging the log of the cross spectrum rather than the cross spectrum itself. Conclusion: Taper the light curves comment the first line to run """ return np.random.seed(4567) sim = az.SimLC() norm = 'var' expo = {'var': 0, 'leahy': 1, 'rms': 2} sim.add_model('powerlaw', [1e-1, -2]) #sim.add_model('broken_powerlaw', [1e-1, 0, -2, 1e-2]) sim.add_model('constant', 2, lag=True) #sim.add_model('lorentz', [2, 0, 2e-1], lag=True) n, mu = 512, 100. def taper(x): xm = np.mean(x) return (x - xm) * np.hanning(len(x)) + xm L = [] for i in range(200): sim.simulate(4 * n, 1.0, mu, norm=norm) sim.apply_lag(phase=False) s, i = az.misc.split_array(sim.y[:n], 64) S, i = az.misc.split_array(sim.x[:n], 64) s = [taper(x) for x in s] S = [taper(x) for x in S] l = az.LCurve.calculate_lag(s, S, 1.0, {'by_n': [2, 1]}) #l = az.LCurve.calculate_lag(s, S, 1.0) L.append(l[:3]) L = np.array(L) fm, lm = sim.normalized_lag[0][1:-1], sim.normalized_lag[1][1:-1] import pylab as plt fq = l[0] plt.semilogx(fm, lm) plt.plot(fq, np.mean(L[:, 1, :], 0), 'o-', color='C2') plt.plot(fq, np.median(L[:, 1, :], 0), color='C3') plt.plot(fq, L[:, 1, :].mean(0) + L[:, 1, :].std(0), '--', color='C2') plt.plot(fq, L[:, 1, :].mean(0) - L[:, 1, :].std(0), '--', color='C2') plt.plot(fq, L[:, 1, :].mean(0) + L[:, 2, :].mean(0), '-.', color='C3') plt.plot(fq, L[:, 1, :].mean(0) - L[:, 2, :].mean(0), '-.', color='C3') plt.show()
def test_bin_psd__sim(self): """Do simple lc simulations and calculated psd Mostly to test the logavg option. The testing is done to compare the errors. 1- Whenever logavg=True is used, bias correciton needs to be applied. 2- This simulations are very sensitive to red noise leak. This is clear from the dependence of the required 'bias' on the driving psd slope when using a singel powerlaw model. If we control for rednoise leak by using a broken powerlaw as a driving psd, things are better. 3- Leak aside, logavg=True (with bias correction) does better particulalry when using a single long segment, and averaging multiple neighboring frequencies. 4- Tapering might work. The psd need to be renormalized to componsate for the reduced variability power (hanning for example reduces power by ~0.62; from ratio of rms for random while noise) Conclusion: Always use logavg=True; if the psd slope is high, use a tapering window to reduce read noise leak, Not sure if that works though. To plot, comments the return line P1 is for simulations with logavg=True, the P2 for logavg=False """ return np.random.seed(1234) sim = az.SimLC() norm = 'var' expo = {'var': 0, 'leahy': 1, 'rms': 2} sim.add_model('powerlaw', [1e-1, -2]) #sim.add_model('broken_powerlaw', [1e-1, 0, -2, 1e-2]) n, mu = 512, 100. P1, P2 = [], [] for i in range(200): sim.simulate(4 * n, 1.0, mu, norm=norm) s, i = az.misc.split_array(sim.x[:n], 0) p0 = az.LCurve.calculate_psd(s, 1.0, norm) p1 = az.LCurve.bin_psd(p0[0], p0[1], {'by_n': [10, 1]}, logavg=True) p2 = az.LCurve.bin_psd(p0[0], p0[1], {'by_n': [10, 1]}, logavg=False) P1.append(p1[:3]) P2.append(p2[:3]) P1, P2 = np.array(P1), np.array(P2) fm, pm = sim.normalized_psd[0][1:-1], sim.normalized_psd[1][1:-1] import pylab as plt PP, pp = [P1, P2], [p1, p2] for i in range(2): plt.subplot(1, 2, i + 1) plt.loglog(fm, pm) P, p = PP[i], pp[i] plt.plot(p[0], P[:, 1, :].mean(0), color='C2') plt.plot(p[0], np.median(P[:, 1, :], 0), color='C3') plt.title('Log' if i == 0 else 'nolog') plt.plot(p[0], P[:, 1, :].mean(0) + P[:, 1, :].std(0), '--', color='C2') plt.plot(p[0], P[:, 1, :].mean(0) - P[:, 1, :].std(0), '--', color='C2') plt.plot(p[0], P[:, 1, :].mean(0) + P[:, 2, :].mean(0), '-.', color='C3') plt.plot(p[0], P[:, 1, :].mean(0) - P[:, 2, :].mean(0), '-.', color='C3') plt.show()
def bin_psd__3(): """Simple powerlaw psd, POISSON, BINNING, LEAK TEST: linear vs log binning, with leak/tapering, with noise SUMMARY: 1- logavg and taper do the best 2- logavg on noise doesn't matter a lot, 3- The bias in the first frequency is high. it is not noise-leak, somehow """ n = 2**12 dt = 1.0 mu = 1000.0 nsim = 200 bins = [2, 10, 50] sim = az.SimLC(seed=123351) sim.add_model('powerlaw', [1e-2, -2.]) psd = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') x = np.random.poisson(sim.x[:n] * 20) / 20 # use different sampling dt, so we reduce the noise a little bit p = az.LCurve.calculate_psd(x, dt, 'var', rerr=(x / 20)**0.5) psd.append([]) pb = [] for b in bins: p1 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, noise=p[2], logavg=False) p2 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, noise=p[2], logavg=True) p1 = np.vstack([p1[:3], p1[3]['noise']]) p2 = np.vstack([p2[:3], p2[3]['noise']]) pb.append([p1, p2]) psd[-1].append(pb) pb = [] p = az.LCurve.calculate_psd(x, dt, 'var', taper=True, rerr=(x / 20)**0.5) for b in bins: p1 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, noise=p[2], logavg=False) p2 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, noise=p[2], logavg=True) p1 = np.vstack([p1[:3], p1[3]['noise']]) p2 = np.vstack([p2[:3], p2[3]['noise']]) pb.append([p1, p2]) psd[-1].append(pb) plt.rcParams['figure.figsize'] = [14, 8] plt.rcParams['font.size'] = 7 for ib in range(len(bins)): pb = np.array([[y[ib] for y in x] for x in psd]) fq = pb[0, 0, 0, 0] p = np.mean(pb[:, :, :, 1], 0) ps = np.std(pb[:, :, :, 1], 0) pe = np.mean(pb[:, :, :, 2], 0) pn = np.mean(pb[:, :, :, 3], 0) ax = plt.subplot(4, len(bins), ib + 1) plt.loglog(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:]) plt.errorbar(fq, p[0, 0], ps[0, 0], label='lin, no-taper', lw=0.5) plt.fill_between(fq, p[0, 0] - pe[0, 0], p[0, 0] + pe[0, 0], alpha=0.6) plt.plot(fq, pn[0, 0]) plt.legend() plt.title('bin %d' % bins[ib]) ax.set_xlim([2e-4, 0.5]) plt.ylim([50, 5e5]) ax = plt.subplot(4, len(bins), len(bins) + ib + 1) plt.loglog(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:]) plt.errorbar(fq, p[0, 1], ps[0, 1], label='log, no-taper', lw=0.5) plt.fill_between(fq, p[0, 1] - pe[0, 1], p[0, 1] + pe[0, 1], alpha=0.6) plt.plot(fq, pn[0, 1]) plt.legend() ax.set_xlim([2e-4, 0.5]) plt.ylim([50, 5e5]) ax = plt.subplot(4, len(bins), 2 * len(bins) + ib + 1) plt.loglog(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:]) plt.errorbar(fq, p[1, 0], ps[1, 0], label='lin, taper', lw=0.5) plt.fill_between(fq, p[1, 0] - pe[1, 0], p[1, 0] + pe[1, 0], alpha=0.6) plt.plot(fq, pn[1, 0]) plt.legend() ax.set_xlim([2e-4, 0.5]) plt.ylim([50, 5e5]) ax = plt.subplot(4, len(bins), 3 * len(bins) + ib + 1) plt.loglog(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:]) plt.errorbar(fq, p[1, 1], ps[1, 1], label='log, taper', lw=0.5) plt.fill_between(fq, p[1, 1] - pe[1, 1], p[1, 1] + pe[1, 1], alpha=0.6) plt.plot(fq, pn[1, 1]) plt.legend() ax.set_xlim([2e-4, 0.5]) plt.ylim([50, 5e5]) plt.title('bin:%d' % bins[ib]) plt.savefig('png/bin_psd__3.png')
def lag__4(): """Similar to phase__4, using lags SUMMRY: 1. This is generally similar to the phase case, but 2. The changing phase and phase wraps can mess things up. It could be worth doing calculations in phase. """ n = 2**14 dt = 1.0 mu = 100.0 lag = 30 nsim = 200 bins = [2, 10, 50] sim = az.SimLC(seed=463104) #sim.add_model('powerlaw', [1e-2, -2.]) sim.add_model('broken_powerlaw', [5e-3, -1, -2, 1e-4]) sim.add_model('constant', lag, lag=True) lag = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') sim.apply_lag(phase=False) scale_fac = 1000 x = np.random.poisson(sim.x[:n] * scale_fac) / scale_fac y = np.random.poisson(sim.y[:n] * scale_fac) / scale_fac lb = [] for b in bins: l1 = az.LCurve.calculate_lag(y, x, dt, phase=False, fqbin={'by_n': [b, 1]}, rerr=(y / scale_fac)**0.5, Rerr=(x / scale_fac)**0.5) l1 = list(l1[:3]) + [l1[3][k] for k in ['coh', 'coh_e']] l2 = az.LCurve.calculate_lag(y, x, dt, phase=False, taper=True, fqbin={'by_n': [b, 1]}, rerr=(y / scale_fac)**0.5, Rerr=(x / scale_fac)**0.5) l2 = list(l2[:3]) + [l2[3][k] for k in ['coh', 'coh_e']] lb.append([l1, l2]) lag.append(lb) plt.rcParams['figure.figsize'] = [14, 10] plt.rcParams['font.size'] = 7 for ib in range(len(bins)): lb = np.array([[m for m in l[ib]] for l in lag]) fq = lb[0, 0, 0] lp = np.percentile(lb, [50, 16, 100 - 16], 0) le = np.median(lb[:, :, 2], 0) he = np.median(lb[:, :, 4], 0) ax = plt.subplot(4, len(bins), ib + 1) plt.plot(fq, lp[0, 0, 1], color='C0', lw=0.5) plt.fill_between(fq, lp[1, 0, 1], lp[2, 0, 1], alpha=0.5, color='C1') plt.fill_between(fq, lp[0, 0, 1] - le[0], lp[0, 0, 1] + le[0], alpha=0.5, color='C3') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') ax.set_ylim([-100, 100]) plt.title('bin: %d, no-taper' % bins[ib]) ax = plt.subplot(4, len(bins), len(bins) + ib + 1) plt.plot(fq, lp[0, 0, 3], color='C0', lw=0.5) plt.fill_between(fq, lp[1, 0, 3], lp[2, 0, 3], alpha=0.5, color='C1') plt.fill_between(fq, lp[0, 0, 3] - he[0], lp[0, 0, 3] + he[0], alpha=0.5, color='C3') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[0, 1:] * 0 + 1, color='C2') ax.set_xscale('log') ax.set_ylim([-1, 2]) ax = plt.subplot(4, len(bins), 2 * len(bins) + ib + 1) plt.plot(fq, lp[0, 1, 1], color='C0', lw=0.5) plt.title('taper') plt.fill_between(fq, lp[1, 1, 1], lp[2, 1, 1], alpha=0.5, color='C1') plt.fill_between(fq, lp[0, 1, 1] - le[1], lp[0, 1, 1] + le[1], alpha=0.5, color='C3') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') ax.set_ylim([-100, 100]) ax = plt.subplot(4, len(bins), 3 * len(bins) + ib + 1) plt.plot(fq, lp[0, 1, 3], color='C0', lw=0.5) plt.fill_between(fq, lp[1, 1, 3], lp[2, 1, 3], alpha=0.5, color='C1') plt.fill_between(fq, lp[0, 1, 3] - he[1], lp[0, 1, 3] + he[1], alpha=0.5, color='C3') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[0, 1:] * 0 + 1, color='C2') ax.set_xscale('log') ax.set_ylim([-1, 2]) plt.savefig('png/lag__4.png')
def simulate_light_curves(**kwargs): """Simulate light curves""" # set defaults; we set them explictely so they are stored in kwargs # which is part of the output kwargs.setdefault('input_psd', ['powerlaw', [1e-4, -2]]) kwargs.setdefault('seed', 3984023) kwargs.setdefault('n', 2**8) kwargs.setdefault('dt', 1.0) kwargs.setdefault('mu', 100.0) kwargs.setdefault('nsim', 100) kwargs.setdefault('gaussNoise', 1.0) kwargs.setdefault('nMult', 1) kwargs.setdefault('noiseSeed', 237) kwargs.setdefault('gaps', None) kwargs.setdefault('sameGap', False) input_psd = kwargs['input_psd'] seed = kwargs['seed'] n = kwargs['n'] dt = kwargs['dt'] mu = kwargs['mu'] nsim = kwargs['nsim'] gaussNoise = kwargs['gaussNoise'] nMult = kwargs['nMult'] noiseSeed = kwargs['noiseSeed'] # if not None; gaps = [seed, period (sec)] gaps = kwargs['gaps'] sameGap = kwargs['sameGap'] # do the simulations # sim = az.SimLC(seed) sim.add_model(*input_psd) n0 = n if gaps is None else 2 * n if not gaps is None: np.random.seed(gaps[0]) lc = [] for isim in range(nsim): sim.simulate(n0 * nMult, dt, mu, 'rms') tarr, yarr = sim.t[:n0], sim.x[:n0] if not gaps is None: prob = np.cos(2 * np.pi * tarr / gaps[1])**2 prob = prob / prob.sum() if isim == 0: idx = np.sort(np.random.choice(np.arange(n0), n, False, prob)) elif not sameGap: idx = np.sort(np.random.choice(np.arange(n0), n, False, prob)) else: pass tarr, yarr = tarr[idx], yarr[idx] yarr = sim.add_noise(yarr, gaussNoise, seed=noiseSeed, dt=dt) if gaussNoise is None: yerr = ((yarr * dt)**0.5 / dt) else: yerr = yarr * 0 + gaussNoise lc.append([tarr, yarr, yerr]) psd_model = np.array(sim.normalized_psd)[:, 1:-1] extra = {'psd_model': psd_model} extra.update(kwargs) # lc.shape: (nsim, 3, n) return np.array(lc), extra
def bin_psd__4(): """Simple powerlaw psd, POISSON, BINNING, LEAK TEST: formula error SUMMARY: 1. Formula works. It just need to be compared to the percentiles of the distribution rather than the std-dev 2. The linear binning has a large bias at the lowest frequencies. logavg does better, but not entirely """ n = 2**12 dt = 1.0 mu = 1000.0 nsim = 200 bins = [2, 10, 50] sim = az.SimLC(seed=12651) sim.add_model('powerlaw', [1e-2, -2.]) psd = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') # use different sampling dt, so we reduce the noise a little bit x = np.random.poisson(sim.x[:n] * 200) / 200 p = az.LCurve.calculate_psd(x, dt, 'var', taper=True, rerr=(x / 200)**0.5) pb = [] for b in bins: p1 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, noise=p[2], logavg=False) p2 = az.LCurve.bin_psd(p[0], p[1], fqbin={'by_n': [b, 1]}, noise=p[2], logavg=True) p1 = np.vstack([p1[:3], p1[3]['noise']]) p2 = np.vstack([p2[:3], p2[3]['noise']]) pb.append([p1, p2]) psd.append(pb) plt.rcParams['figure.figsize'] = [14, 8] plt.rcParams['font.size'] = 7 for ib in range(len(bins)): pb = np.array([x[ib] for x in psd]) fq = pb[0, 0, 0] p = np.mean(pb[:, :, 1], 0) ps = np.std(pb[:, :, 1], 0) pp = np.percentile(pb[:, :, 1], [16, 100 - 16], 0) pe = np.mean(pb[:, :, 2], 0) pn = np.mean(pb[:, :, 3], 0) ax = plt.subplot(2, len(bins), ib + 1) plt.loglog(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:]) plt.errorbar(fq, p[0], ps[0], lw=0.5, label='lin') plt.fill_between(fq, p[0] - pe[0], p[0] + pe[0], alpha=0.6) plt.fill_between(fq, pp[0, 0], pp[1, 0], alpha=0.6, color='C2') plt.plot(fq, pn[0]) plt.legend() plt.title('bin %d' % bins[ib]) ax.set_xlim([2e-4, 0.5]) plt.ylim([5, 5e5]) ax = plt.subplot(2, len(bins), len(bins) + ib + 1) plt.loglog(sim.normalized_psd[0, 1:], sim.normalized_psd[1, 1:]) plt.errorbar(fq, p[1], ps[1], lw=0.5, label='log') plt.fill_between(fq, p[1] - pe[1], p[1] + pe[0], alpha=0.6) plt.fill_between(fq, pp[0, 1], pp[1, 1], alpha=0.6, color='C2') plt.plot(fq, pn[1]) plt.legend() ax.set_xlim([2e-4, 0.5]) plt.ylim([5, 5e5]) plt.title('bin:%d' % bins[ib]) plt.savefig('png/bin_psd__4.png')
def phase__4(): """Constant phase lag, BINNING, NOISE, RED NOISE LEAK TEST: error formular, and the psd/noise inside SUMMARY: 1. Formula works with taper, and simple ftt (no norms, logavg) using psd and cxd without noise subtraction as in Nowak+99 and not Uttley+14 2. Without tapering, the error formula gives large error. Even with tapering, the formula gives a slightly larger errors. """ n = 2**12 dt = 1.0 mu = 100.0 lag = 0.5 nsim = 200 bins = [2, 5, 10, 20, 50] sim = az.SimLC(seed=463104) sim.add_model('powerlaw', [1e-2, -2.]) sim.add_model('constant', lag, lag=True) lag = [] for isim in range(nsim): az.misc.print_progress(isim, nsim, isim == nsim - 1) sim.simulate(n * 4, dt, mu, norm='var') sim.apply_lag(phase=True) scale_fac = 1000 x = np.random.poisson(sim.x[:n] * scale_fac) / scale_fac y = np.random.poisson(sim.y[:n] * scale_fac) / scale_fac lb = [] for b in bins: l1 = az.LCurve.calculate_lag(y, x, dt, phase=True, fqbin={'by_n': [b, 1]}, rerr=(y / scale_fac)**0.5, Rerr=(x / scale_fac)**0.5) l1 = list(l1[:3]) + [l1[3][k] for k in ['coh', 'coh_e']] l2 = az.LCurve.calculate_lag(y, x, dt, phase=True, taper=True, fqbin={'by_n': [b, 1]}, rerr=(y / scale_fac)**0.5, Rerr=(x / scale_fac)**0.5) l2 = list(l2[:3]) + [l2[3][k] for k in ['coh', 'coh_e']] lb.append([l1, l2]) lag.append(lb) plt.rcParams['figure.figsize'] = [14, 10] plt.rcParams['font.size'] = 7 for ib in range(len(bins)): lb = np.array([[m for m in l[ib]] for l in lag]) fq = lb[0, 0, 0] lp = np.percentile(lb, [50, 16, 100 - 16], 0) le = np.median(lb[:, :, 2], 0) he = np.median(lb[:, :, 4], 0) ax = plt.subplot(4, len(bins), ib + 1) plt.plot(fq, lp[0, 0, 1], color='C0', lw=0.5) plt.fill_between(fq, lp[1, 0, 1], lp[2, 0, 1], alpha=0.5, color='C1') plt.fill_between(fq, lp[0, 0, 1] - le[0], lp[0, 0, 1] + le[0], alpha=0.5, color='C3') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') ax.set_ylim([-1, 1]) plt.title('bin: %d, no-taper' % bins[ib]) ax = plt.subplot(4, len(bins), len(bins) + ib + 1) plt.plot(fq, lp[0, 0, 3], color='C0', lw=0.5) plt.fill_between(fq, lp[1, 0, 3], lp[2, 0, 3], alpha=0.5, color='C1') plt.fill_between(fq, lp[0, 0, 3] - he[0], lp[0, 0, 3] + he[0], alpha=0.5, color='C3') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[0, 1:] * 0 + 1, color='C2') ax.set_xscale('log') ax.set_ylim([-1, 2]) ax = plt.subplot(4, len(bins), 2 * len(bins) + ib + 1) plt.plot(fq, lp[0, 1, 1], color='C0', lw=0.5) plt.title('taper') plt.fill_between(fq, lp[1, 1, 1], lp[2, 1, 1], alpha=0.5, color='C1') plt.fill_between(fq, lp[0, 1, 1] - le[1], lp[0, 1, 1] + le[1], alpha=0.5, color='C3') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[1, 1:], color='C2') ax.set_xscale('log') ax.set_ylim([-1, 1]) ax = plt.subplot(4, len(bins), 3 * len(bins) + ib + 1) plt.plot(fq, lp[0, 1, 3], color='C0', lw=0.5) plt.fill_between(fq, lp[1, 1, 3], lp[2, 1, 3], alpha=0.5, color='C1') plt.fill_between(fq, lp[0, 1, 3] - he[1], lp[0, 1, 3] + he[1], alpha=0.5, color='C3') plt.plot(sim.normalized_lag[0, 1:], sim.normalized_lag[0, 1:] * 0 + 1, color='C2') ax.set_xscale('log') ax.set_ylim([-1, 2]) plt.savefig('png/phase__4.png')
def simulate_scatter(lag, xtime, cflux, lflux, psdpar, dt, lag_model='const', nsim=200, tf_width_frac=0.5): """Simulate the scatter in cflux-lflux relation Parameters: lag: lag value to simulate xtime, cflux,lflux: light curves of dims [2,nval] psdpar: input continuum psd parameters for az.SimLC shape of (2,2) for poweralw and (2,3) for bending powerlaw. the first dim is for value,err dt: time sampling lag_model: 'const' for a delta function otherwise use top-hat with tf_width_frac controlling the fractional half width """ xe, ye = cflux[1], lflux[1] mu_c, mu_l = cflux[0].mean(), lflux[0].mean() xtime = np.array(xtime/dt, np.int) * dt gtime = np.arange(np.int((xtime[-1]-xtime[0])/dt)+10) * dt + xtime[0] itime = np.in1d(gtime, xtime) assert(len(itime[itime]) == len(xtime)) ngtime = len(gtime) len_sim = 2**(1+np.int(np.log(ngtime)/np.log(2))) scat = [] for isim in range(nsim): sim = az.SimLC() psdpar_sim = np.random.randn(len(psdpar[0])) * psdpar[1] + psdpar[0] psdpar_sim[0] = np.exp(psdpar_sim[0]) if len(psdpar_sim) == 2: # powerlaw psd fit # sim.add_model('broken_powerlaw', [psdpar_sim[0], -1, psdpar_sim[1], 1e-7]) else: # bending power psd fit # psdpar_sim[2] = np.exp(psdpar_sim[2]) sim.add_model('bending_powerlaw', [psdpar_sim[0], psdpar_sim[1], psdpar_sim[2]]) sim.simulate(len_sim, dt, mu_c, 'rms') if lag_model == 'const': # simple delta function # sim.add_model('constant', lag, clear=True, lag=True) sim.apply_lag(phase=False) y = sim.y else: # top hat tf = np.zeros_like(sim.x) if tf_width_frac > 0: # tf_width_frac is used as a fraction of the lag # tf[(sim.t>=np.abs(lag)*(1-tf_width_frac)) & (sim.t<=np.abs(lag)*(1+tf_width_frac))] = 1 else: if tf_width_frac==0: # randomize to marginalize w = np.random.rand() * 5 #w = np.clip(w, dt/2, np.abs(lag)/2) else: w = np.abs(tf_width_frac)/2 # simple fixed width w = np.clip(w, 0, np.abs(lag)/2) tf[(sim.t>=np.abs(lag) - w) & (sim.t<=np.abs(lag) + w)] = 1 #tf = st.norm.pdf(sim.t, loc=lag, scale=lag*tf_width_frac) if not np.all(tf==0): tf /= tf.sum() # tf2lag # n = len(sim.t) fq = np.arange(1,n/2+1)/(n*dt) ff = np.fft.fft(tf)[1:(n//2+1)] denom = 1+np.real(ff) denom[denom==0] = 1e-7 tan_phi = np.imag(ff) / denom lag_ = -np.sign(lag)*np.arctan(tan_phi) / (np.pi*fq) lag_ = np.concatenate([[lag_[0]], lag_]) fq = np.concatenate([[0], fq]) y = sim.lag_array(sim.x, lag_, False, fq) X = sim.x[:ngtime][itime] Y = (y[:ngtime][itime] - mu_c) * (mu_l/mu_c) + mu_l X += np.random.randn(len(xe)) * xe Y += np.random.randn(len(ye)) * ye scat.append(calc_scatter(X, xe, Y, ye, nsim=0)[0]) return np.array(scat)