def test_fake_DMfit(): """ fit only for DM with fake TOAs compare the variance of that result against the uncertainties """ parfile = pint.config.examplefile("NGC6440E.par") timfile = pint.config.examplefile("NGC6440E.tim") m, t = get_model_and_toas(parfile, timfile) # pick only data for a DM fit t = t[-8:] m.RAJ.frozen = True m.DECJ.frozen = True m.F0.frozen = True m.F1.frozen = True f = GLSFitter(t, m) f.fit_toas() N = 30 DMs = np.zeros(N) * u.pc / u.cm**3 for iter in range(N): t_fake = pint.simulation.make_fake_toas(t, m, add_noise=True) f_fake = GLSFitter(t_fake, m) f_fake.fit_toas() DMs[iter] = f_fake.model.DM.quantity.astype(np.float64) assert np.isclose(DMs.std(), f.model.DM.uncertainty, rtol=0.5) assert np.abs(DMs.mean() - f.model.DM.quantity) < 5 * f.model.DM.uncertainty
def calc_chi2(self, full_cov=False): """Return the weighted chi-squared for the model and toas. If the errors on the TOAs are independent this is a straightforward calculation, but if the noise model introduces correlated errors then obtaining a meaningful chi-squared value requires a Cholesky decomposition. This is carried out, here, by constructing a GLSFitter and asking it to do the chi-squared computation but not a fit. The return value here is available as self.chi2, which will not redo the computation unless necessary. The chi-squared value calculated here is suitable for use in downhill minimization algorithms and Bayesian approaches. Handling of problematic results - degenerate conditions explored by a minimizer for example - may need to be checked to confirm that they correctly return infinity. """ if self.model.has_correlated_errors: # Use GLS but don't actually fit from pint.fitter import GLSFitter f = GLSFitter(self.toas, self.model, residuals=self) try: return f.fit_toas(maxiter=0, full_cov=full_cov) except LinAlgError as e: log.warning( "Degenerate conditions encountered when " "computing chi-squared: %s" % (e,) ) return np.inf else: # Residual units are in seconds. Error units are in microseconds. if (self.toas.get_errors() == 0.0).any(): return np.inf else: # The self.time_resids is in the unit of "s", the error "us". # This is more correct way, but it is the slowest. # return (((self.time_resids / self.toas.get_errors()).decompose()**2.0).sum()).value # This method is faster then the method above but not the most correct way # return ((self.time_resids.to(u.s) / self.toas.get_errors().to(u.s)).value**2.0).sum() # This the fastest way, but highly depend on the assumption of time_resids and # error units. return ( (self.time_resids / self.toas.get_errors().to(u.s)) ** 2.0 ).sum()
def test_residuals_gls_chi2(): model = get_model( StringIO(""" PSRJ J1234+5678 ELAT 0 ELONG 0 DM 10 F0 1 PEPOCH 58000 ECORR mjd 57000 58000 2 """)) toas = make_fake_toas(57000, 59000, 20, model=model, error=1 * u.us) np.random.seed(0) toas.adjust_TOAs(TimeDelta(np.random.randn(len(toas)) * u.us)) r = Residuals(toas, model) f = GLSFitter(toas, model) assert f.fit_toas() == r.chi2
def test_fake_from_timfile(): m, t = get_model_and_toas( pint.config.examplefile("B1855+09_NANOGrav_9yv1.gls.par"), pint.config.examplefile("B1855+09_NANOGrav_9yv1.tim"), ) # refit the data to get rid of a trend f = GLSFitter(t, m) f.fit_toas() r = pint.residuals.Residuals(t, f.model) t_sim = pint.simulation.make_fake_toas(t, f.model, add_noise=True) r_sim = pint.residuals.Residuals(t_sim, f.model) # need a generous rtol because of the small statistics assert np.isclose(r.calc_time_resids().std(), r_sim.calc_time_resids().std(), rtol=2)
def setUpClass(self): self.par = 'B1855+09_NANOGrav_9yv1.gls.par' self.tim = 'B1855+09_NANOGrav_9yv1.tim' self.m = mb.get_model(self.par) self.t = toa.get_TOAs(self.tim, ephem='DE436') self.f = GLSFitter(self.t, self.m) # get tempo2 parameter dict with open('B1855+09_tempo2_gls_pars.json', 'r') as fp: self.t2d = json.load(fp)
def test_gls_chi2_reasonable(full_cov): model = get_model( StringIO(""" PSRJ J1234+5678 ELAT 0 ELONG 0 DM 10 F0 1 PEPOCH 58000 TNRedAmp -14.227505410948254 TNRedGam 4.91353 TNRedC 45 """)) toas = make_fake_toas(57000, 59000, 40, model=model, error=1 * u.us) np.random.seed(0) toas.adjust_TOAs(TimeDelta(np.random.randn(len(toas)) * u.us)) f = GLSFitter(toas, model) fit_chi2 = f.fit_toas(full_cov=full_cov) assert_allclose(fit_chi2, f.resids.calc_chi2(full_cov=full_cov))
def setUpClass(cls): os.chdir(datadir) cls.par = "B1855+09_NANOGrav_9yv1.gls.par" cls.tim = "B1855+09_NANOGrav_9yv1.tim" cls.m = mb.get_model(cls.par) cls.t = toa.get_TOAs(cls.tim, ephem="DE436") cls.f = GLSFitter(cls.t, cls.m) # get tempo2 parameter dict with open("B1855+09_tempo2_gls_pars.json", "r") as fp: cls.t2d = json.load(fp)
def test_gls_covmatrix(wls): gls = GLSFitter(wls.toas, wls.model_init) gls.fit_toas() assert np.isclose( wls.parameter_covariance_matrix.matrix, gls.parameter_covariance_matrix.matrix ).all() uncertainties = gls.model.get_params_dict("free", "uncertainty") for param in uncertainties: # uncertainty based on the diagonals of the covariance matrix matrix_uncertainty = np.sqrt( gls.parameter_covariance_matrix.get_label_matrix([param]).matrix[0, 0] ) if param in ["RAJ", "DECJ"]: # then uncertainties are in arcsec, need to convert factor = 3600 else: factor = 1 assert np.isclose(uncertainties[param] / factor, matrix_uncertainty)
def setUpClass(cls): os.chdir(datadir) cls.par = "B1855+09_NANOGrav_9yv1.gls.par" cls.tim = "B1855+09_NANOGrav_9yv1.tim" cls.m = mb.get_model(cls.par) cls.t = toa.get_TOAs(cls.tim, ephem="DE436") cls.f = GLSFitter(cls.t, cls.m) # get tempo2 parameter dict with open("B1855+09_tempo2_gls_pars.json", "r") as fp: cls.t2d = json.load(fp) # Get tempo whitened resids mjd, cls.twres = (np.genfromtxt( "B1855+09_NANOGrav_9yv1_whitened.tempo_test", unpack=True) * u.us)
def test_gls_chi2_behaviour(): model = get_model( StringIO(""" PSRJ J1234+5678 ELAT 0 ELONG 0 DM 10 F0 1 PEPOCH 58000 TNRedAmp -14.227505410948254 TNRedGam 4.91353 TNRedC 45 """)) model.free_params = ["F0", "ELAT", "ELONG"] toas = make_fake_toas(57000, 59000, 40, model=model, error=1 * u.us) np.random.seed(0) toas.adjust_TOAs(TimeDelta(np.random.randn(len(toas)) * u.us)) f = GLSFitter(toas, model) initial_chi2 = Residuals(toas, model).calc_chi2() fit_chi2 = f.fit_toas() assert fit_chi2 <= initial_chi2 assert f.resids.calc_chi2() <= initial_chi2 assert initial_chi2 == Residuals(toas, model).calc_chi2()
def setUpClass(cls): os.chdir(datadir) cls.par = "J0023+0923_NANOGrav_11yv0.gls.par" cls.tim = "J0023+0923_NANOGrav_11yv0.tim" cls.m = mb.get_model(cls.par) cls.t = toa.get_TOAs(cls.tim, ephem="DE436") cls.f = GLSFitter(cls.t, cls.m) # Get comparison resids and uncertainties mjd, freq, res, err, ophase, chi2, info = np.genfromtxt(cls.par + ".resavg", unpack=True) cls.resavg_mjd = mjd * u.d cls.resavg_freq = freq * u.MHz cls.resavg_res = res * u.us cls.resavg_err = err * u.us cls.resavg_chi2 = chi2
class TestGLS(unittest.TestCase): """Compare delays from the dd model with tempo and PINT""" @classmethod def setUpClass(self): self.par = 'B1855+09_NANOGrav_9yv1.gls.par' self.tim = 'B1855+09_NANOGrav_9yv1.tim' self.m = mb.get_model(self.par) self.t = toa.get_TOAs(self.tim, ephem='DE436') self.f = GLSFitter(self.t, self.m) # get tempo2 parameter dict with open('B1855+09_tempo2_gls_pars.json', 'r') as fp: self.t2d = json.load(fp) def fit(self, full_cov): self.f.reset_model() self.f.update_resids() self.f.fit_toas(full_cov=full_cov) def test_gls_fitter(self): for full_cov in [True, False]: self.fit(full_cov) for par, val in sorted(self.t2d.items()): if par not in ['F0']: v = (getattr(self.f.model, par).value if par not in [ 'ELONG', 'ELAT' ] else getattr(self.f.model, par).quantity.to(u.rad).value) e = (getattr(self.f.model, par).uncertainty.value if par not in ['ELONG', 'ELAT'] else getattr( self.f.model, par).uncertainty.to(u.rad).value) msg = 'Parameter {} does not match T2 for full_cov={}'.format( par, full_cov) assert np.abs(v - val[0]) <= val[1], msg assert np.abs(v - val[0]) <= e, msg assert np.abs(1 - val[1] / e) < 0.1, msg def test_gls_compare(self): self.fit(full_cov=False) chi21 = self.f.resids.chi2 self.fit(full_cov=True) chi22 = self.f.resids.chi2 assert np.allclose(chi21, chi22)
class TestGLS(unittest.TestCase): """Compare delays from the dd model with tempo and PINT""" @classmethod def setUpClass(self): self.par = 'B1855+09_NANOGrav_9yv1.gls.par' self.tim = 'B1855+09_NANOGrav_9yv1.tim' self.m = mb.get_model(self.par) self.t = toa.get_TOAs(self.tim, ephem='DE436') self.f = GLSFitter(self.t, self.m) # get tempo2 parameter dict with open('B1855+09_tempo2_gls_pars.json', 'r') as fp: self.t2d = json.load(fp) def fit(self, full_cov): self.f.reset_model() self.f.update_resids() self.f.fit_toas(full_cov=full_cov) def test_gls_fitter(self): for full_cov in [True, False]: self.fit(full_cov) for par, val in sorted(self.t2d.items()): if par not in ['F0']: v = (getattr(self.f.model, par).value if par not in ['ELONG', 'ELAT'] else getattr(self.f.model, par).quantity.to(u.rad).value) e = (getattr(self.f.model, par).uncertainty.value if par not in ['ELONG', 'ELAT'] else getattr(self.f.model, par).uncertainty.to(u.rad).value) msg = 'Parameter {} does not match T2 for full_cov={}'.format(par, full_cov) assert np.abs(v-val[0]) <= val[1], msg assert np.abs(v-val[0]) <= e, msg assert np.abs(1 - val[1]/e) < 0.1, msg def test_gls_compare(self): self.fit(full_cov=False) chi21 = self.f.resids.chi2 self.fit(full_cov=True) chi22 = self.f.resids.chi2 assert np.allclose(chi21, chi22)
def test_compare_gls(full_cov, wls): gls = GLSFitter(wls.toas, wls.model_init) gls.fit_toas(full_cov=full_cov) assert abs(wls.resids.chi2 - gls.resids.chi2) < 0.01