def test_fourier_red_noise_pshift(self): """Test that red noise signal returns correct values.""" # set up signal parameter pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) rn = gp_signals.FourierBasisGP(spectrum=pl, components=30, pshift=True, pseed=42) rnm = rn(self.psr) # parameters log10_A, gamma = -14.5, 4.33 params = {"B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma} # basis matrix test F, f2 = utils.createfourierdesignmatrix_red(self.psr.toas, nmodes=30, pshift=True, pseed=42) msg = "F matrix incorrect for GP Fourier signal." assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test phi = utils.powerlaw(f2, log10_A=log10_A, gamma=gamma) msg = "Spectrum incorrect for GP Fourier signal." assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for GP Fourier signal." assert np.all(rnm.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert rnm.get_basis(params).shape == F.shape, msg
def test_fourier_red_user_freq_array(self): """Test that red noise signal returns correct values with user defined frequency array.""" # set parameters log10_A, gamma = -14.5, 4.33 params = {"B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma} F, f2 = utils.createfourierdesignmatrix_red(self.psr.toas, nmodes=30) # set up signal model. use list of frequencies to make basis pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) rn = gp_signals.FourierBasisGP(spectrum=pl, modes=f2[::2]) rnm = rn(self.psr) # basis matrix test msg = "F matrix incorrect for GP Fourier signal." assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test phi = utils.powerlaw(f2, log10_A=log10_A, gamma=gamma) msg = "Spectrum incorrect for GP Fourier signal." assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for GP Fourier signal." assert np.all(rnm.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert rnm.get_basis(params).shape == F.shape, msg
def test_fourier_red_noise(self): """Test that red noise signal returns correct values.""" # set up signal parameter pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(1,7)) rn = gs.FourierBasisGP(spectrum=pl, components=30) rnm = rn(self.psr) # parameters log10_A, gamma = -14.5, 4.33 params = {'B1855+09_log10_A': log10_A, 'B1855+09_gamma': gamma} # basis matrix test F, f2 = utils.createfourierdesignmatrix_red( self.psr.toas, nmodes=30) msg = 'F matrix incorrect for GP Fourier signal.' assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test phi = utils.powerlaw(f2, log10_A=log10_A, gamma=gamma) msg = 'Spectrum incorrect for GP Fourier signal.' assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = 'Spectrum inverse incorrect for GP Fourier signal.' assert np.all(rnm.get_phiinv(params) == 1/phi), msg # test shape msg = 'F matrix shape incorrect' assert rnm.get_basis(params).shape == F.shape, msg
def test_gp_parameter(self): """Test GP basis model with parameterized basis.""" pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(0, 7)) basis_env = utils.createfourierdesignmatrix_env( log10_Amp=parameter.Uniform(-10, -5), t0=parameter.Uniform(4.3e9, 5e9), log10_Q=parameter.Uniform(0, 4)) basis_red = utils.createfourierdesignmatrix_red() rn_env = gp_signals.BasisGP(pl, basis_env, name="env") rn = gp_signals.BasisGP(pl, basis_red) s = rn_env + rn m = s(self.psr) # parameters log10_A, gamma = -14.5, 4.33 log10_A_env, gamma_env = -14.0, 2.5 log10_Amp, log10_Q, t0 = -7.3, np.log10(345), 55000 * 86400 params = { "B1855+09_log10_A": log10_A, "B1855+09_gamma": gamma, "B1855+09_env_log10_A": log10_A_env, "B1855+09_env_gamma": gamma_env, "B1855+09_env_log10_Q": log10_Q, "B1855+09_env_log10_Amp": log10_Amp, "B1855+09_env_t0": t0, } # get basis Fred, f2_red = utils.createfourierdesignmatrix_red(self.psr.toas, nmodes=30) Fenv, f2_env = utils.createfourierdesignmatrix_env(self.psr.toas, nmodes=30, log10_Amp=log10_Amp, log10_Q=log10_Q, t0=t0) F = np.hstack((Fenv, Fred)) phi_env = utils.powerlaw(f2_env, log10_A=log10_A_env, gamma=gamma_env) phi_red = utils.powerlaw(f2_red, log10_A=log10_A, gamma=gamma) phi = np.concatenate((phi_env, phi_red)) # basis matrix test msg = "F matrix incorrect for GP Fourier signal." assert np.allclose(F, m.get_basis(params)), msg # spectrum test msg = "Spectrum incorrect for GP Fourier signal." assert np.all(m.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for GP Fourier signal." assert np.all(m.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert m.get_basis(params).shape == F.shape, msg
def test_red_noise_add(self): """Test that red noise addition only returns independent columns.""" # set up signals pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(1,7)) cpl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12)('log10_Agw'), gamma=parameter.Uniform(1,7)('gamma_gw')) # parameters log10_A, gamma = -14.5, 4.33 log10_Ac, gammac = -15.5, 1.33 params = {'B1855+09_log10_A': log10_A, 'B1855+09_gamma': gamma, 'log10_Agw': log10_Ac, 'gamma_gw': gammac} Tmax = self.psr.toas.max() - self.psr.toas.min() tpars = [(30, 20, Tmax, Tmax), (20, 30, Tmax, Tmax), (30, 30, Tmax, Tmax), (30, 20, Tmax, 1.123*Tmax), (20, 30, Tmax, 1.123*Tmax), (30, 30, 1.123*Tmax, Tmax)] for (nf1, nf2, T1, T2) in tpars: rn = gs.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1) crn = gs.FourierBasisGP(spectrum=cpl, components=nf2, Tspan=T2) s = rn + crn rnm = s(self.psr) # set up frequencies F1, f1 = utils.createfourierdesignmatrix_red( self.psr.toas, nmodes=nf1, Tspan=T1) F2, f2 = utils.createfourierdesignmatrix_red( self.psr.toas, nmodes=nf2, Tspan=T2) # test power spectrum p1 = utils.powerlaw(f1, log10_A, gamma) p2 = utils.powerlaw(f2, log10_Ac, gammac) if T1 == T2: nf = max(2*nf1, 2*nf2) phi = np.zeros(nf) F = F1 if nf1 > nf2 else F2 phi[:2*nf1] = p1 phi[:2*nf2] += p2 F[:,] else: phi = np.concatenate((p1, p2)) F = np.hstack((F1, F2)) msg = 'Combined red noise PSD incorrect ' msg += 'for {} {} {} {}'.format(nf1, nf2, T1, T2) assert np.all(rnm.get_phi(params) == phi), msg msg = 'Combined red noise PSD inverse incorrect ' msg += 'for {} {} {} {}'.format(nf1, nf2, T1, T2) assert np.all(rnm.get_phiinv(params) == 1/phi), msg msg = 'Combined red noise Fmat incorrect ' msg += 'for {} {} {} {}'.format(nf1, nf2, T1, T2) assert np.allclose(F, rnm.get_basis(params)), msg
def test_fourier_red_noise_backend(self): """Test that red noise-backend signal returns correct values.""" # set up signal parameter pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) selection = Selection(selections.by_backend) rn = gp_signals.FourierBasisGP(spectrum=pl, components=30, selection=selection) rnm = rn(self.psr) # parameters log10_As = [-14, -14.4, -15, -14.8] gammas = [2.3, 4.4, 1.8, 5.6] params = { "B1855+09_red_noise_430_ASP_gamma": gammas[0], "B1855+09_red_noise_430_PUPPI_gamma": gammas[1], "B1855+09_red_noise_L-wide_ASP_gamma": gammas[2], "B1855+09_red_noise_L-wide_PUPPI_gamma": gammas[3], "B1855+09_red_noise_430_ASP_log10_A": log10_As[0], "B1855+09_red_noise_430_PUPPI_log10_A": log10_As[1], "B1855+09_red_noise_L-wide_ASP_log10_A": log10_As[2], "B1855+09_red_noise_L-wide_PUPPI_log10_A": log10_As[3], } # get the basis bflags = self.psr.backend_flags Fmats, fs, phis = [], [], [] for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag F, f = utils.createfourierdesignmatrix_red(self.psr.toas[mask], 30) Fmats.append(F) fs.append(f) phis.append(utils.powerlaw(f, log10_As[ct], gammas[ct])) nf = sum(F.shape[1] for F in Fmats) F = np.zeros((len(self.psr.toas), nf)) phi = np.hstack([p for p in phis]) nftot = 0 for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag nn = Fmats[ct].shape[1] F[mask, nftot:nn + nftot] = Fmats[ct] nftot += nn msg = "F matrix incorrect for GP Fourier backend signal." assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test msg = "Spectrum incorrect for GP Fourier backend signal." assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for GP Fourier backend signal." assert np.all(rnm.get_phiinv(params) == 1 / phi), msg # test shape msg = "F matrix shape incorrect" assert rnm.get_basis(params).shape == F.shape, msg
def test_gp_parameter(self): """Test GP basis model with parameterized basis.""" pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(0, 7)) basis_env = utils.createfourierdesignmatrix_env( log10_Amp=parameter.Uniform(-10, -5), t0=parameter.Uniform(4.3e9, 5e9), log10_Q=parameter.Uniform(0,4)) basis_red = utils.createfourierdesignmatrix_red() rn_env = gs.BasisGP(pl, basis_env, name='env') rn = gs.BasisGP(pl, basis_red) s = rn_env + rn m = s(self.psr) # parameters log10_A, gamma = -14.5, 4.33 log10_A_env, gamma_env = -14.0, 2.5 log10_Amp, log10_Q, t0 = -7.3, np.log10(345), 55000*86400 params = {'B1855+09_log10_A': log10_A, 'B1855+09_gamma': gamma, 'B1855+09_env_log10_A': log10_A_env, 'B1855+09_env_gamma': gamma_env, 'B1855+09_env_log10_Q': log10_Q, 'B1855+09_env_log10_Amp': log10_Amp, 'B1855+09_env_t0': t0} # get basis Fred, f2_red = utils.createfourierdesignmatrix_red( self.psr.toas, nmodes=30) Fenv, f2_env = utils.createfourierdesignmatrix_env( self.psr.toas, nmodes=30, log10_Amp=log10_Amp, log10_Q=log10_Q, t0=t0) F = np.hstack((Fenv, Fred)) phi_env = utils.powerlaw(f2_env, log10_A=log10_A_env, gamma=gamma_env) phi_red = utils.powerlaw(f2_red, log10_A=log10_A, gamma=gamma) phi = np.concatenate((phi_env, phi_red)) # basis matrix test msg = 'F matrix incorrect for GP Fourier signal.' assert np.allclose(F, m.get_basis(params)), msg # spectrum test msg = 'Spectrum incorrect for GP Fourier signal.' assert np.all(m.get_phi(params) == phi), msg # inverse spectrum test msg = 'Spectrum inverse incorrect for GP Fourier signal.' assert np.all(m.get_phiinv(params) == 1/phi), msg # test shape msg = 'F matrix shape incorrect' assert m.get_basis(params).shape == F.shape, msg
def test_fourier_red_noise_backend(self): """Test that red noise-backend signal returns correct values.""" # set up signal parameter pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(1,7)) selection = Selection(selections.by_backend) rn = gs.FourierBasisGP(spectrum=pl, components=30, selection=selection) rnm = rn(self.psr) # parameters log10_As = [-14, -14.4, -15, -14.8] gammas = [2.3, 4.4, 1.8, 5.6] params = {'B1855+09_430_ASP_gamma': gammas[0], 'B1855+09_430_PUPPI_gamma': gammas[1], 'B1855+09_L-wide_ASP_gamma': gammas[2], 'B1855+09_L-wide_PUPPI_gamma': gammas[3], 'B1855+09_430_ASP_log10_A': log10_As[0], 'B1855+09_430_PUPPI_log10_A': log10_As[1], 'B1855+09_L-wide_ASP_log10_A': log10_As[2], 'B1855+09_L-wide_PUPPI_log10_A': log10_As[3]} # get the basis bflags = self.psr.backend_flags Fmats, fs, phis = [], [], [] for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag F, f = utils.createfourierdesignmatrix_red( self.psr.toas[mask], 30) Fmats.append(F) fs.append(f) phis.append(utils.powerlaw(f, log10_As[ct], gammas[ct])) nf = sum(F.shape[1] for F in Fmats) F = np.zeros((len(self.psr.toas), nf)) phi = np.hstack(p for p in phis) nftot = 0 for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag nn = Fmats[ct].shape[1] F[mask, nftot:nn+nftot] = Fmats[ct] nftot += nn msg = 'F matrix incorrect for GP Fourier backend signal.' assert np.allclose(F, rnm.get_basis(params)), msg # spectrum test msg = 'Spectrum incorrect for GP Fourier backend signal.' assert np.all(rnm.get_phi(params) == phi), msg # inverse spectrum test msg = 'Spectrum inverse incorrect for GP Fourier backend signal.' assert np.all(rnm.get_phiinv(params) == 1/phi), msg # test shape msg = 'F matrix shape incorrect' assert rnm.get_basis(params).shape == F.shape, msg
def chromred(self, option="vary"): """ This is an generalization of DM noise, with the dependence of Fourier amplitudes on radio frequency nu as ~ 1/nu^chi, where chi is a free parameter. Examples of chi: - Pulse scattering in the ISM: chi = 4 (Lyne A., Graham-Smith F., 2012, Pulsar astronomy) - Refractive propagation: chi = 6.4 (Shannon, R. M., and J. M. Cordes. MNRAS, 464.2 (2017): 2075-2089). """ log10_A = parameter.Uniform(self.params.dmn_lgA[0], self.params.dmn_lgA[1]) gamma = parameter.Uniform(self.params.dmn_gamma[0], self.params.dmn_gamma[1]) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) nfreqs = self.determine_nfreqs(sel_func_name=None) if option == "vary": idx = parameter.Uniform(self.params.chrom_idx[0], \ self.params.chrom_idx[1]) else: idx = option chr_basis = models.createfourierdesignmatrix_chromatic( nmodes=nfreqs, Tspan=self.params.Tspan, idx=idx) chrn = gp_signals.BasisGP(pl, chr_basis, name='chromatic_gp') return chrn
def spin_noise(self, option="powerlaw"): """ Achromatic red noise process is called spin noise, although generally this model is used to model any unknown red noise. If this model is preferred over chromatic models then the observed noise is really spin noise, associated with pulsar rotational irregularities. """ log10_A = parameter.Uniform(self.params.sn_lgA[0], self.params.sn_lgA[1]) gamma = parameter.Uniform(self.params.sn_gamma[0], self.params.sn_gamma[1]) if option == "powerlaw": pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) elif option == "turnover": fc = parameter.Uniform(self.params.sn_fc[0], self.params.sn_fc[1]) pl = powerlaw_bpl(log10_A=log10_A, gamma=gamma, fc=fc, components=self.params.red_general_nfouriercomp) nfreqs = self.determine_nfreqs(sel_func_name=None) sn = gp_signals.FourierBasisGP(spectrum=pl, Tspan=self.params.Tspan, name='red_noise', components=nfreqs) return sn
def paired_ppta_band_noise(self, option=[]): """ Including band noise terms for paired values of the PPTA "-B" flag: joint 1020-cm and 4050-cm red processes. """ for ii, paired_band_term in enumerate(option): log10_A = parameter.Uniform(self.params.syn_lgA[0], self.params.syn_lgA[1]) gamma = parameter.Uniform(self.params.syn_gamma[0],\ self.params.syn_gamma[1]) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) setattr(self, paired_band_term, globals()[paired_band_term]) nfreqs = self.determine_nfreqs(sel_func_name=paired_band_term) pbn_term = gp_signals.FourierBasisGP(spectrum=pl, Tspan=self.params.Tspan, name='band_noise_' + paired_band_term, selection=selections.Selection( \ self.__dict__[paired_band_term] ), components=nfreqs) if ii == 0: pbn = pbn_term elif ii > 0: pbn += pbn_term return pbn
def red_noise_block(prior='log-uniform', Tspan=None): """ Returns red noise model: 1. Red noise modeled as a power-law with 30 sampling frequencies :param prior: Prior on log10_A. Default if "log-uniform". Use "uniform" for upper limits. :param Tspan: Sets frequency sampling f_i = i / Tspan. Default will use overall time span for indivicual pulsar. """ # red noise parameters if prior == 'uniform': log10_A = parameter.LinearExp(-20, -11) elif prior == 'log-uniform': log10_A = parameter.Uniform(-20, -11) else: raise ValueError('Unknown prior for red noise amplitude!') gamma = parameter.Uniform(0, 7) # red noise signal pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) rn = gp_signals.FourierBasisGP(pl, components=30, Tspan=Tspan) return rn
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 dm_noise(self, option="powerlaw"): """ A term to account for stochastic variations in DM. It is based on spin noise model, with Fourier amplitudes depending on radio frequency nu as ~ 1/nu^2. """ log10_A = parameter.Uniform(self.params.dmn_lgA[0], self.params.dmn_lgA[1]) gamma = parameter.Uniform(self.params.dmn_gamma[0], self.params.dmn_gamma[1]) if option == "powerlaw": pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) elif option == "turnover": fc = parameter.Uniform(self.params.sn_fc[0], self.params.sn_fc[1]) pl = powerlaw_bpl(log10_A=log10_A, gamma=gamma, fc=fc, components=self.params.red_general_nfouriercomp) nfreqs = self.determine_nfreqs(sel_func_name=None) dm_basis = utils.createfourierdesignmatrix_dm(nmodes=nfreqs, Tspan=self.params.Tspan, fref=self.params.fref) dmn = gp_signals.BasisGP(pl, dm_basis, name='dm_gp') return dmn
def test_parameterized_orf(self): T1 = 3.16e8 pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(1,7)) orf = hd_orf_generic(a=parameter.Uniform(0,5), b=parameter.Uniform(0,5), c=parameter.Uniform(0,5)) rn = gp_signals.FourierBasisGP(spectrum=pl, Tspan=T1, components=30) crn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=orf, components=30, name='gw', Tspan=T1) model = rn + crn pta = model(self.psrs[0]) + model(self.psrs[1]) lA1, gamma1 = -13, 1e-15 lA2, gamma2 = -13.3, 1e-15 lAc, gammac = -13.1, 1e-15 a, b, c = 1.9, 0.4, 0.23 params = {'gw_log10_A': lAc, 'gw_gamma': gammac, 'gw_a': a, 'gw_b':b, 'gw_c':c, 'B1855+09_log10_A': lA1, 'B1855+09_gamma': gamma1, 'J1909-3744_log10_A': lA2, 'J1909-3744_gamma': gamma2} phi = pta.get_phi(params) phiinv = pta.get_phiinv(params) F1, f1 = utils.createfourierdesignmatrix_red( self.psrs[0].toas, nmodes=30, Tspan=T1) F2, f2 = utils.createfourierdesignmatrix_red( self.psrs[1].toas, nmodes=30, Tspan=T1) msg = 'F matrix incorrect' assert np.allclose(pta.get_basis(params)[0], F1, rtol=1e-10), msg assert np.allclose(pta.get_basis(params)[1], F2, rtol=1e-10), msg nftot = 120 phidiag = np.zeros(nftot) phit = np.zeros((nftot, nftot)) phidiag[:60] = utils.powerlaw(f1, lA1, gamma1) phidiag[:60] += utils.powerlaw(f1, lAc, gammac) phidiag[60:] = utils.powerlaw(f2, lA2, gamma2) phidiag[60:] += utils.powerlaw(f2, lAc, gammac) phit[np.diag_indices(nftot)] = phidiag orf = hd_orf_generic(self.psrs[0].pos, self.psrs[1].pos, a=a, b=b, c=c) spec = utils.powerlaw(f1, log10_A=lAc, gamma=gammac) phit[:60, 60:] = np.diag(orf*spec) phit[60:, :60] = phit[:60, 60:] msg = '{} {}'.format(np.diag(phi), np.diag(phit)) assert np.allclose(phi, phit, rtol=1e-15, atol=1e-17), msg msg = 'PTA Phi inverse is incorrect {}.'.format(params) assert np.allclose(phiinv, np.linalg.inv(phit), rtol=1e-15, atol=1e-17), msg
def gwb(self,option="hd_vary_gamma"): """ Spatially-correlated quadrupole signal from the nanohertz stochastic gravitational-wave background. """ name = 'gw' if "_nfreqs" in option: split_idx_nfreqs = option.split('_').index('nfreqs') - 1 nfreqs = int(option.split('_')[split_idx_nfreqs]) else: nfreqs = self.determine_nfreqs(sel_func_name=None, common_signal=True) if "_gamma" in option: amp_name = '{}_log10_A'.format(name) if self.params.gwb_lgA_prior == "uniform": gwb_log10_A = parameter.Uniform(self.params.gwb_lgA[0], self.params.gwb_lgA[1])(amp_name) elif self.params.gwb_lgA_prior == "linexp": gwb_log10_A = parameter.LinearExp(self.params.gwb_lgA[0], self.params.gwb_lgA[1])(amp_name) gam_name = '{}_gamma'.format(name) if "vary_gamma" in option: gwb_gamma = parameter.Uniform(self.params.gwb_gamma[0], self.params.gwb_gamma[1])(gam_name) elif "fixed_gamma" in option: gwb_gamma = parameter.Constant(4.33)(gam_name) else: split_idx_gamma = option.split('_').index('gamma') - 1 gamma_val = float(option.split('_')[split_idx_gamma]) gwb_gamma = parameter.Constant(gamma_val)(gam_name) gwb_pl = utils.powerlaw(log10_A=gwb_log10_A, gamma=gwb_gamma) elif "freesp" in option: amp_name = '{}_log10_rho'.format(name) log10_rho = parameter.Uniform(self.params.gwb_lgrho[0], self.params.gwb_lgrho[1], size=nfreqs)(amp_name) gwb_pl = gp_priors.free_spectrum(log10_rho=log10_rho) if "hd" in option: orf = utils.hd_orf() gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs, name='gwb', Tspan=self.params.Tspan) else: gwb = gp_signals.FourierBasisGP(gwb_pl, components=nfreqs, name='gwb', Tspan=self.params.Tspan) return gwb
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 gwb(self,option="common_pl"): """ Spatially-correlated quadrupole signal from the nanohertz stochastic gravitational-wave background. """ gwb_log10_A = parameter.Uniform(params.gwb_lgA[0],params.gwb_lgA[1]) if option=="common_pl": gwb_gamma = parameter.Uniform(params.gwb_gamma[0],params.gwb_gamma[1]) elif option=="fixed_gamma": gwb_gamma = parameter.Constant(4.33) gwb_pl = utils.powerlaw(log10_A=gwb_log10_A, gamma=gwb_gamma) nfreqs = self.determine_nfreqs(sel_func_name=None) orf = utils.hd_orf() gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=nfreqs, \ name='gwb', Tspan=self.params.Tspan) return gwb
def test_summary(self): """ Test summary table.""" T1, T3 = 3.16e8, 3.16e8 nf1 = 30 pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(1,7)) orf = utils.hd_orf() rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1) crn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=orf, components=1, name='gw', Tspan=T3) model = rn + crn pta = model(self.psrs[0]) + model(self.psrs[1]) pta.summary()
def ppta_band_noise(self,option=[]): """ Including red noise terms by the PPTA "-B" flag, only with flagvals in noise model file. It is considered a derivative of system noise in our code. See Lentati, Lindley, et al. MNRAS 458.2 (2016): 2161-2187. """ for ii, band_term in enumerate(option): log10_A = parameter.Uniform(self.params.syn_lgA[0],self.params.syn_lgA[1]) gamma = parameter.Uniform(self.params.syn_gamma[0],\ self.params.syn_gamma[1]) selection_function_name = 'band_noise_selection_' + \ str(self.sys_noise_count) setattr(self, selection_function_name, selection_factory(selection_function_name)) band_term, nfreqs = self.option_nfreqs(band_term, \ selection_flag='B', \ sel_func_name=selection_function_name) if "turnover" in band_term: fc = parameter.Uniform(self.params.sn_fc[0],self.params.sn_fc[1]) pl = powerlaw_bpl(log10_A=log10_A, gamma=gamma, fc=fc, components=self.params.red_general_nfouriercomp) option_split = band_term.split("_") del option_split[option_split.index("turnover")] band_term = "_".join(option_split) else: pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) tspan = self.determine_tspan(sel_func_name=selection_function_name) syn_term = gp_signals.FourierBasisGP(spectrum=pl, Tspan=tspan, name='band_noise_' + \ str(self.sys_noise_count), selection=selections.Selection( \ self.__dict__[selection_function_name] ), components=nfreqs) if ii == 0: syn = syn_term elif ii > 0: syn += syn_term self.sys_noise_count += 1 return syn
def test_summary(self): """ Test summary table.""" T1, T3 = 3.16e8, 3.16e8 nf1 = 30 pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) orf = utils.hd_orf() rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1) crn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=orf, components=1, name='gw', Tspan=T3) model = rn + crn pta = model(self.psrs[0]) + model(self.psrs[1]) pta.summary(to_stdout=True)
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 test_psd(self): """Test PSD functions.""" Tmax = self.psr.toas.max() - self.psr.toas.min() f = np.linspace(1 / Tmax, 10 / Tmax, 10) log10_A = -15 gamma = 4.33 lf0 = -8.5 kappa = 10 / 3 beta = 0.5 pl = (10**log10_A)**2 / 12.0 / np.pi**2 * const.fyr**(gamma - 3) * f**( -gamma) * f[0] hcf = 10**log10_A * (f / const.fyr)**( (3 - gamma) / 2) / (1 + (10**lf0 / f)**kappa)**beta pt = hcf**2 / 12 / np.pi**2 / f**3 * f[0] msg = "PSD calculation incorrect" assert np.allclose(utils.powerlaw(f, log10_A, gamma), pl), msg assert np.allclose(utils.turnover(f, log10_A, gamma, lf0, kappa, beta), pt), msg
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_psd(self): """Test PSD functions.""" Tmax = self.psr.toas.max() - self.psr.toas.min() f = np.linspace(1/Tmax, 10/Tmax, 10) log10_A = -15 gamma = 4.33 lf0 = -8.5 kappa = 10/3 beta = 0.5 pl = ((10**log10_A)**2 / 12.0 / np.pi**2 * const.fyr**(gamma-3) * f**(-gamma)*f[0]) hcf = (10**log10_A * (f / const.fyr) ** ((3-gamma) / 2) / (1 + (10**lf0 / f) ** kappa) ** beta) pt = hcf**2/12/np.pi**2/f**3 * f[0] msg = 'PSD calculation incorrect' assert np.allclose(utils.powerlaw(f, log10_A, gamma), pl), msg assert np.allclose(utils.turnover(f, log10_A, gamma, lf0, kappa, beta),pt), msg
def chromred(self,option="vary"): """ This is an generalization of DM noise, with the dependence of Fourier amplitudes on radio frequency nu as ~ 1/nu^chi, where chi is a free parameter. Examples of chi: - Pulse scattering in the ISM: chi = 4 (Lyne A., Graham-Smith F., 2012, Pulsar astronomy) - Refractive propagation: chi = 6.4 (Shannon, R. M., and J. M. Cordes. MNRAS, 464.2 (2017): 2075-2089). """ log10_A = parameter.Uniform(self.params.dmn_lgA[0],self.params.dmn_lgA[1]) gamma = parameter.Uniform(self.params.dmn_gamma[0],self.params.dmn_gamma[1]) option, nfreqs = self.option_nfreqs(option, sel_func_name=None) if type(option) is str and "turnover" in option: fc = parameter.Uniform(self.params.sn_fc[0],self.params.sn_fc[1]) pl = powerlaw_bpl(log10_A=log10_A, gamma=gamma, fc=fc, components=self.params.red_general_nfouriercomp) option_split = option.split("_") del option_split[option_split.index("turnover")] option = "_".join(option_split) if option.isdigit(): option = float(option) else: pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) #idx_code = option.split"_").index("idx") + 1 if option=="vary": idx = parameter.Uniform(self.params.chrom_idx[0], \ self.params.chrom_idx[1]) else: idx = option chr_basis = gp_bases.createfourierdesignmatrix_chromatic(nmodes=nfreqs, Tspan=self.params.Tspan, idx=idx) chrn = gp_signals.BasisGP(pl, chr_basis, name='chromatic_gp') return chrn
def paired_ppta_band_noise(self, option=[]): """ Including band noise terms for paired values of the PPTA "-B" flag: joint 1020-cm and 4050-cm red processes. """ for ii, paired_band_term in enumerate(option): log10_A = parameter.Uniform(self.params.syn_lgA[0],self.params.syn_lgA[1]) gamma = parameter.Uniform(self.params.syn_gamma[0],\ self.params.syn_gamma[1]) if "turnover" in paired_band_term: fc = parameter.Uniform(self.params.sn_fc[0],self.params.sn_fc[1]) pl = powerlaw_bpl(log10_A=log10_A, gamma=gamma, fc=fc, components=self.params.red_general_nfouriercomp) option_split = paired_band_term.split("_") del option_split[option_split.index("turnover")] paired_band_term = "_".join(option_split) else: pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) if "nfreqs" not in paired_band_term: setattr(self, paired_band_term, globals()[paired_band_term]) paired_band_term, nfreqs = self.option_nfreqs(paired_band_term, \ sel_func_name=paired_band_term) setattr(self, paired_band_term, globals()[paired_band_term]) tspan = self.determine_tspan(sel_func_name=paired_band_term) pbn_term = gp_signals.FourierBasisGP(spectrum=pl, Tspan=tspan, name='band_noise_' + paired_band_term, selection=selections.Selection( \ self.__dict__[paired_band_term] ), components=nfreqs) if ii == 0: pbn = pbn_term elif ii > 0: pbn += pbn_term return pbn
def test_fourier_red_noise(self): """Test that implicit and explicit GP delays are the same.""" # set up signal parameter pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) rn = gp_signals.FourierBasisGP(spectrum=pl, components=20) rnm = rn(self.psr) rnc = gp_signals.FourierBasisGP(spectrum=pl, components=20, coefficients=True) rnmc = rnc(self.psr) # parameters log10_A, gamma = -14.5, 4.33 params = { "B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma } # get the GP delays in two different ways cf = np.random.randn(40) d1 = np.dot(rnm.get_basis(params), cf) params.update({"B1855+09_red_noise_coefficients": cf}) d2 = rnmc.get_delay(params) msg = "Implicit and explicit GP delays are different." assert np.allclose(d1, d2), msg # np.array cast is needed because we get a KernelArray phimat = np.array(rnm.get_phi(params)) pr1 = (-0.5 * np.sum(cf * cf / phimat) - 0.5 * np.sum(np.log(phimat)) - 0.5 * len(phimat) * np.log(2 * math.pi)) cpar = [p for p in rnmc.params if "coefficients" in p.name][0] pr2 = cpar.get_logpdf(params=params) msg = "Implicit and explicit GP priors are different." assert np.allclose(pr1, pr2), msg
def ppta_band_noise(self, option=[]): """ Including red noise terms by the PPTA "-B" flag, only with flagvals in noise model file. It is considered a derivative of system noise in our code. See Lentati, Lindley, et al. MNRAS 458.2 (2016): 2161-2187. """ for ii, band_term in enumerate(option): log10_A = parameter.Uniform(self.params.syn_lgA[0], self.params.syn_lgA[1]) gamma = parameter.Uniform(self.params.syn_gamma[0],\ self.params.syn_gamma[1]) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) selection_function_name = 'band_noise_selection_' + \ str(self.sys_noise_count) setattr(self, selection_function_name, selection_factory(selection_function_name)) self.psr.sys_flags.append('B') self.psr.sys_flagvals.append(band_term) nfreqs = self.determine_nfreqs( sel_func_name=selection_function_name) tspan = self.determine_tspan(sel_func_name=selection_function_name) syn_term = gp_signals.FourierBasisGP(spectrum=pl, Tspan=tspan, name='band_noise_' + \ str(self.sys_noise_count), selection=selections.Selection( \ self.__dict__[selection_function_name] ), components=nfreqs) if ii == 0: syn = syn_term elif ii > 0: syn += syn_term self.sys_noise_count += 1 return syn
def system_noise(self,option=[]): """ Including red noise terms by "-group" flag, only with flagvals in noise model file. See Lentati, Lindley, et al. MNRAS 458.2 (2016): 2161-2187. """ for ii, sys_noise_term in enumerate(option): log10_A = parameter.Uniform(self.params.syn_lgA[0],self.params.syn_lgA[1]) gamma = parameter.Uniform(self.params.syn_gamma[0],\ self.params.syn_gamma[1]) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma, \ components=self.params.red_general_nfouriercomp) selection_function_name = 'sys_noise_selection_'+str(self.sys_noise_count) setattr(self, selection_function_name, selection_factory(selection_function_name)) sys_noise_term, nfreqs = self.option_nfreqs(sys_noise_term, \ selection_flag='group', \ sel_func_name=selection_function_name) tspan = self.determine_tspan(sel_func_name=selection_function_name) syn_term = gp_signals.FourierBasisGP(spectrum=pl, Tspan=tspan, name='system_noise_' + \ str(self.sys_noise_count), selection=selections.Selection( \ self.__dict__[selection_function_name] ), components=nfreqs) if ii == 0: syn = syn_term elif ii > 0: syn += syn_term self.sys_noise_count += 1 return syn
def add_rn(self): """Return dictionary containing red noise power-law signal attributes :return: OrderedDict of red noise signal """ log10_A = parameter.Uniform(-20.0, -10.0) gamma = parameter.Uniform(0.02, 6.98) pl = utils.powerlaw(log10_A=log10_A, gamma=gamma) rn = gp_signals.FourierBasisGP(pl, components=self.nfreqcomps, name='rn') newsignal = OrderedDict({ 'type': 'rn', 'name': [self.pname + '_rn_log10_A', self.pname + '_rn_gamma'], 'pmin': [-20.0, 0.02], 'pmax': [-10.0, 6.98], 'pstart': [-14.5, 3.51], 'interval': [True, True], 'numpars': 2 }) self.rn_sig = rn(self.psr) return {'rn': newsignal}
def test_pta_phiinv_methods(self): ef = white_signals.MeasurementNoise(efac=parameter.Uniform(0.1, 5)) span = np.max(self.psrs[0].toas) - np.min(self.psrs[0].toas) pl = utils.powerlaw(log10_A=parameter.Uniform(-16,-13), gamma=parameter.Uniform(1,7)) orf = utils.hd_orf() vrf = utils.dipole_orf() rn = gp_signals.FourierBasisGP(spectrum=pl, components=30, Tspan=span) hdrn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=orf, components=20, Tspan=span, name='gw') vrn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=vrf, components=20, Tspan=span, name='vec') vrn2 = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=vrf, components=20, Tspan=span*1.234, name='vec2') # two common processes, sharing basis partially model = ef + rn + hdrn # + vrn pta = signal_base.PTA([model(psr) for psr in self.psrs]) ps = {p.name: float(p.sample()) for p in pta.params} phi = pta.get_phi(ps) ldp = np.linalg.slogdet(phi)[1] inv1, ld1 = pta.get_phiinv(ps,method='cliques', logdet=True) inv2, ld2 = pta.get_phiinv(ps,method='partition', logdet=True) inv3, ld3 = pta.get_phiinv(ps,method='sparse', logdet=True) inv3 = inv3.toarray() for ld in [ld1, ld2, ld3]: msg = "Wrong phi log determinant for two common processes" assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg for inv in [inv1,inv2,inv3]: msg = "Wrong phi inverse for two common processes" assert np.allclose(np.dot(phi, inv), np.eye(phi.shape[0]), rtol=1e-15, atol=1e-6), msg for inva, invb in itertools.combinations([inv1,inv2,inv3],2): assert np.allclose(inva,invb) # two common processes, no sharing basis model = ef + rn + vrn2 pta = signal_base.PTA([model(psr) for psr in self.psrs]) ps = {p.name: float(p.sample()) for p in pta.params} phi = pta.get_phi(ps) ldp = np.linalg.slogdet(phi)[1] inv1, ld1 = pta.get_phiinv(ps,method='cliques', logdet=True) inv2, ld2 = pta.get_phiinv(ps,method='partition', logdet=True) inv3, ld3 = pta.get_phiinv(ps,method='sparse', logdet=True) inv3 = inv3.toarray() for ld in [ld1, ld2, ld3]: msg = "Wrong phi log determinant for two common processes" assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg for inv in [inv1,inv2,inv3]: msg = "Wrong phi inverse for two processes" assert np.allclose(np.dot(phi, inv), np.eye(phi.shape[0]), rtol=1e-15, atol=1e-6), msg for inva, invb in itertools.combinations([inv1,inv2,inv3],2): assert np.allclose(inva,invb) # three common processes, sharing basis partially model = ef + rn + hdrn + vrn pta = signal_base.PTA([model(psr) for psr in self.psrs]) ps = {p.name: float(p.sample()) for p in pta.params} phi = pta.get_phi(ps) ldp = np.linalg.slogdet(phi)[1] inv1, ld1 = pta.get_phiinv(ps,method='cliques', logdet=True) inv2, ld2 = pta.get_phiinv(ps,method='partition', logdet=True) inv3, ld3 = pta.get_phiinv(ps,method='sparse', logdet=True) inv3 = inv3.toarray() for ld in [ld1, ld3]: msg = "Wrong phi log determinant for two common processes" assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg for inv in [inv1,inv3]: msg = "Wrong phi inverse for three common processes" assert np.allclose(np.dot(phi, inv), np.eye(phi.shape[0]), rtol=1e-15, atol=1e-6), msg for inva, invb in itertools.combinations([inv1,inv3],2): assert np.allclose(inva,invb) # four common processes, three sharing basis partially model = ef + rn + hdrn + vrn + vrn2 pta = signal_base.PTA([model(psr) for psr in self.psrs]) ps = {p.name: float(p.sample()) for p in pta.params} phi = pta.get_phi(ps) ldp = np.linalg.slogdet(phi)[1] inv1, ld1 = pta.get_phiinv(ps,method='cliques', logdet=True) inv2, ld2 = pta.get_phiinv(ps,method='partition', logdet=True) inv3, ld3 = pta.get_phiinv(ps,method='sparse', logdet=True) inv3 = inv3.toarray() for ld in [ld1, ld3]: msg = "Wrong phi log determinant for two common processes" assert np.allclose(ldp, ld, rtol=1e-15, atol=1e-6), msg for inv in [inv1, inv3]: msg = "Wrong phi inverse for four processes" assert np.allclose(np.dot(phi, inv), np.eye(phi.shape[0]), rtol=1e-15, atol=1e-6), msg for inva, invb in itertools.combinations([inv1, inv3],2): assert np.allclose(inva, invb)
def test_red_noise_add_backend(self): """Test that red noise with backend addition only returns independent columns.""" # set up signals pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) selection = Selection(selections.by_backend) cpl = utils.powerlaw( log10_A=parameter.Uniform(-18, -12)("log10_Agw"), gamma=parameter.Uniform(1, 7)("gamma_gw") ) # parameters log10_As = [-14, -14.4, -15, -14.8] gammas = [2.3, 4.4, 1.8, 5.6] log10_Ac, gammac = -15.5, 1.33 params = { "B1855+09_red_noise_430_ASP_gamma": gammas[0], "B1855+09_red_noise_430_PUPPI_gamma": gammas[1], "B1855+09_red_noise_L-wide_ASP_gamma": gammas[2], "B1855+09_red_noise_L-wide_PUPPI_gamma": gammas[3], "B1855+09_red_noise_430_ASP_log10_A": log10_As[0], "B1855+09_red_noise_430_PUPPI_log10_A": log10_As[1], "B1855+09_red_noise_L-wide_ASP_log10_A": log10_As[2], "B1855+09_red_noise_L-wide_PUPPI_log10_A": log10_As[3], "log10_Agw": log10_Ac, "gamma_gw": gammac, } Tmax = self.psr.toas.max() - self.psr.toas.min() tpars = [ (30, 20, Tmax, Tmax), (20, 30, Tmax, Tmax), (30, 30, Tmax, Tmax), (30, 20, Tmax, 1.123 * Tmax), (20, 30, Tmax, 1.123 * Tmax), (30, 30, 1.123 * Tmax, Tmax), (30, 20, None, Tmax), ] for (nf1, nf2, T1, T2) in tpars: rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1, selection=selection) crn = gp_signals.FourierBasisGP(spectrum=cpl, components=nf2, Tspan=T2) s = rn + crn rnm = s(self.psr) # get the basis bflags = self.psr.backend_flags Fmats, fs, phis = [], [], [] F2, f2 = utils.createfourierdesignmatrix_red(self.psr.toas, nf2, Tspan=T2) p2 = utils.powerlaw(f2, log10_Ac, gammac) for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag F1, f1 = utils.createfourierdesignmatrix_red(self.psr.toas[mask], nf1, Tspan=T1) Fmats.append(F1) fs.append(f1) phis.append(utils.powerlaw(f1, log10_As[ct], gammas[ct])) Fmats.append(F2) phis.append(p2) nf = sum(F.shape[1] for F in Fmats) F = np.zeros((len(self.psr.toas), nf)) phi = np.hstack([p for p in phis]) nftot = 0 for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag nn = Fmats[ct].shape[1] F[mask, nftot : nn + nftot] = Fmats[ct] nftot += nn F[:, -2 * nf2 :] = F2 msg = "Combined red noise PSD incorrect " msg += "for {} {} {} {}".format(nf1, nf2, T1, T2) assert np.all(rnm.get_phi(params) == phi), msg msg = "Combined red noise PSD inverse incorrect " msg += "for {} {} {} {}".format(nf1, nf2, T1, T2) assert np.all(rnm.get_phiinv(params) == 1 / phi), msg msg = "Combined red noise Fmat incorrect " msg += "for {} {} {} {}".format(nf1, nf2, T1, T2) assert np.allclose(F, rnm.get_basis(params)), msg
def test_red_noise_add(self): """Test that red noise addition only returns independent columns.""" # set up signals pl = utils.powerlaw(log10_A=parameter.Uniform(-18, -12), gamma=parameter.Uniform(1, 7)) cpl = utils.powerlaw( log10_A=parameter.Uniform(-18, -12)("log10_Agw"), gamma=parameter.Uniform(1, 7)("gamma_gw") ) # parameters log10_A, gamma = -14.5, 4.33 log10_Ac, gammac = -15.5, 1.33 params = { "B1855+09_red_noise_log10_A": log10_A, "B1855+09_red_noise_gamma": gamma, "log10_Agw": log10_Ac, "gamma_gw": gammac, } Tmax = self.psr.toas.max() - self.psr.toas.min() tpars = [ (30, 20, Tmax, Tmax), (20, 30, Tmax, Tmax), (30, 30, Tmax, Tmax), (30, 20, Tmax, 1.123 * Tmax), (20, 30, Tmax, 1.123 * Tmax), (30, 30, 1.123 * Tmax, Tmax), ] for (nf1, nf2, T1, T2) in tpars: rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1) crn = gp_signals.FourierBasisGP(spectrum=cpl, components=nf2, Tspan=T2) s = rn + crn rnm = s(self.psr) # set up frequencies F1, f1 = utils.createfourierdesignmatrix_red(self.psr.toas, nmodes=nf1, Tspan=T1) F2, f2 = utils.createfourierdesignmatrix_red(self.psr.toas, nmodes=nf2, Tspan=T2) # test power spectrum p1 = utils.powerlaw(f1, log10_A, gamma) p2 = utils.powerlaw(f2, log10_Ac, gammac) if T1 == T2: nf = max(2 * nf1, 2 * nf2) phi = np.zeros(nf) F = F1 if nf1 > nf2 else F2 phi[: 2 * nf1] = p1 phi[: 2 * nf2] += p2 F[ :, ] # noqa: E231 else: phi = np.concatenate((p1, p2)) F = np.hstack((F1, F2)) msg = "Combined red noise PSD incorrect " msg += "for {} {} {} {}".format(nf1, nf2, T1, T2) assert np.all(rnm.get_phi(params) == phi), msg msg = "Combined red noise PSD inverse incorrect " msg += "for {} {} {} {}".format(nf1, nf2, T1, T2) assert np.all(rnm.get_phiinv(params) == 1 / phi), msg msg = "Combined red noise Fmat incorrect " msg += "for {} {} {} {}".format(nf1, nf2, T1, T2) assert np.allclose(F, rnm.get_basis(params)), msg
def test_pta_phi(self): T1, T2, T3 = 3.16e8, 3.16e8, 3.16e8 nf1, nf2, nf3 = 2, 2, 1 pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(1,7)) orf = utils.hd_orf() rn = gp_signals.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1) crn = gp_signals.FourierBasisCommonGP(spectrum=pl, orf=orf, components=1, name='gw', Tspan=T3) model = rn + crn pta = model(self.psrs[0]) + model(self.psrs[1]) lA1, gamma1 = -13, 1e-15 lA2, gamma2 = -13.3, 1e-15 lAc, gammac = -13.1, 1e-15 params = {'gw_log10_A': lAc, 'gw_gamma': gammac, 'B1855+09_log10_A': lA1, 'B1855+09_gamma': gamma1, 'J1909-3744_log10_A': lA2, 'J1909-3744_gamma': gamma2} phi = pta.get_phi(params) phiinv = pta.get_phiinv(params) T1, T2, T3 = 3.16e8, 3.16e8, 3.16e8 nf1, nf2, nf3 = 2, 2, 1 F1, f1 = utils.createfourierdesignmatrix_red( self.psrs[0].toas, nf1, Tspan=T1) F2, f2 = utils.createfourierdesignmatrix_red( self.psrs[1].toas, nf2, Tspan=T2) F1c, fc = utils.createfourierdesignmatrix_red( self.psrs[0].toas, nf3, Tspan=T3) F2c, fc = utils.createfourierdesignmatrix_red( self.psrs[1].toas, nf3, Tspan=T3) nftot = 2 * 2 * nf1 phidiag = np.zeros(nftot) phit = np.zeros((nftot, nftot)) phidiag[:4] = utils.powerlaw(f1, lA1, gamma1) phidiag[:2] += utils.powerlaw(fc, lAc, gammac) phidiag[4:] = utils.powerlaw(f2, lA2, gamma2) phidiag[4:6] += utils.powerlaw(fc, lAc, gammac) phit[np.diag_indices(nftot)] = phidiag phit[:2, 4:6] = np.diag(hd_powerlaw(fc, self.psrs[0].pos, self.psrs[1].pos, lAc, gammac)) phit[4:6, :2] = np.diag(hd_powerlaw(fc, self.psrs[0].pos, self.psrs[1].pos, lAc, gammac)) msg = '{} {}'.format(np.diag(phi), np.diag(phit)) assert np.allclose(phi, phit, rtol=1e-15, atol=1e-17), msg msg = 'PTA Phi inverse is incorrect {}.'.format(params) assert np.allclose(phiinv, np.linalg.inv(phit), rtol=1e-15, atol=1e-17), msg
def hd_powerlaw(f, pos1, pos2, log10_A=-15, gamma=4.3): return utils.powerlaw(f, log10_A, gamma) * utils.hd_orf(pos1, pos2)
log10_A_gw_2 = parameter.Uniform(-18, -13)('zlog10_A_other_gw') gamma_gw_2 = parameter.Constant(7 / 3)('zgamma_other_gw') ##### Set up signals ##### # timing model tm = gp_signals.TimingModel() # white noise ef = white_signals.MeasurementNoise(efac=efac, selection=selection) eq = white_signals.EquadNoise(log10_equad=log10_equad, selection=selection) ec = white_signals.EcorrKernelNoise(log10_ecorr=log10_ecorr, selection=selection) # red noise (powerlaw with 30 frequencies) pl = utils.powerlaw(log10_A=red_noise_log10_A, gamma=red_noise_gamma) rn = gp_signals.FourierBasisGP(spectrum=pl, components=30, Tspan=Tspan) cpl_1 = utils.powerlaw(log10_A=log10_A_gw_1, gamma=gamma_gw_1) cpl_2 = utils.powerlaw(log10_A=log10_A_gw_2, gamma=gamma_gw_2) #Common red noise process with no correlations crn_1 = gp_signals.FourierBasisGP(spectrum=cpl_1, components=30, Tspan=Tspan, name='gw') crn_2 = gp_signals.FourierBasisGP(spectrum=cpl_2, components=30, Tspan=Tspan, name='other_gw')
def test_red_noise_add_backend(self): """Test that red noise with backend addition only returns independent columns.""" # set up signals pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(1,7)) selection = Selection(selections.by_backend) cpl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12)('log10_Agw'), gamma=parameter.Uniform(1,7)('gamma_gw')) # parameters log10_As = [-14, -14.4, -15, -14.8] gammas = [2.3, 4.4, 1.8, 5.6] log10_Ac, gammac = -15.5, 1.33 params = {'B1855+09_430_ASP_gamma': gammas[0], 'B1855+09_430_PUPPI_gamma': gammas[1], 'B1855+09_L-wide_ASP_gamma': gammas[2], 'B1855+09_L-wide_PUPPI_gamma': gammas[3], 'B1855+09_430_ASP_log10_A': log10_As[0], 'B1855+09_430_PUPPI_log10_A': log10_As[1], 'B1855+09_L-wide_ASP_log10_A': log10_As[2], 'B1855+09_L-wide_PUPPI_log10_A': log10_As[3], 'log10_Agw': log10_Ac, 'gamma_gw': gammac} Tmax = self.psr.toas.max() - self.psr.toas.min() tpars = [(30, 20, Tmax, Tmax), (20, 30, Tmax, Tmax), (30, 30, Tmax, Tmax), (30, 20, Tmax, 1.123*Tmax), (20, 30, Tmax, 1.123*Tmax), (30, 30, 1.123*Tmax, Tmax), (30, 20, None, Tmax)] for (nf1, nf2, T1, T2) in tpars: rn = gs.FourierBasisGP(spectrum=pl, components=nf1, Tspan=T1, selection=selection) crn = gs.FourierBasisGP(spectrum=cpl, components=nf2, Tspan=T2) s = rn + crn rnm = s(self.psr) # get the basis bflags = self.psr.backend_flags Fmats, fs, phis = [], [], [] F2, f2 = utils.createfourierdesignmatrix_red( self.psr.toas, nf2, Tspan=T2) p2 = utils.powerlaw(f2, log10_Ac, gammac) for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag F1, f1 = utils.createfourierdesignmatrix_red( self.psr.toas[mask], nf1, Tspan=T1) Fmats.append(F1) fs.append(f1) phis.append(utils.powerlaw(f1, log10_As[ct], gammas[ct])) Fmats.append(F2) phis.append(p2) nf = sum(F.shape[1] for F in Fmats) F = np.zeros((len(self.psr.toas), nf)) phi = np.hstack(p for p in phis) nftot = 0 for ct, flag in enumerate(np.unique(bflags)): mask = bflags == flag nn = Fmats[ct].shape[1] F[mask, nftot:nn+nftot] = Fmats[ct] nftot += nn F[:, -2*nf2:] = F2 msg = 'Combined red noise PSD incorrect ' msg += 'for {} {} {} {}'.format(nf1, nf2, T1, T2) assert np.all(rnm.get_phi(params) == phi), msg msg = 'Combined red noise PSD inverse incorrect ' msg += 'for {} {} {} {}'.format(nf1, nf2, T1, T2) assert np.all(rnm.get_phiinv(params) == 1/phi), msg msg = 'Combined red noise Fmat incorrect ' msg += 'for {} {} {} {}'.format(nf1, nf2, T1, T2) assert np.allclose(F, rnm.get_basis(params)), msg
def test_combine_signals(self): """Test for combining different signals.""" # set up signal parameter ecorr = parameter.Uniform(-10, -5) ec = gs.EcorrBasisModel(log10_ecorr=ecorr) pl = utils.powerlaw(log10_A=parameter.Uniform(-18,-12), gamma=parameter.Uniform(1,7)) rn = gs.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 = gs.BasisGP(prior, basis, name='se') ts = gs.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_log10_ecorr': ecorr, 'B1855+09_log10_A': log10_A, 'B1855+09_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
def common_red_noise_block(psd='powerlaw', prior='log-uniform', Tspan=None, gamma_val=None, orf=None, name='gwb'): """ Returns common red noise model: 1. Red noise modeled with user defined PSD with 30 sampling frequencies. Available PSDs are ['powerlaw', 'turnover' 'spectrum'] :param psd: PSD to use for common red noise signal. Available options are ['powerlaw', 'turnover' 'spectrum'] :param prior: Prior on log10_A. Default if "log-uniform". Use "uniform" for upper limits. :param Tspan: Sets frequency sampling f_i = i / Tspan. Default will use overall time span for indivicual pulsar. :param gamma_val: Value of spectral index for power-law and turnover models. By default spectral index is varied of 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 name: Name of common red process """ orfs = { 'hd': utils.hd_orf(), 'dipole': utils.dipole_orf(), 'monopole': utils.monopole_orf() } # common red noise parameters if psd in ['powerlaw', 'turnover']: amp_name = '{}_log10_A'.format(name) if prior == 'uniform': log10_Agw = parameter.LinearExp(-18, -11)(amp_name) elif prior == 'log-uniform' and gamma_val is not None: if np.abs(gamma_val - 4.33) < 0.1: log10_Agw = parameter.Uniform(-18, -14)(amp_name) else: log10_Agw = parameter.Uniform(-18, -11)(amp_name) else: log10_Agw = parameter.Uniform(-18, -11)(amp_name) gam_name = '{}_gamma'.format(name) if gamma_val is not None: gamma_gw = parameter.Constant(gamma_val)(gam_name) else: gamma_gw = parameter.Uniform(0, 7)(gam_name) # common red noise PSD if psd == 'powerlaw': cpl = utils.powerlaw(log10_A=log10_Agw, gamma=gamma_gw) elif psd == 'turnover': kappa_name = '{}_kappa'.format(name) lf0_name = '{}_log10_fbend'.format(name) kappa_gw = parameter.Uniform(0, 7)(kappa_name) lf0_gw = parameter.Uniform(-9, -7)(lf0_name) cpl = utils.turnover(log10_A=log10_Agw, gamma=gamma_gw, lf0=lf0_gw, kappa=kappa_gw) if orf is None: crn = gp_signals.FourierBasisGP(cpl, components=30, Tspan=Tspan) elif orf in orfs.keys(): crn = gp_signals.FourierBasisCommonGP(cpl, orfs[orf], components=30, Tspan=Tspan) else: raise ValueError('ORF {} not recognized'.format(orf)) return crn
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
for p, t in zip(parfiles, timfiles): psr = Pulsar(p, t) psrs.append(psr) save1 = np.load('noisepars.npy') save2 = np.load('noisepardict.npy') save3 = np.load('dpdmpars-maxposprob.npy') save4 = np.load('dpdmpardict.npy') Dict = {save2[i]: save1[i] for i in range(len(save2))} Dict.update({save4[i]: save3[i] for i in range(len(save4))}) # The Big Model # dm noise log10_A_dm = parameter.Constant() gamma_dm = parameter.Constant() pl_dm = utils.powerlaw(log10_A=log10_A_dm, gamma=gamma_dm) 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')
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['{}_log10_A'.format(pname)]) gamma.append(params['{}_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