def test_gp_timing_model(self): """Test that the timing model signal returns correct values.""" # set up signal parameter ts = gp_signals.TimingModel() tm = ts(self.psr) # basis matrix test M = self.psr.Mmat.copy() norm = np.sqrt(np.sum(M ** 2, axis=0)) M /= norm params = {} msg = "M matrix incorrect for Timing Model signal." assert np.allclose(M, tm.get_basis(params)), msg # Jvec test phi = np.ones(self.psr.Mmat.shape[1]) * 1e40 msg = "Prior vector incorrect for Timing Model signal." assert np.all(tm.get_phi(params) == phi), msg # inverse Jvec test msg = "Prior vector inverse incorrect for Timing Model signal." assert np.all(tm.get_phiinv(params) == 1 / phi), msg # test shape msg = "M matrix shape incorrect" assert tm.get_basis(params).shape == self.psr.Mmat.shape, msg # test unnormed ts = gp_signals.TimingModel(normed=False) tm = ts(self.psr) msg = "Incorrect unnormed timing-model matrix" assert np.allclose(self.psr.Mmat, tm.get_basis({})), msg # test prescribed norm ts = gp_signals.TimingModel(normed=np.ones(self.psr.Mmat.shape[1])) tm = ts(self.psr) msg = "Incorrect prescribed-norm timing-model matrix" assert np.allclose(self.psr.Mmat, tm.get_basis({})), msg # test svd ts = gp_signals.TimingModel(use_svd=True) tm = ts(self.psr) u, s, v = np.linalg.svd(self.psr.Mmat, full_matrices=False) msg = "Incorrect SVD timing-model matrix" assert np.allclose(u, tm.get_basis({})), msg # test incompatible prescription self.assertRaises(ValueError, gp_signals.TimingModel, use_svd=True, normed=False)
def test_formalism(self): # create marginalized model ef = white_signals.MeasurementNoise( efac=parameter.Uniform(0.1, 5.0)) tm = gp_signals.TimingModel() ec = gp_signals.EcorrBasisModel( log10_ecorr=parameter.Uniform(-10, -5)) pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) rn = gp_signals.FourierBasisGP(spectrum=pl, components=10) model = ef + tm + ec + rn pta = signal_base.PTA([model(self.psr)]) # create hierarchical model tmc = gp_signals.TimingModel(coefficients=True) ecc = gp_signals.EcorrBasisModel(log10_ecorr=parameter.Uniform( -10, -5), coefficients=True) rnc = gp_signals.FourierBasisGP(spectrum=pl, components=10, coefficients=True) modelc = ef + tmc + ecc + rnc ptac = signal_base.PTA([modelc(self.psr)]) ps = { "B1855+09_efac": 1, "B1855+09_basis_ecorr_log10_ecorr": -6, "B1855+09_red_noise_log10_A": -14, "B1855+09_red_noise_gamma": 3, } psc = utils.get_coefficients(pta, ps) d1 = ptac.get_delay(psc)[0] d2 = (np.dot(pta.pulsarmodels[0].signals[1].get_basis(ps), psc["B1855+09_linear_timing_model_coefficients"]) + np.dot(pta.pulsarmodels[0].signals[2].get_basis(ps), psc["B1855+09_basis_ecorr_coefficients"]) + np.dot(pta.pulsarmodels[0].signals[3].get_basis(ps), psc["B1855+09_red_noise_coefficients"])) msg = "Implicit and explicit PTA delays are different." assert np.allclose(d1, d2), msg l1 = pta.get_lnlikelihood(ps) l2 = ptac.get_lnlikelihood(psc) # I don't know how to integrate l2 to match l1... msg = "Marginal and hierarchical likelihoods should be different." assert l1 != l2, msg
def test_compare_ecorr_likelihood(self): """Compare basis and kernel ecorr methods.""" selection = Selection(selections.nanograv_backends) ef = white_signals.MeasurementNoise() ec = white_signals.EcorrKernelNoise(selection=selection) ec2 = gp_signals.EcorrBasisModel(selection=selection) tm = gp_signals.TimingModel() m = ef + ec + tm m2 = ef + ec2 + tm pta1 = signal_base.PTA([m(p) for p in self.psrs]) pta2 = signal_base.PTA([m2(p) for p in self.psrs]) params = parameter.sample(pta1.params) l1 = pta1.get_lnlikelihood(params) # need to translate some names for EcorrBasis basis_params = {} for parname, parval in params.items(): if "log10_ecorr" in parname: toks = parname.split("_") basisname = toks[0] + "_basis_ecorr_" + "_".join(toks[1:]) basis_params[basisname] = parval params.update(basis_params) l2 = pta2.get_lnlikelihood(params) msg = "Likelihood mismatch between ECORR methods" assert np.allclose(l1, l2), msg
def test_gp_timing_model(self): """Test that the timing model signal returns correct values.""" # set up signal parameter ts = gp_signals.TimingModel() tm = ts(self.psr) # basis matrix test M = self.psr.Mmat.copy() norm = np.sqrt(np.sum(M**2, axis=0)) M /= norm params = {} msg = "M matrix incorrect for Timing Model signal." assert np.allclose(M, tm.get_basis(params)), msg # Jvec test phi = np.ones(self.psr.Mmat.shape[1]) * 1e40 msg = "Prior vector incorrect for Timing Model signal." assert np.all(tm.get_phi(params) == phi), msg # inverse Jvec test msg = "Prior vector inverse incorrect for Timing Model signal." assert np.all(tm.get_phiinv(params) == 1 / phi), msg # test shape msg = "M matrix shape incorrect" assert tm.get_basis(params).shape == self.psr.Mmat.shape, msg
def model_1(psr): """ Reads in enterprise Pulsar instance and returns a PTA instantiated with the standard NANOGrav noise model: 1. EFAC per backend/receiver system 2. EQUAD per backend/receiver system 3. ECORR per backend/receiver system 4. Red noise modeled as a power-law with 30 sampling frequencies 5. Linear timing model. """ # white noise s = white_noise_block(vary=True) # red noise s += red_noise_block() # timing model s += gp_signals.TimingModel() # set up PTA of one pta = signal_base.PTA([s(psr)]) return pta
def __init__(self, psrs, params=None): print('Initializing the model...') efac = parameter.Constant() equad = parameter.Constant() ef = white_signals.MeasurementNoise(efac=efac) eq = white_signals.EquadNoise(log10_equad=equad) tm = gp_signals.TimingModel(use_svd=True) s = eq + ef + tm model = [] for p in psrs: model.append(s(p)) self.pta = signal_base.PTA(model) # set white noise parameters if params is None: print('No noise dictionary provided!...') else: self.pta.set_default_params(params) self.psrs = psrs self.params = params self.Nmats = None
def get_All_results(): # Modeling each pulsar. tm = gp_signals.TimingModel() wnb = models.white_noise_block(vary=True) dmn = models.dm_noise_block(components=30) spn = models.red_noise_block(components=30) model = tm + wnb + dmn + spn ptas = [signal_base.PTA(model(psr)) for psr in psrs] # Multiprocessing. jobs = [] RETs={} for i in range(len(psrs)): RETs[i] = multiprocessing.Manager().Value('i',0) p = multiprocessing.Process(target=get_pulsar_noise, args=(ptas[i],RETs[i])) jobs.append(p) p.start() for p in jobs: p.join() # Return the sum of the Ln Maximal Likelihood values. MLHselect = [RET.value for RET in RETs.values()] return MLHselect
def test_pshift_fourier(self): """Test Fourier basis with prescribed phase shifts.""" # build a SignalCollection with timing model and red noise with phase shifts Tspan = self.psr.toas.max() - self.psr.toas.min() pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(0, 7)) ts = gp_signals.TimingModel() rn = gp_signals.FourierBasisGP(pl, components=5, Tspan=Tspan, pseed=parameter.Uniform(0, 32768)) s = ts + rn m = s(self.psr) b1 = m.signals[1].get_basis() b2 = utils.createfourierdesignmatrix_red(nmodes=5, Tspan=Tspan)("")(self.psr.toas)[0] msg = "Fourier bases incorrect (no phase shifts)" assert np.all(b1 == b2), msg b1 = m.signals[1].get_basis() b2 = utils.createfourierdesignmatrix_red(nmodes=5, Tspan=Tspan, pseed=5)("")(self.psr.toas)[0] msg = "Fourier bases incorrect (no-parameter call vs phase shift 5)" assert not np.all(b1 == b2), msg b1 = m.signals[1].get_basis(params={self.psr.name + "_red_noise_pseed": 5}) b2 = utils.createfourierdesignmatrix_red(nmodes=5, Tspan=Tspan, pseed=5)("")(self.psr.toas)[0] msg = "Fourier bases incorrect (phase shift 5)" assert np.all(b1 == b2), msg b1 = m.signals[1].get_basis(params={self.psr.name + "_red_noise_pseed": 5}) b2 = utils.createfourierdesignmatrix_red(nmodes=5, Tspan=Tspan)("")(self.psr.toas)[0] msg = "Fourier bases incorrect (phase-shift-5 call vs no phase shift)" assert not np.all(b1 == b2), msg
def __init__(self, psrs, params=None, psrTerm=True, bayesephem=True, pta=None): if pta is None: # initialize standard model with fixed white noise # and powerlaw red noise # uses the implementation of ECORR in gp_signals print('Initializing the model...') tmin = np.min([p.toas.min() for p in psrs]) tmax = np.max([p.toas.max() for p in psrs]) Tspan = tmax - tmin s = deterministic.cw_block_circ(amp_prior='log-uniform', psrTerm=psrTerm, tref=tmin, name='cw') s += gp_signals.TimingModel() s += blocks.red_noise_block(prior='log-uniform', psd='powerlaw', Tspan=Tspan, components=30) if bayesephem: s += deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True) # adding white-noise, and acting on psr objects models = [] for p in psrs: if 'NANOGrav' in p.flags['pta']: s2 = s + blocks.white_noise_block(vary=False, inc_ecorr=True, gp_ecorr=True) models.append(s2(p)) else: s3 = s + blocks.white_noise_block(vary=False, inc_ecorr=False) models.append(s3(p)) pta = signal_base.PTA(models) # set white noise parameters if params is None: print('No noise dictionary provided!') else: pta.set_default_params(params) self.pta = pta else: # user can specify their own pta object # if ECORR is included, use the implementation in gp_signals self.pta = pta self.psrs = psrs self.params = params self.Nmats = self.get_Nmats()
def test_vector_parameter_like(self): """Test vector parameter in a likelihood""" # white noise efac = parameter.Uniform(0.5, 2) ef = white_signals.MeasurementNoise(efac=efac) # red noise nf = 3 spec = free_spectrum(log10_rho=parameter.Uniform(-20, -10, size=nf)) rn = gp_signals.FourierBasisGP(spec, components=nf) # timing model tm = gp_signals.TimingModel() # combined signal s = ef + rn + tm # PTA pta = signal_base.PTA([s(self.psr)]) # parameters xs = np.hstack(p.sample() for p in pta.params) params = { "B1855+09_red_noise_log10_rho": xs[1:], "B1855+09_efac": xs[0] } # test log likelihood msg = "Likelihoods do not match" assert pta.get_lnlikelihood(xs) == pta.get_lnlikelihood(params), msg # test log prior msg = "Priors do not match" assert pta.get_lnprior(xs) == pta.get_lnprior(params), msg # test prior value prior = 1 / (2 - 0.5) * (1 / 10)**3 msg = "Prior value incorrect." assert np.allclose(pta.get_lnprior(xs), np.log(prior)), msg # test PTA level parameter names pnames = [ "B1855+09_efac", "B1855+09_red_noise_log10_rho_0", "B1855+09_red_noise_log10_rho_1", "B1855+09_red_noise_log10_rho_2", ] msg = "Incorrect parameter names" assert pta.param_names == pnames
def initialize_pta_sim(psrs, fgw): # continuous GW signal s = models.cw_block_circ(log10_fgw=np.log10(fgw), psrTerm=True) # white noise efac = parameter.Constant(1.0) s += white_signals.MeasurementNoise(efac=efac) # linearized timing model s += gp_signals.TimingModel(use_svd=True) model = [s(psr) for psr in psrs] pta = signal_base.PTA(model) return pta
def add_timingmodel(self): """Return dictionary containing timing model signal attributes :return: OrderedDict of timing model signal """ tm = gp_signals.TimingModel(use_svd=False) npars = self.psr.Mmat.shape[1] newsignal = OrderedDict({ 'type': 'timingmodel', 'name': 'timingmodel', 'pmin': [-1.0e6] * npars, 'pmax': [1.0e6] * npars, 'pstart': [1.0e-10] * npars, 'interval': [False] * npars, 'numpars': npars }) self.tm_sig = tm(self.psr) return {'timingmodel': newsignal}
def initialize_pta_sim(psrs, fgw, inc_efac=True, inc_equad=False, inc_ecorr=False, selection=None, inc_red_noise=False, noisedict=None): # continuous GW signal s = models.cw_block_circ(log10_fgw=np.log10(fgw), psrTerm=True) # linearized timing model s += gp_signals.TimingModel(use_svd=True) # white noise if selection == 'backend': selection = selections.Selection(selections.by_backend) if inc_efac: efac = parameter.Constant() s += white_signals.MeasurementNoise(efac=efac, selection=selection) if inc_equad: equad = parameter.Constant() s += white_signals.EquadNoise(log10_equad=equad, selection=selection) if inc_ecorr: ecorr = parameter.Constant() s += gp_signals.EcorrBasisModel(log10_ecorr=ecorr, selection=selection) if inc_red_noise: log10_A = parameter.Constant() gamma = parameter.Constant() pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) s += gp_signals.FourierBasisGP(pl, components=30) model = [s(psr) for psr in psrs] pta = signal_base.PTA(model) # set white noise parameters if noisedict is None: print('No noise dictionary provided!...') else: pta.set_default_params(noisedict) return pta
def pta_pshift(dmx_psrs, caplog): Tspan = model_utils.get_tspan(dmx_psrs) tm = gp_signals.TimingModel() wn = blocks.white_noise_block(inc_ecorr=True, tnequad=True) rn = blocks.red_noise_block(Tspan=Tspan) pseed = parameter.Uniform(0, 10000)('gw_pseed') gw_log10_A = parameter.Uniform(-18, -14)('gw_log10_A') gw_gamma = parameter.Constant(13. / 3)('gw_gamma') gw_pl = utils.powerlaw(log10_A=gw_log10_A, gamma=gw_gamma) gw_pshift = gp_signals.FourierBasisGP(spectrum=gw_pl, components=5, Tspan=Tspan, name='gw', pshift=True, pseed=pseed) model = tm + wn + rn + gw_pshift pta_pshift = signal_base.PTA([model(p) for p in dmx_psrs]) pta_pshift.set_default_params(noise_dict) return pta_pshift
def test_model_2a_altpol_spectrum(nodmx_psrs, caplog): log10_A_tt = parameter.LinearExp(-18, -12)('log10_A_tt') log10_A_st = parameter.LinearExp(-18, -12)('log10_A_st') log10_A_vl = parameter.LinearExp(-18, -15)('log10_A_vl') log10_A_sl = parameter.LinearExp(-18, -16)('log10_A_sl') kappa = parameter.Uniform(0, 15)('kappa') p_dist = parameter.Normal(1.0, 0.2) pl = model_orfs.generalized_gwpol_psd(log10_A_tt=log10_A_tt, log10_A_st=log10_A_st, log10_A_vl=log10_A_vl, log10_A_sl=log10_A_sl, kappa=kappa, p_dist=p_dist, alpha_tt=-2 / 3, alpha_alt=-1) s = models.white_noise_block(vary=False, inc_ecorr=True) s += models.red_noise_block(prior='log-uniform') s += gp_signals.FourierBasisGP(spectrum=pl, name='gw') s += gp_signals.TimingModel() m = signal_base.PTA([s(psr) for psr in nodmx_psrs]) m.set_default_params(noise_dict) for param in m.params: if 'gw_p_dist' in str(param): # get pulsar name and distance psr_name = str(param).split('_')[0].strip('"') psr_dist = [p._pdist for p in nodmx_psrs if psr_name in p.name][0] # edit prior settings param._prior = parameter.Normal(mu=psr_dist[0], sigma=psr_dist[1]) param._mu = psr_dist[0] param._sigma = psr_dist[1] assert hasattr(m, 'get_lnlikelihood')
def _ecorr_test(self, method="sparse"): """Test of sparse/sherman-morrison ecorr signal and solve methods.""" selection = Selection(selections.by_backend) efac = parameter.Uniform(0.1, 5) ecorr = parameter.Uniform(-10, -5) ef = white_signals.MeasurementNoise(efac=efac, selection=selection) ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr, selection=selection, method=method) tm = gp_signals.TimingModel() s = ef + ec + tm m = s(self.psr) # set parameters efacs = [1.3, 1.4, 1.5, 1.6] ecorrs = [-6.1, -6.2, -6.3, -6.4] params = { "B1855+09_430_ASP_efac": efacs[0], "B1855+09_430_PUPPI_efac": efacs[1], "B1855+09_L-wide_ASP_efac": efacs[2], "B1855+09_L-wide_PUPPI_efac": efacs[3], "B1855+09_430_ASP_log10_ecorr": ecorrs[0], "B1855+09_430_PUPPI_log10_ecorr": ecorrs[1], "B1855+09_L-wide_ASP_log10_ecorr": ecorrs[2], "B1855+09_L-wide_PUPPI_log10_ecorr": ecorrs[3], } # get EFAC Nvec flags = ["430_ASP", "430_PUPPI", "L-wide_ASP", "L-wide_PUPPI"] nvec0 = np.zeros_like(self.psr.toas) for ct, flag in enumerate(np.unique(flags)): ind = flag == self.psr.backend_flags nvec0[ind] = efacs[ct]**2 * self.psr.toaerrs[ind]**2 # get the basis bflags = self.psr.backend_flags Umats = [] for flag in np.unique(bflags): mask = bflags == flag Umats.append( utils.create_quantization_matrix(self.psr.toas[mask], nmin=2)[0]) nepoch = sum(U.shape[1] for U in Umats) U = np.zeros((len(self.psr.toas), nepoch)) jvec = np.zeros(nepoch) netot = 0 for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag nn = Umats[ct].shape[1] U[mask, netot:nn + netot] = Umats[ct] jvec[netot:nn + netot] = 10**(2 * ecorrs[ct]) netot += nn # get covariance matrix wd = Woodbury(nvec0, U, jvec) # test msg = "EFAC/ECORR {} logdet incorrect.".format(method) N = m.get_ndiag(params) assert np.allclose(N.solve(self.psr.residuals, logdet=True)[1], wd.logdet(), rtol=1e-10), msg msg = "EFAC/ECORR {} D1 solve incorrect.".format(method) assert np.allclose(N.solve(self.psr.residuals), wd.solve(self.psr.residuals), rtol=1e-10), msg msg = "EFAC/ECORR {} 1D1 solve incorrect.".format(method) assert np.allclose( N.solve(self.psr.residuals, left_array=self.psr.residuals), np.dot(self.psr.residuals, wd.solve(self.psr.residuals)), rtol=1e-10, ), msg msg = "EFAC/ECORR {} 2D1 solve incorrect.".format(method) T = m.get_basis() assert np.allclose(N.solve(self.psr.residuals, left_array=T), np.dot(T.T, wd.solve(self.psr.residuals)), rtol=1e-10), msg msg = "EFAC/ECORR {} 2D2 solve incorrect.".format(method) assert np.allclose(N.solve(T, left_array=T), np.dot(T.T, wd.solve(T)), rtol=1e-10), msg
def test_conditional_gp(self): ef = white_signals.MeasurementNoise(efac=parameter.Uniform(0.1, 5.0)) tm = gp_signals.TimingModel() ec = gp_signals.EcorrBasisModel(log10_ecorr=parameter.Uniform(-10, -5)) pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) rn = gp_signals.FourierBasisGP(spectrum=pl, components=10, combine=False) model = ef + tm + ec + rn pta = signal_base.PTA([model(self.psr), model(self.psr2)]) p0 = { "B1855+09_basis_ecorr_log10_ecorr": -6.051740765663904, "B1855+09_efac": 2.9027266737466095, "B1855+09_red_noise_gamma": 6.9720332277819725, "B1855+09_red_noise_log10_A": -16.749192700991543, "B1937+21_basis_ecorr_log10_ecorr": -9.726747733721872, "B1937+21_efac": 3.959178240268702, "B1937+21_red_noise_gamma": 2.9030772884814797, "B1937+21_red_noise_log10_A": -17.978562921948992, } c = utils.ConditionalGP(pta) cmean = c.get_mean_coefficients(p0) # build index for the global coefficient vector idx, ntot = {}, 0 for l, v in cmean.items(): idx[l] = slice(ntot, ntot + len(v)) ntot = ntot + len(v) # repeat the computation using the common-signal formalism TNrs = pta.get_TNr(p0) TNTs = pta.get_TNT(p0) phiinvs = pta.get_phiinv(p0, logdet=False, method="cliques") TNr = np.concatenate(TNrs) Sigma = sps.block_diag(TNTs, "csc") + sps.block_diag( [np.diag(phiinvs[0]), np.diag(phiinvs[1])]) ch = cholesky(Sigma) mn = ch(TNr) iSigma = sps.linalg.inv(Sigma) # check mean values msg = "Conditional GP coefficient value does not match" for l, v in cmean.items(): assert np.allclose(mn[idx[l]], v, atol=1e-4, rtol=1e-4), msg # check variances par = "B1937+21_linear_timing_model_coefficients" c1 = np.cov( np.array([cs[par] for cs in c.sample_coefficients(p0, n=10000)]).T) c2 = iSigma[idx[par], idx[par]].toarray().T msg = "Conditional GP coefficient variance does not match" assert np.allclose(c1, c2, atol=1e-4, rtol=1e-4), msg # check mean processes proc = "B1937+21_linear_timing_model" p1 = c.get_mean_processes(p0)[proc] p2 = np.dot(pta["B1937+21"]["linear_timing_model"].get_basis(), mn[idx[par]]) msg = "Conditional GP time series does not match" assert np.allclose(p1, p2, atol=1e-4, rtol=1e-4), msg # check mean of sampled processes p2 = np.mean(np.array( [pc[proc] for pc in c.sample_processes(p0, n=1000)]), axis=0) msg = "Mean of sampled conditional GP processes does not match" assert np.allclose(p1, p2, atol=1e-4, rtol=1e-4) # now try with a common process crn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=utils.hd_orf(), components=10, combine=False) model = ef + tm + ec + crn pta = signal_base.PTA([model(self.psr), model(self.psr2)]) p0 = { "B1855+09_basis_ecorr_log10_ecorr": -5.861847220080768, "B1855+09_efac": 4.588342210948306, "B1937+21_basis_ecorr_log10_ecorr": -9.151872649912377, "B1937+21_efac": 0.8947815819783302, "common_fourier_gamma": 6.638289750637263, "common_fourier_log10_A": -15.68180643904114, } c = utils.ConditionalGP(pta) cmean = c.get_mean_coefficients(p0) idx, ntot = {}, 0 for l, v in cmean.items(): idx[l] = slice(ntot, ntot + len(v)) ntot = ntot + len(v) TNrs = pta.get_TNr(p0) TNTs = pta.get_TNT(p0) phiinvs = pta.get_phiinv(p0, logdet=False, method="cliques") TNr = np.concatenate(TNrs) Sigma = sps.block_diag(TNTs, "csc") + sps.csc_matrix(phiinvs) ch = cholesky(Sigma) mn = ch(TNr) msg = "Conditional GP coefficient value does not match for common GP" for l, v in cmean.items(): assert np.allclose(mn[idx[l]], v)
def gwb_ul(psrs_cut, num_points): # find the maximum time span to set GW frequency sampling tmin = [p.toas.min() for p in psrs_cut] tmax = [p.toas.max() for p in psrs_cut] Tspan = np.max(tmax) - np.min(tmin) # define selection by observing backend selection = selections.Selection(selections.by_backend) # white noise parameters # we set these ourselves so we know the most likely values! efac = parameter.Constant(1) # quad = parameter.Constant(0) # ecorr = parameter.Constant(0) # red noise parameters log10_A = parameter.LinearExp(-20, -11) gamma = parameter.Uniform(0, 7) # GW parameters (initialize with names here to use parameters in common across pulsars) log10_A_gw = parameter.LinearExp(-18, -12)('log10_A_gw') gamma_gw = parameter.Constant(4.33)('gamma_gw') # white noise ef = white_signals.MeasurementNoise(efac=efac, selection=selection) # eq = white_signals.EquadNoise(log10_equad=equad, selection=selection) # ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr, selection=selection) # red noise (powerlaw with 30 frequencies) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) rn = gp_signals.FourierBasisGP(spectrum=pl, components=30, Tspan=Tspan) # gwb (no spatial correlations) cpl = utils.powerlaw(log10_A=log10_A_gw, gamma=gamma_gw) gw = gp_signals.FourierBasisGP(spectrum=cpl, components=30, Tspan=Tspan, name='gw') # timing model tm = gp_signals.TimingModel( use_svd=True) # stabilizing timing model design matrix with SVD s = ef + rn + gw + tm # intialize PTA models = [] for p in psrs_cut: models.append(s(p)) pta = signal_base.PTA(models) outDir = './chains/psrs/{0}'.format(psrs_cut[0].name) sample = sampler.setup_sampler(pta, outdir=outDir) x0 = np.hstack([p.sample() for p in pta.params]) # sampler for N steps N = int( num_points) # normally, we would use 5e6 samples (this will save time) sample.sample( x0, N, SCAMweight=30, AMweight=15, DEweight=50, ) chain = np.loadtxt(os.path.join(outDir, 'chain_1.txt')) pars = np.loadtxt(outDir + '/pars.txt', dtype=np.unicode_) ind = list(pars).index('log10_A_gw') UL, unc = model_utils.ul(chain[:, ind]) return UL, unc
def model_bwm(psrs, Tmin_bwm=None, Tmax_bwm=None, skyloc=None, logmin=-18, logmax=-11, upper_limit=False, bayesephem=False, sngl_psr=False, dmgp=False, free_rn=False): """ Reads in list of enterprise Pulsar instance and returns a PTA instantiated with BWM model: per pulsar: 1. fixed EFAC per backend/receiver system 2. fixed EQUAD per backend/receiver system 3. fixed ECORR per backend/receiver system 4. Red noise modeled as a power-law with 30 sampling frequencies 5. Linear timing model. global: 1. Deterministic GW burst with memory signal. 2. Optional physical ephemeris modeling. :param Tmin_bwm: Min time to search for BWM (MJD). If omitted, uses first TOA. :param Tmax_bwm: Max time to search for BWM (MJD). If omitted, uses last TOA. :param skyloc: Fixed sky location of BWM signal search as [cos(theta), phi]. Search over sky location if ``None`` given. :param logmin: log of minimum BWM amplitude for prior (log10) :param logmax: log of maximum BWM amplitude for prior (log10) :param upper_limit: Perform upper limit on common red noise amplitude. By default this is set to False. Note that when perfoming upper limits it is recommended that the spectral index also be fixed to a specific value. :param bayesephem: Include BayesEphem model. Set to False by default :param sngl_psr: run on a single pulsar only. Uses different BWM parameterization to avoid problem with sky nulls. Set to False by default. :param free_rn: Use free red noise spectrum model. Set to False by default. """ amp_prior = 'uniform' if upper_limit else 'log-uniform' # find the maximum time span to set GW frequency sampling tmin = np.min([p.toas.min() for p in psrs]) tmax = np.max([p.toas.max() for p in psrs]) Tspan = tmax - tmin if Tmin_bwm == None: Tmin_bwm = tmin / const.day if Tmax_bwm == None: Tmax_bwm = tmax / const.day # white noise s = white_noise_block(vary=False) # red noise if free_rn: s += free_noise_block(prior=amp_prior, Tspan=Tspan) else: s += red_noise_block(prior=amp_prior, Tspan=Tspan) # GW BWM signal block s += bwm_block(Tmin_bwm, Tmax_bwm, amp_prior=amp_prior, skyloc=skyloc, logmin=logmin, logmax=logmax, sngl=sngl_psr, name='bwm') # ephemeris model if bayesephem: s += deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True) # timing model s += gp_signals.TimingModel(use_svd=True) # set up PTA pta = signal_base.PTA([s(psr) for psr in psrs]) return pta
def model_gwb(psrs, psd='powerlaw', gamma_common=None, orf=None, upper_limit=False, bayesephem=False): """ Reads in list of enterprise Pulsar instance and returns a PTA instantiated with GWB model: per pulsar: 1. fixed EFAC per backend/receiver system 2. fixed EQUAD per backend/receiver system 3. fixed ECORR per backend/receiver system 4. Red noise modeled as a power-law with 30 sampling frequencies 5. Linear timing model. global: 1.Common red noise modeled with user defined PSD with 30 sampling frequencies. Available PSDs are ['powerlaw', 'turnover'] 2. Optional physical ephemeris modeling. :param psd: PSD to use for common red noise signal. Available options are ['powerlaw', 'turnover']. 'powerlaw' is default value. :param gamma_common: Fixed common red process spectral index value. By default we vary the spectral index over the range [0, 7]. :param orf: String representing which overlap reduction function to use. By default we do not use any spatial correlations. Permitted values are ['hd', 'dipole', 'monopole']. :param upper_limit: Perform upper limit on common red noise amplitude. By default this is set to False. Note that when perfoming upper limits it is recommended that the spectral index also be fixed to a specific value. :param bayesephem: Include BayesEphem model. Set to False by default """ amp_prior = 'uniform' if upper_limit else 'log-uniform' # find the maximum time span to set GW frequency sampling tmin = np.min([p.toas.min() for p in psrs]) tmax = np.max([p.toas.max() for p in psrs]) Tspan = tmax - tmin # white noise s = white_noise_block(vary=False) # red noise s += red_noise_block(prior=amp_prior, Tspan=Tspan) # common red noise block s += common_red_noise_block(psd=psd, prior=amp_prior, Tspan=Tspan, gamma_val=gamma_common, name='gwb', orf=orf) # ephemeris model if bayesephem: s += deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True) # timing model s += gp_signals.TimingModel() # set up PTA pta = signal_base.PTA([s(psr) for psr in psrs]) return pta
def model_bwm(psrs, Tmin_bwm=None, Tmax_bwm=None, skyloc=None, logmin=-18, logmax=-11, amp_prior='log-uniform', bayesephem=False, dmgp=False, free_rn=False): """ Reads in list of enterprise Pulsar instance and returns a PTA instantiated with BWM model: per pulsar: 1. fixed EFAC per backend/receiver system 2. fixed EQUAD per backend/receiver system 3. fixed ECORR per backend/receiver system 4. Red noise modeled as a power-law with 30 sampling frequencies 5. Linear timing model. global: 1. Deterministic GW burst with memory signal. 2. Optional physical ephemeris modeling. :param Tmin_bwm: Min time to search for BWM (MJD). If omitted, uses first TOA. :param Tmax_bwm: Max time to search for BWM (MJD). If omitted, uses last TOA. :param skyloc: Fixed sky location of BWM signal search as [cos(theta), phi]. Search over sky location if ``None`` given. :param logmin: log of minimum BWM amplitude for prior (log10) :param logmax: log of maximum BWM amplitude for prior (log10) :param upper_limit: Perform upper limit on common red noise amplitude. By default this is set to False. Note that when perfoming upper limits it is recommended that the spectral index also be fixed to a specific value. :param bayesephem: Include BayesEphem model. Set to False by default :param free_rn: Use free red noise spectrum model. Set to False by default """ # find the maximum time span to set GW frequency sampling tmin = np.min([p.toas.min() for p in psrs]) tmax = np.max([p.toas.max() for p in psrs]) Tspan = tmax - tmin if Tmin_bwm == None: Tmin_bwm = tmin / const.day if Tmax_bwm == None: Tmax_bwm = tmax / const.day # white noise s = models.white_noise_block(vary=False) # red noise if free_rn: s += models.free_noise_block(prior=amp_prior, Tspan=Tspan) else: s += red_noise_block(prior=amp_prior, Tspan=Tspan) # GW BWM signal block s += bwm_sngl_block(Tmin_bwm, Tmax_bwm, amp_prior=amp_prior, logmin=logmin, logmax=logmax, name='bwm') # ephemeris model if bayesephem: s += deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True) # timing model s += gp_signals.TimingModel(use_svd=True) # DM variations model if dmgp: s += models.dm_noise_block(gp_kernel='diag', psd='powerlaw', prior=amp_prior, Tspan=Tspan) s += models.dm_annual_signal() # DM exponential dip for J1713's DM event dmexp = models.dm_exponential_dip(tmin=54500, tmax=54900) s2 = s + dmexp # set up PTA mods = [] for p in psrs: if dmgp and 'J1713+0747' == p.name: mods.append(s2(p)) else: mods.append(s(p)) pta = signal_base.PTA(mods) return pta
bwm_log10_A = parameter.LinearExp(-18, -11)(amp_name) else: bwm_log10_A = parameter.Uniform(-18, -11)(amp_name) t0 = parameter.Constant(args.t0)('bwm_t0') pol = parameter.Constant(args.psi)('bwm_pol') phi = parameter.Constant(args.phi)('bwm_phi') costh = parameter.Constant(args.costh)('bwm_costheta') bwm_wf = utils.bwm_delay(log10_h=bwm_log10_A, t0=t0, cos_gwtheta=costh, gwphi=phi, gwpol=pol) # BWM signal bwm = deterministic_signals.Deterministic(bwm_wf, name='bwm') # Timing Model tm = gp_signals.TimingModel(use_svd=True) # BayesEphem be = deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True) # construct PTA mod = tm + wn + rn + bwm if args.BE: mod += be pta = signal_base.PTA([mod(p) for p in psrs]) pta.set_default_params(noise_params) sumfile = os.path.join(outdir, 'summary.txt') with open(sumfile, 'w') as f: f.write(pta.summary())
def init_pta(params_all): """ Initiate enterprise signal models and enterprise.signals.signal_base.PTA. """ ptas = dict.fromkeys(params_all.models) for ii, params in params_all.models.items(): allpsr_model = params_all.noise_model_obj(psr=params_all.psrs, params=params) models = list() from_par_file = list() ecorrexists = np.zeros(len(params_all.psrs)) # Including parameters common for all pulsars if params.tm == 'default': tm = gp_signals.TimingModel() elif params.tm == 'ridge_regression': log10_variance = parameter.Uniform(-20, -10) basis = scaled_tm_basis() prior = ridge_prior(log10_variance=log10_variance) tm = gp_signals.BasisGP(prior, basis, name='ridge') # Adding common noise terms for all pulsars # Only those common signals are added that are listed in the noise model # file, getting Enterprise models from the noise model object. if 'm_all' in locals(): del m_all for psp, option in params.common_signals.items(): if 'm_all' in locals(): m_all += getattr(allpsr_model, psp)(option=option) else: m_all = tm + getattr(allpsr_model, psp)(option=option) # Including single pulsar noise models for pnum, psr in enumerate(params_all.psrs): singlepsr_model = params_all.noise_model_obj(psr=psr, params=params) # Determine if ecorr is mentioned in par file try: for key, val in psr.t2pulsar.noisemodel.items(): if key.startswith('ecorr') or key.startswith('ECORR'): ecorrexists[pnum] = True except Exception as pint_problem: print(pint_problem) ecorrexists[pnum] = False # Add noise models if psr.name in params.noisemodel.keys(): noise_model_dict_psr = params.noisemodel[psr.name] else: noise_model_dict_psr = params.universal for psp, option in noise_model_dict_psr.items(): if 'm_sep' in locals(): m_sep += getattr(singlepsr_model, psp)(option=option) elif 'm_all' in locals(): m_sep = m_all + getattr(singlepsr_model, psp)(option=option) else: m_sep = tm + getattr(singlepsr_model, psp)(option=option) models.append(m_sep(psr)) del m_sep pta = signal_base.PTA(models) if 'noisefiles' in params.__dict__.keys(): noisedict = get_noise_dict(psrlist=[p.name for p in params_all.psrs],\ noisefiles=params.noisefiles) print('For constant parameters using noise files in PAL2 format') pta.set_default_params(noisedict) print('Model',ii,'params (',len(pta.param_names),') in order: ', \ pta.param_names) if params.opts.mpi_regime != 2: np.savetxt(params.output_dir + '/pars.txt', pta.param_names, fmt='%s') ptas[ii] = pta return ptas
ef = white_signals.MeasurementNoise(efac=efac, selection=selection) eq = white_signals.EquadNoise(log10_equad=equad, selection=selection) ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr, selection=selection_ch) # red noise (powerlaw with 5 frequencies) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) basis = utils.createfourierdesignmatrix_red(Tspan=Tspan, nmodes=args.nfreqs, logf=args.logf) rn = gp_signals.BasisGP(priorFunction=pl, name='red_noise', basisFunction=basis) # timing model tm = gp_signals.TimingModel(use_svd=False) model = tm + ef + eq + ec + rn if args.dm_gp_psrs[0] == args.psr: dm_basis = utils.createfourierdesignmatrix_dm(Tspan=Tspan, nmodes=args.nfreqs, logf=args.logf) dm_gp = gp_signals.BasisGP(priorFunction=pl, basisFunction=dm_basis, name='dm_gp') model += dm_gp pta = signal_base.PTA(model(psr)) x0 = np.hstack(p.sample() for p in pta.params)
def model_simple(psrs, psd='powerlaw', efac=False, n_gwbfreqs=30, components=30, freqs=None, vary_gamma=False, upper_limit=False, bayesephem=False, select='backend', red_noise=False, Tspan=None, hd_orf=False, rn_dropout=False, dp_threshold=0.5): """ Reads in list of enterprise Pulsar instance and returns a PTA instantiated with the most simple model allowable for enterprise: per pulsar: 1. fixed EFAC per backend/receiver system at 1.0 2. Linear timing model. 3. Red noise modeled as a power-law with 30 sampling frequencies. Default=False global: 1.Common red noise modeled with user defined PSD with 30 sampling frequencies. Available PSDs are ['powerlaw', 'turnover' 'spectrum'] 2. Optional physical ephemeris modeling. :param psd: PSD to use for common red noise signal. Available options are ['powerlaw', 'turnover' 'spectrum']. 'powerlaw' is default value. :param gamma_common: Fixed common red process spectral index value. By default we vary the spectral index over the range [0, 7]. :param upper_limit: Perform upper limit on common red noise amplitude. By default this is set to False. Note that when performing upper limits it is recommended that the spectral index also be fixed to a specific value. :param bayesephem: Include BayesEphem model. Set to False by default """ amp_prior = 'uniform' if upper_limit else 'log-uniform' # find the maximum time span to set GW frequency sampling if Tspan is None: Tspan = model_utils.get_tspan(psrs) # timing model model = gp_signals.TimingModel() #Only White Noise is EFAC set to 1.0 selection = selections.Selection(selections.by_backend) if efac: ef = parameter.Uniform(0.1,10.0) else: ef = parameter.Constant(1.00) model += white_signals.MeasurementNoise(efac=ef, selection=selection) # common red noise block if upper_limit: log10_A_gw = parameter.LinearExp(-18,-12)('gw_log10_A') else: log10_A_gw = parameter.Uniform(-18,-12)('gw_log10_A') if vary_gamma: gamma_gw = parameter.Uniform(0,7)('gw_gamma') else: gamma_gw = parameter.Constant(4.33)('gw_gamma') pl = signal_base.Function(utils.powerlaw, log10_A=log10_A_gw, gamma=gamma_gw) if hd_orf: if freqs is None: gw = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=utils.hd_orf(), components=n_gwbfreqs, Tspan=Tspan, name='gw') else: gw = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=utils.hd_orf(), modes=freqs, name='gw') model += gw else: if freqs is None: crn = gp_signals.FourierBasisGP(spectrum=pl, components=n_gwbfreqs, Tspan=Tspan, name='gw') else: crn = gp_signals.FourierBasisGP(spectrum=pl, modes=freqs, name='gw') model += crn if red_noise and rn_dropout: if amp_prior == 'uniform': log10_A = parameter.LinearExp(-20, -11) elif amp_prior == 'log-uniform': log10_A = parameter.Uniform(-20, -11) else: log10_A = parameter.Uniform(-20, -11) gamma = parameter.Uniform(0, 7) k_drop = parameter.Uniform(0, 1) if dp_threshold == 6.0: dp_threshold = parameter.Uniform(0,1)('k_threshold') pl = dropout.dropout_powerlaw(log10_A=log10_A, gamma=gamma, k_drop=k_drop, k_threshold=dp_threshold) rn = gp_signals.FourierBasisGP(pl, components=components, Tspan=Tspan, name='red_noise') model += rn elif red_noise: # red noise model += models.red_noise_block(prior=amp_prior, Tspan=Tspan, components=components) # ephemeris model if bayesephem: model += deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True) # set up PTA pta = signal_base.PTA([model(p) for p in psrs]) return pta
def model_3d(psrs, psd='powerlaw', gamma_common=None, upper_limit=False, bayesephem=False): """ Reads in list of enterprise Pulsar instance and returns a PTA instantiated with model 3D from the analysis paper: per pulsar: 1. fixed EFAC per backend/receiver system 2. fixed EQUAD per backend/receiver system 3. fixed ECORR per backend/receiver system 4. Red noise modeled as a power-law with 30 sampling frequencies 5. Linear timing model. global: 1. GWB with HD correlations modeled with user defined PSD with 30 sampling frequencies. Available PSDs are ['powerlaw', 'turnover' 'spectrum'] 2. Monopole signal modeled with user defined PSD with 30 sampling frequencies. Available PSDs are ['powerlaw', 'turnover' 'spectrum'] 3. Optional physical ephemeris modeling. :param psd: PSD to use for common red noise signal. Available options are ['powerlaw', 'turnover' 'spectrum'] 'powerlaw' is default value. :param gamma_common: Fixed common red process spectral index value. By default we vary the spectral index over the range [0, 7]. :param upper_limit: Perform upper limit on common red noise amplitude. By default this is set to False. Note that when perfoming upper limits it is recommended that the spectral index also be fixed to a specific value. :param bayesephem: Include BayesEphem model. Set to False by default """ amp_prior = 'uniform' if upper_limit else 'log-uniform' # find the maximum time span to set GW frequency sampling tmin = [p.toas.min() for p in psrs] tmax = [p.toas.max() for p in psrs] Tspan = np.max(tmax) - np.min(tmin) # white noise s = white_noise_block(vary=False) # red noise s += red_noise_block(prior=amp_prior, Tspan=Tspan) # common red noise block s += common_red_noise_block(psd=psd, prior=amp_prior, Tspan=Tspan, gamma_val=gamma_common, orf='hd', name='gw') # monopole s += common_red_noise_block(psd=psd, prior=amp_prior, Tspan=Tspan, gamma_val=gamma_common, orf='monopole', name='monopole') # ephemeris model if bayesephem: s += deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True) # timing model s += gp_signals.TimingModel() # set up PTA pta = signal_base.PTA([s(psr) for psr in psrs]) # set white noise parameters noisedict = get_noise_dict(psrlist=[p.name for p in psrs]) pta.set_default_params(noisedict) return pta
def compute_like(self, npsrs=1, inc_corr=False, inc_kernel=False): # get parameters from PAL2 style noise files params = get_noise_from_pal2(datadir + "/B1855+09_noise.txt") params2 = get_noise_from_pal2(datadir + "/J1909-3744_noise.txt") params.update(params2) psrs = self.psrs if npsrs == 2 else [self.psrs[0]] if inc_corr: params.update({"GW_gamma": 4.33, "GW_log10_A": -15.0}) # find the maximum time span to set GW frequency sampling tmin = [p.toas.min() for p in psrs] tmax = [p.toas.max() for p in psrs] Tspan = np.max(tmax) - np.min(tmin) # setup basic model efac = parameter.Constant() equad = parameter.Constant() ecorr = parameter.Constant() log10_A = parameter.Constant() gamma = parameter.Constant() selection = Selection(selections.by_backend) ef = white_signals.MeasurementNoise(efac=efac, selection=selection) eq = white_signals.EquadNoise(log10_equad=equad, selection=selection) ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr, selection=selection) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) rn = gp_signals.FourierBasisGP(pl) orf = utils.hd_orf() crn = gp_signals.FourierBasisCommonGP(pl, orf, components=20, name="GW", Tspan=Tspan) tm = gp_signals.TimingModel() log10_sigma = parameter.Uniform(-10, -5) log10_lam = parameter.Uniform(np.log10(86400), np.log10(1500 * 86400)) basis = create_quant_matrix(dt=7 * 86400) prior = se_kernel(log10_sigma=log10_sigma, log10_lam=log10_lam) se = gp_signals.BasisGP(prior, basis, name="se") # set up kernel stuff if isinstance(inc_kernel, bool): inc_kernel = [inc_kernel] * npsrs if inc_corr: s = ef + eq + ec + rn + crn + tm else: s = ef + eq + ec + rn + tm models = [] for ik, psr in zip(inc_kernel, psrs): snew = s + se if ik else s models.append(snew(psr)) pta = signal_base.PTA(models) # set parameters pta.set_default_params(params) # SE kernel parameters log10_sigmas, log10_lams = [-7.0, -6.5], [7.0, 6.5] params.update({ "B1855+09_se_log10_lam": log10_lams[0], "B1855+09_se_log10_sigma": log10_sigmas[0], "J1909-3744_se_log10_lam": log10_lams[1], "J1909-3744_se_log10_sigma": log10_sigmas[1], }) # get parameters efacs, equads, ecorrs, log10_A, gamma = [], [], [], [], [] lsig, llam = [], [] for pname in [p.name for p in psrs]: efacs.append([ params[key] for key in sorted(params.keys()) if "efac" in key and pname in key ]) equads.append([ params[key] for key in sorted(params.keys()) if "equad" in key and pname in key ]) ecorrs.append([ params[key] for key in sorted(params.keys()) if "ecorr" in key and pname in key ]) log10_A.append(params["{}_red_noise_log10_A".format(pname)]) gamma.append(params["{}_red_noise_gamma".format(pname)]) lsig.append(params["{}_se_log10_sigma".format(pname)]) llam.append(params["{}_se_log10_lam".format(pname)]) GW_gamma = 4.33 GW_log10_A = -15.0 # correct value tflags = [sorted(list(np.unique(p.backend_flags))) for p in psrs] cfs, logdets, phis, Ts = [], [], [], [] for ii, (ik, psr, flags) in enumerate(zip(inc_kernel, psrs, tflags)): nvec0 = np.zeros_like(psr.toas) for ct, flag in enumerate(flags): ind = psr.backend_flags == flag nvec0[ind] = efacs[ii][ct]**2 * psr.toaerrs[ind]**2 nvec0[ind] += 10**(2 * equads[ii][ct]) * np.ones(np.sum(ind)) # get the basis bflags = psr.backend_flags Umats = [] for flag in np.unique(bflags): mask = bflags == flag Umats.append( utils.create_quantization_matrix(psr.toas[mask])[0]) nepoch = sum(U.shape[1] for U in Umats) U = np.zeros((len(psr.toas), nepoch)) jvec = np.zeros(nepoch) netot = 0 for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag nn = Umats[ct].shape[1] U[mask, netot:nn + netot] = Umats[ct] jvec[netot:nn + netot] = 10**(2 * ecorrs[ii][ct]) netot += nn # get covariance matrix cov = np.diag(nvec0) + np.dot(U * jvec[None, :], U.T) cf = sl.cho_factor(cov) logdet = np.sum(2 * np.log(np.diag(cf[0]))) cfs.append(cf) logdets.append(logdet) F, f2 = utils.createfourierdesignmatrix_red(psr.toas, nmodes=20, Tspan=Tspan) Mmat = psr.Mmat.copy() norm = np.sqrt(np.sum(Mmat**2, axis=0)) Mmat /= norm U2, avetoas = create_quant_matrix(psr.toas, dt=7 * 86400) if ik: T = np.hstack((F, Mmat, U2)) else: T = np.hstack((F, Mmat)) Ts.append(T) phi = utils.powerlaw(f2, log10_A=log10_A[ii], gamma=gamma[ii]) if inc_corr: phigw = utils.powerlaw(f2, log10_A=GW_log10_A, gamma=GW_gamma) else: phigw = np.zeros(40) K = se_kernel(avetoas, log10_sigma=log10_sigmas[ii], log10_lam=log10_lams[ii]) k = np.diag( np.concatenate((phi + phigw, np.ones(Mmat.shape[1]) * 1e40))) if ik: k = sl.block_diag(k, K) phis.append(k) # manually compute loglike loglike = 0 TNrs, TNTs = [], [] for ct, psr in enumerate(psrs): TNrs.append(np.dot(Ts[ct].T, sl.cho_solve(cfs[ct], psr.residuals))) TNTs.append(np.dot(Ts[ct].T, sl.cho_solve(cfs[ct], Ts[ct]))) loglike += -0.5 * ( np.dot(psr.residuals, sl.cho_solve(cfs[ct], psr.residuals)) + logdets[ct]) TNr = np.concatenate(TNrs) phi = sl.block_diag(*phis) if inc_corr: hd = utils.hd_orf(psrs[0].pos, psrs[1].pos) phi[len(phis[0]):len(phis[0]) + 40, :40] = np.diag(phigw * hd) phi[:40, len(phis[0]):len(phis[0]) + 40] = np.diag(phigw * hd) cf = sl.cho_factor(phi) phiinv = sl.cho_solve(cf, np.eye(phi.shape[0])) logdetphi = np.sum(2 * np.log(np.diag(cf[0]))) Sigma = sl.block_diag(*TNTs) + phiinv cf = sl.cho_factor(Sigma) expval = sl.cho_solve(cf, TNr) logdetsigma = np.sum(2 * np.log(np.diag(cf[0]))) loglike -= 0.5 * (logdetphi + logdetsigma) loglike += 0.5 * np.dot(TNr, expval) method = ["partition", "sparse", "cliques"] for mth in method: eloglike = pta.get_lnlikelihood(params, phiinv_method=mth) msg = "Incorrect like for npsr={}, phiinv={}".format(npsrs, mth) assert np.allclose(eloglike, loglike), msg
def test_combine_signals(self): """Test for combining different signals.""" # set up signal parameter ecorr = parameter.Uniform(-10, -5) ec = gp_signals.EcorrBasisModel(log10_ecorr=ecorr) pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) rn = gp_signals.FourierBasisGP(spectrum=pl, components=30) log10_sigma = parameter.Uniform(-10, -5) log10_lam = parameter.Uniform(np.log10(86400), np.log10(1500 * 86400)) basis = create_quant_matrix(dt=7 * 86400) prior = se_kernel(log10_sigma=log10_sigma, log10_lam=log10_lam) se = gp_signals.BasisGP(prior, basis, name="se") ts = gp_signals.TimingModel() s = ec + rn + ts + se m = s(self.psr) # parameters ecorr = -6.4 log10_A, gamma = -14.5, 4.33 log10_lam, log10_sigma = 7.4, -6.4 params = { "B1855+09_basis_ecorr_log10_ecorr": ecorr, "B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma, "B1855+09_se_log10_lam": log10_lam, "B1855+09_se_log10_sigma": log10_sigma, } # combined basis matrix U = utils.create_quantization_matrix(self.psr.toas)[0] M = self.psr.Mmat.copy() norm = np.sqrt(np.sum(M ** 2, axis=0)) M /= norm F, f2 = utils.createfourierdesignmatrix_red(self.psr.toas, nmodes=30) U2, avetoas = create_quant_matrix(self.psr.toas, dt=7 * 86400) T = np.hstack((U, F, M, U2)) # combined prior vector jvec = 10 ** (2 * ecorr) * np.ones(U.shape[1]) phim = np.ones(self.psr.Mmat.shape[1]) * 1e40 phi = utils.powerlaw(f2, log10_A=log10_A, gamma=gamma) K = se_kernel(avetoas, log10_lam=log10_lam, log10_sigma=log10_sigma) phivec = np.concatenate((jvec, phi, phim)) phi = sl.block_diag(np.diag(phivec), K) phiinv = np.linalg.inv(phi) # basis matrix test msg = "Basis matrix incorrect for combined signal." assert np.allclose(T, m.get_basis(params)), msg # Kernal test msg = "Prior matrix incorrect for combined signal." assert np.allclose(m.get_phi(params), phi), msg # inverse Kernel test msg = "Prior matrix inverse incorrect for combined signal." assert np.allclose(m.get_phiinv(params), phiinv), msg # test shape msg = "Basis matrix shape incorrect size for combined signal." assert m.get_basis(params).shape == T.shape, msg
dm_basis = utils.createfourierdesignmatrix_dm(nmodes=50, Tspan=None) dmn = gp_signals.BasisGP(pl_dm, dm_basis, name='dm_gp', coefficients=False) # spin noise log10_A = parameter.Constant() gamma = parameter.Constant() pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) selection = selections.Selection(selections.no_selection) spn = gp_signals.FourierBasisGP(pl, components=50, Tspan=None, coefficients=False, selection=selection, modes=None) dp = DPDM.dpdm_block(type_='Bayes') tm = gp_signals.TimingModel() eph = deterministic_signals.PhysicalEphemerisSignal(use_epoch_toas=True) wnb = models.white_noise_block(vary=False) model = tm + dp + wnb + dmn + spn + eph nparams = [] # Get the number of parameters of each pulsar signals = [] for psr in psrs: signal = model(psr) nparams.append(len(signal.params) - 5) # Subtracting common DPDM params signals.append(signal) PTA = signal_base.PTA(signals) ndim = len(PTA.params) + 5 # Use the best fit noise parameters!
def _ecorr_test_ipta(self, method="sparse"): """Test of sparse/sherman-morrison ecorr signal and solve methods.""" selection = Selection(selections.nanograv_backends) efac = parameter.Uniform(0.1, 5) ecorr = parameter.Uniform(-10, -5) ef = white_signals.MeasurementNoise(efac=efac) ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr, selection=selection, method=method) tm = gp_signals.TimingModel() s = ef + ec + tm m = s(self.ipsr) # set parameters efacs = [1.3] ecorrs = [-6.1, -6.2, -6.3, -6.4, -7.2, -8.4, -7.1, -7.9] params = { "J1713+0747_efac": efacs[0], "J1713+0747_ASP-L_log10_ecorr": ecorrs[0], "J1713+0747_ASP-S_log10_ecorr": ecorrs[1], "J1713+0747_GASP-8_log10_ecorr": ecorrs[2], "J1713+0747_GASP-L_log10_ecorr": ecorrs[3], "J1713+0747_GUPPI-8_log10_ecorr": ecorrs[4], "J1713+0747_GUPPI-L_log10_ecorr": ecorrs[5], "J1713+0747_PUPPI-L_log10_ecorr": ecorrs[6], "J1713+0747_PUPPI-S_log10_ecorr": ecorrs[7], } # get EFAC Nvec nvec0 = efacs[0]**2 * self.ipsr.toaerrs**2 # get the basis flags = [ "ASP-L", "ASP-S", "GASP-8", "GASP-L", "GUPPI-8", "GUPPI-L", "PUPPI-L", "PUPPI-S" ] bflags = self.ipsr.backend_flags Umats = [] for flag in np.unique(bflags): if flag in flags: mask = bflags == flag Umats.append( utils.create_quantization_matrix(self.ipsr.toas[mask], nmin=2)[0]) nepoch = sum(U.shape[1] for U in Umats) U = np.zeros((len(self.ipsr.toas), nepoch)) jvec = np.zeros(nepoch) netot, ct = 0, 0 for flag in np.unique(bflags): if flag in flags: mask = bflags == flag nn = Umats[ct].shape[1] U[mask, netot:nn + netot] = Umats[ct] jvec[netot:nn + netot] = 10**(2 * ecorrs[ct]) netot += nn ct += 1 # get covariance matrix wd = Woodbury(nvec0, U, jvec) # test msg = "EFAC/ECORR {} logdet incorrect.".format(method) N = m.get_ndiag(params) assert np.allclose(N.solve(self.ipsr.residuals, logdet=True)[1], wd.logdet(), rtol=1e-8), msg msg = "EFAC/ECORR {} D1 solve incorrect.".format(method) assert np.allclose(N.solve(self.ipsr.residuals), wd.solve(self.ipsr.residuals), rtol=1e-8), msg msg = "EFAC/ECORR {} 1D1 solve incorrect.".format(method) assert np.allclose( N.solve(self.ipsr.residuals, left_array=self.ipsr.residuals), np.dot(self.ipsr.residuals, wd.solve(self.ipsr.residuals)), rtol=1e-8, ), msg msg = "EFAC/ECORR {} 2D1 solve incorrect.".format(method) T = m.get_basis() assert np.allclose(N.solve(self.ipsr.residuals, left_array=T), np.dot(T.T, wd.solve(self.ipsr.residuals)), rtol=1e-8), msg msg = "EFAC/ECORR {} 2D2 solve incorrect.".format(method) assert np.allclose(N.solve(T, left_array=T), np.dot(T.T, wd.solve(T)), rtol=1e-8), msg