def white_noise_block(vary=False): """ Returns the white noise block of the model: 1. EFAC per backend/receiver system 2. EQUAD per backend/receiver system 3. ECORR per backend/receiver system :param vary: If set to true we vary these parameters with uniform priors. Otherwise they are set to constants with values to be set later. """ # define selection by observing backend selection = selections.Selection(selections.by_backend) # white noise parameters if vary: efac = parameter.Uniform(0.01, 10.0) equad = parameter.Uniform(-8.5, -5) ecorr = parameter.Uniform(-8.5, -5) else: efac = parameter.Constant() equad = parameter.Constant() ecorr = parameter.Constant() # white noise signals 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) # combine signals s = ef + eq + ec return s
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 ecorr(self,option="by_backend"): """ Similar to EFAC and EQUAD, ECORR is a white noise parameter that describes a correlation between ToAs in a single epoch (observation). Arzoumanian, Zaven, et al. The Astrophysical Journal 859.1 (2018): 47. """ if option not in selections.__dict__.keys(): raise ValueError('ECORR option must be Enterprise selection function \ name') se=selections.Selection(selections.__dict__[option]) ecorrpr = interpret_white_noise_prior(self.params.ecorr) ecs = white_signals.EcorrKernelNoise(log10_ecorr=ecorrpr,selection=se) return ecs
log10_A_gw_1 = parameter.Uniform(-18, -13)('zlog10_A_gw') gamma_gw_1 = parameter.Constant(13 / 3)('zgamma_gw') # Second GW parameters 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,
def white_noise_block(vary=False, inc_ecorr=False, gp_ecorr=False, efac1=False, select='backend', name=None): """ Returns the white noise block of the model: 1. EFAC per backend/receiver system 2. EQUAD per backend/receiver system 3. ECORR per backend/receiver system :param vary: If set to true we vary these parameters with uniform priors. Otherwise they are set to constants with values to be set later. :param inc_ecorr: include ECORR, needed for NANOGrav channelized TOAs :param gp_ecorr: whether to use the Gaussian process model for ECORR :param efac1: use a strong prior on EFAC = Normal(mu=1, stdev=0.1) """ if select == 'backend': # define selection by observing backend backend = selections.Selection(selections.by_backend) # define selection by nanograv backends backend_ng = selections.Selection(selections.nanograv_backends) else: # define no selection backend = selections.Selection(selections.no_selection) # white noise parameters if vary: if efac1: efac = parameter.Normal(1.0, 0.1) else: efac = parameter.Uniform(0.01, 10.0) equad = parameter.Uniform(-8.5, -5) if inc_ecorr: ecorr = parameter.Uniform(-8.5, -5) else: efac = parameter.Constant() equad = parameter.Constant() if inc_ecorr: ecorr = parameter.Constant() # white noise signals ef = white_signals.MeasurementNoise(efac=efac, selection=backend, name=name) eq = white_signals.EquadNoise(log10_equad=equad, selection=backend, name=name) if inc_ecorr: if gp_ecorr: if name is None: ec = gp_signals.EcorrBasisModel(log10_ecorr=ecorr, selection=backend_ng) else: ec = gp_signals.EcorrBasisModel(log10_ecorr=ecorr, selection=backend_ng, name=name) else: ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr, selection=backend_ng, name=name) # combine signals if inc_ecorr: s = ef + eq + ec elif not inc_ecorr: s = ef + eq return s
def test_single_pulsar(self): # get parameters from PAL2 style noise files params = get_noise_from_pal2(datadir + "/B1855+09_noise.txt") # setup basic model efac = parameter.Constant() equad = parameter.Constant() ecorr = parameter.Constant() log10_A = parameter.Constant() gamma = parameter.Constant() selection = Selection(selections.by_backend) ms = white_signals.MeasurementNoise(efac=efac, log10_t2equad=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) s = ms + ec + rn m = s(self.psrs[0]) # set parameters m.set_default_params(params) # get parameters efacs = [params[key] for key in sorted(params.keys()) if "efac" in key] equads = [ params[key] for key in sorted(params.keys()) if "equad" in key ] ecorrs = [ params[key] for key in sorted(params.keys()) if "ecorr" in key ] log10_A = params["B1855+09_red_noise_log10_A"] gamma = params["B1855+09_red_noise_gamma"] # correct value flags = ["430_ASP", "430_PUPPI", "L-wide_ASP", "L-wide_PUPPI"] nvec0 = np.zeros_like(self.psrs[0].toas) for ct, flag in enumerate(np.unique(flags)): ind = flag == self.psrs[0].backend_flags nvec0[ind] = efacs[ct]**2 * ( self.psrs[0].toaerrs[ind]**2 + 10**(2 * equads[ct]) * np.ones(np.sum(ind))) # get the basis bflags = self.psrs[0].backend_flags Umats = [] for flag in np.unique(bflags): mask = bflags == flag Umats.append( utils.create_quantization_matrix(self.psrs[0].toas[mask])[0]) nepoch = sum(U.shape[1] for U in Umats) U = np.zeros((len(self.psrs[0].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 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]))) # test msg = "EFAC/ECORR logdet incorrect." N = m.get_ndiag(params) assert np.allclose(N.solve(self.psrs[0].residuals, logdet=True)[1], logdet, rtol=1e-10), msg msg = "EFAC/ECORR D1 solve incorrect." assert np.allclose(N.solve(self.psrs[0].residuals), sl.cho_solve(cf, self.psrs[0].residuals), rtol=1e-10), msg msg = "EFAC/ECORR 1D1 solve incorrect." assert np.allclose( N.solve(self.psrs[0].residuals, left_array=self.psrs[0].residuals), np.dot(self.psrs[0].residuals, sl.cho_solve(cf, self.psrs[0].residuals)), rtol=1e-10, ), msg msg = "EFAC/ECORR 2D1 solve incorrect." T = m.get_basis(params) assert np.allclose( N.solve(self.psrs[0].residuals, left_array=T), np.dot(T.T, sl.cho_solve(cf, self.psrs[0].residuals)), rtol=1e-10, ), msg msg = "EFAC/ECORR 2D2 solve incorrect." assert np.allclose(N.solve(T, left_array=T), np.dot(T.T, sl.cho_solve(cf, T)), rtol=1e-10), msg F, f2 = utils.createfourierdesignmatrix_red(self.psrs[0].toas, nmodes=20) # spectrum test phi = utils.powerlaw(f2, log10_A=log10_A, gamma=gamma) 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
def test_pta(self): # 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) # setup basic model efac = parameter.Constant() equad = parameter.Constant() ecorr = parameter.Constant() log10_A = parameter.Constant() gamma = parameter.Constant() selection = Selection(selections.by_backend) ms = white_signals.MeasurementNoise(efac=efac, log10_t2equad=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) s = ms + ec + rn pta = s(self.psrs[0]) + s(self.psrs[1]) # set parameters pta.set_default_params(params) # get parameters efacs, equads, ecorrs, log10_A, gamma = [], [], [], [], [] for pname in [p.name for p in self.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)]) # correct value tflags = [sorted(list(np.unique(p.backend_flags))) for p in self.psrs] cfs, logdets, phis = [], [], [] for ii, (psr, flags) in enumerate(zip(self.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 + 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) phi = utils.powerlaw(f2, log10_A=log10_A[ii], gamma=gamma[ii]) phis.append(phi) # tests Ns = pta.get_ndiag(params) pphis = pta.get_phi(params) pphiinvs = pta.get_phiinv(params) Ts = pta.get_basis(params) zipped = zip(logdets, cfs, phis, self.psrs, Ns, pphis, pphiinvs, Ts) for logdet, cf, phi, psr, N, pphi, pphiinv, T in zipped: msg = "EFAC/ECORR logdet incorrect." assert np.allclose(N.solve(psr.residuals, logdet=True)[1], logdet, rtol=1e-10), msg msg = "EFAC/ECORR D1 solve incorrect." assert np.allclose(N.solve(psr.residuals), sl.cho_solve(cf, psr.residuals), rtol=1e-10), msg msg = "EFAC/ECORR 1D1 solve incorrect." assert np.allclose( N.solve(psr.residuals, left_array=psr.residuals), np.dot(psr.residuals, sl.cho_solve(cf, psr.residuals)), rtol=1e-10, ), msg msg = "EFAC/ECORR 2D1 solve incorrect." assert np.allclose(N.solve(psr.residuals, left_array=T), np.dot(T.T, sl.cho_solve(cf, psr.residuals)), rtol=1e-10), msg msg = "EFAC/ECORR 2D2 solve incorrect." assert np.allclose(N.solve(T, left_array=T), np.dot(T.T, sl.cho_solve(cf, T)), rtol=1e-10), msg # spectrum test msg = "Spectrum incorrect for GP Fourier signal." assert np.all(pphi == phi), msg # inverse spectrum test msg = "Spectrum inverse incorrect for GP Fourier signal." assert np.all(pphiinv == 1 / phi), msg
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
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 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
rn_gamma = parameter.Uniform(0, 7) rn_pl = utils.powerlaw(log10_A=rn_log10_A, gamma=rn_gamma) # GWB parameters and powerlaw orf = utils.hd_orf() if args.ul: gwb_log10_A = parameter.LinearExp(-18, -12)('gwb_log10_A') else: gwb_log10_A = parameter.Uniform(-18, -12)('gwb_log10_A') gwb_gamma = parameter.Constant(13 / 3)('gwb_gamma') gwb_pl = utils.powerlaw(log10_A=gwb_log10_A, gamma=gwb_gamma) # signals ef = white_signals.MeasurementNoise(efac=efac, selection=bkend) eq = white_signals.EquadNoise(log10_equad=equad, selection=bkend) ec = white_signals.EcorrKernelNoise(log10_ecorr=ecorr, selection=bkend_NG) dmgp = gp_signals.BasisGP(dm_pl, dm_basis, name='dm_gp') dmexp = models.dm_exponential_dip(tmin=54500, tmax=55000, name='dmexp_1') dm1yr = models.dm_annual_signal() rn = gp_signals.FourierBasisGP(spectrum=rn_pl, components=30, Tspan=Tspan) gwb = gp_signals.FourierBasisCommonGP(gwb_pl, orf, components=30, Tspan=Tspan, name='gw') tm = gp_signals.TimingModel(use_svd=True) be = deterministic_signals.PhysicalEphemerisSignal( # widen prior on jup orbit use_epoch_toas=True,