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_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 = parameter.sample(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) if not isinstance(inv3, np.ndarray): 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 = parameter.sample(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) if not isinstance(inv3, np.ndarray): 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 = parameter.sample(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) if not isinstance(inv3, np.ndarray): 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 = parameter.sample(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) if not isinstance(inv3, np.ndarray): 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_wideband(self): ms = white_signals.MeasurementNoise(selection=Selection(selections.by_backend)) dm = gp_signals.WidebandTimingModel( dmefac=parameter.Uniform(0.9, 1.1), dmefac_selection=Selection(selections.by_backend), dmjump=parameter.Normal(0, 1), dmjump_selection=Selection(selections.by_frontend), ) model = ms + dm pta = signal_base.PTA([model(self.psr)]) ps = parameter.sample(pta.params) pta.get_lnlikelihood(ps) dmtiming = pta.pulsarmodels[0].signals[1] msg = "DMEFAC masks do not cover the data." assert np.all(sum(dmtiming._dmefac_masks) == 1), msg msg = "DMJUMP masks do not cover the data." assert np.all(sum(dmtiming._dmjump_masks) == 1), msg # start with zero DMEFAC and DMJUMP p0 = {par.name: (1 if "dmefac" in par.name else 0) for par in dmtiming.params} pta.get_lnlikelihood(params=p0) phi0 = dmtiming.get_phi(params=p0) dl0 = dmtiming.get_delay(params=p0) dm_flags, dme_flags = np.array(self.psr.flags["pp_dm"], "d"), np.array(self.psr.flags["pp_dme"], "d") delays = np.zeros_like(self.psr.toas) check = 0 for index, par in enumerate(self.psr.fitpars): if "DMX" not in par: msg = "Problem with unbound timing parameters" assert phi0[index] == 1e40, msg else: dmx = self.psr.dmx[par] which = (dmx["DMXR1"] <= (self.psr.stoas / 86400)) & ((self.psr.stoas / 86400) < dmx["DMXR2"]) check += which avgdm = np.sum(dm_flags[which] / dme_flags[which] ** 2) / np.sum(1.0 / dme_flags[which] ** 2) vardm = 1.0 / np.sum(1.0 / dme_flags[which] ** 2) msg = "Priors do not match" assert np.allclose(vardm, phi0[index]), msg delays[which] = (avgdm - self.psr.dm - dmx["DMX"]) / (2.41e-4 * self.psr.freqs[which] ** 2) msg = "Not all TOAs are covered by DMX" assert np.all(check == 1) msg = "Delays do not match" assert np.allclose(dl0, delays), msg # sample DMEFACs randomly p1 = {par.name: (parameter.sample(par)[par.name] if "dmefac" in par.name else 0) for par in dmtiming.params} pta.get_lnlikelihood(params=p1) phi1 = dmtiming.get_phi(params=p1) dl1 = dmtiming.get_delay(params=p1) sel = Selection(selections.by_backend)(self.psr) msg = "Problem making selection" assert np.all(sum(m for m in sel.masks.values()) == 1), msg dme_flags_var = dme_flags.copy() for key, mask in sel.masks.items(): dmefac = p1["J1832-0836_" + key + "_dmefac"] dme_flags_var[mask] *= dmefac for index, par in enumerate(self.psr.fitpars): if "DMX" not in par: msg = "Problem with unbound timing parameters" assert phi1[index] == 1e40, msg else: dmx = self.psr.dmx[par] which = (dmx["DMXR1"] <= (self.psr.stoas / 86400)) & ((self.psr.stoas / 86400) < dmx["DMXR2"]) avgdm = np.sum(dm_flags[which] / dme_flags_var[which] ** 2) / np.sum(1.0 / dme_flags_var[which] ** 2) vardm = 1.0 / np.sum(1.0 / dme_flags_var[which] ** 2) msg = "Priors do not match" assert np.allclose(vardm, phi1[index]), msg delays[which] = (avgdm - self.psr.dm - dmx["DMX"]) / (2.41e-4 * self.psr.freqs[which] ** 2) msg = "Delays do not match" assert np.allclose(dl1, delays), msg