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_uniform(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 test_write(self): # change parameter value for p in self.modelB1855.params: par = getattr(self.modelB1855, p) # Change value for 20% if isinstance(par.value, numbers.Number): ov = par.value if isinstance(par, mp.MJDParameter): continue else: par.value = ov * 0.8 self.res = Residuals(self.toasB1855, self.modelB1855, use_weighted_mean=False).time_resids.to(u.s) f = open(self.out_parfile, "w") f.write(self.modelB1855.as_parfile()) f.close() read_model = mb.get_model(self.out_parfile) read_res = Residuals(self.toasB1855, read_model, use_weighted_mean=False).time_resids.to(u.s) assert np.all(np.abs(read_res.value - self.res.value) < 1e-15 ), "Output parfile did not produce same residuals." for pp in self.modelB1855.params: par_ori = getattr(self.modelB1855, pp) par_read = getattr(read_model, pp) if par_ori.uncertainty_value is not None: unc_diff = par_ori.uncertainty_value - par_read.uncertainty_value assert np.abs(unc_diff) < 1e-15, ( pp + "uncertainty does not keep the precision. at" + str(np.abs(unc_diff)))
def test_build_phase_residual(self): phase_res = Residuals(toas=self.toa, model=self.model) assert len(phase_res.phase_resids) == self.toa.ntoas # Test no mean subtraction phase_res_nomean = Residuals( toas=self.toa, model=self.model, residual_type="toa", subtract_mean=False, ) assert len(phase_res_nomean.resids) == self.toa.ntoas assert phase_res.resids.unit == phase_res.unit phase_res_noweight = Residuals( toas=self.toa, model=self.model, residual_type="toa", subtract_mean=True, use_weighted_mean=False, ) phase_res_no_f0_scale = Residuals(toas=self.toa, model=self.model, residual_type="toa", scaled_by_F0=False) assert phase_res_no_f0_scale.resids.unit == u.Unit("")
def test_pulse_number(): model = pint.models.get_model(parfile) toas = pint.toa.get_TOAs(timfile) # Make sure pn table column was added assert "pulse_number" in toas.table.colnames # Tracking pn should result in runaway residuals track_resids = Residuals(toas, model).time_resids assert np.amax(track_resids) >= 0.2 * u.second # Not tracking pn should keep residuals bounded getattr(model, "TRACK").value = "0" notrack_resids = Residuals(toas, model).time_resids assert np.amax(notrack_resids) < 0.2 * u.second # Make sure Exceptions are thrown when trying to track nonexistent pn del toas.table["pulse_number"] getattr(model, "TRACK").value = "-2" with pytest.raises(Exception): Residuals(toas, model) # Make sure pn can be added back by using the model assert toas.get_pulse_numbers() is None toas.compute_pulse_numbers(model) assert "pulse_number" in toas.table.colnames
def test_to_equatorial(self): # determine residuals with base (ecliptic) model pint_resids = Residuals(self.toasB1855, self.modelB1855, use_weighted_mean=False).time_resids.to(u.s) # convert model to ecliptic coordinates EQUmodelB1855 = model_ecliptic_to_equatorial(self.modelB1855) assert EQUmodelB1855 is not None, "Creation of equatorial model failed" assert ( "AstrometryEquatorial" in EQUmodelB1855.components), "Creation of equatorial model failed" assert not ("AstrometryEcliptic" in EQUmodelB1855.components ), "Ecliptic model still present" self.log.debug("Equatorial model created") # determine residuals with new (equatorial) model EQUpint_resids = Residuals(self.toasB1855, EQUmodelB1855, use_weighted_mean=False).time_resids.to(u.s) self.log.debug(np.abs(pint_resids - EQUpint_resids)) msg = ( "Residual comparison to ecliptic model failed with max relative difference %e s" % np.nanmax(np.abs(pint_resids - EQUpint_resids)).value) assert np.all(np.abs(pint_resids - EQUpint_resids) < 1e-10 * u.s), msg
def __init__(self, parfile=None, timfile=None, ephem=None, fitter="GLSFitter"): super(Pulsar, self).__init__() log.info(f"Loading pulsar parfile: {str(parfile)}") if parfile is None or timfile is None: raise ValueError("No valid pulsar model and/or TOAs to load") self.parfile = parfile self.timfile = timfile self.prefit_model = pint.models.get_model(self.parfile) if ephem is not None: log.info( f"Overriding model ephemeris {self.prefit_model.EPHEM.value} with {ephem}" ) self.prefit_model.EPHEM.value = ephem self.all_toas = get_TOAs(self.timfile, model=self.prefit_model, usepickle=True) # Make sure that if we used a model, that any phase jumps from # the parfile have their flags updated in the TOA table if "PhaseJump" in self.prefit_model.components: self.prefit_model.jump_params_to_flags(self.all_toas) # turns pre-existing jump flags in toas.table['flags'] into parameters in parfile self.prefit_model.jump_flags_to_params(self.all_toas) self.selected_toas = copy.deepcopy(self.all_toas) print("The prefit model as a parfile:") print(self.prefit_model.as_parfile()) # adds extra prefix params for fitting self.add_model_params() self.all_toas.print_summary() self.prefit_resids = Residuals(self.all_toas, self.prefit_model) self.selected_prefit_resids = self.prefit_resids print( "RMS pre-fit PINT residuals are %.3f us\n" % self.prefit_resids.rms_weighted().to(u.us).value ) # Set of indices from original list that are deleted # We use indices because of the grouping of TOAs by observatory self.deleted = set([]) if fitter == "auto": self.fit_method = self.getDefaultFitter(downhill=False) log.info( f"Since wideband={self.all_toas.wideband} and correlated={self.prefit_model.has_correlated_errors}, selecting fitter={self.fit_method}" ) elif fitter == "downhill": self.fit_method = self.getDefaultFitter(downhill=True) log.info( f"Since wideband={self.all_toas.wideband} and correlated={self.prefit_model.has_correlated_errors}, selecting Downhill fitter={self.fit_method}" ) else: self.fit_method = fitter self.fitter = None self.fitted = False self.stashed = None # for temporarily stashing some TOAs self.faketoas1 = None # for random models self.faketoas = None # for random models self.use_pulse_numbers = False
def test_combined_residuals(self): phase_res = Residuals(toas=self.toa, model=self.model) dm_res = Residuals(toas=self.toa, model=self.model, residual_type="dm") cb_residuals = CombinedResiduals([phase_res, dm_res]) cb_chi2 = cb_residuals.chi2 assert len(cb_residuals.resids) == 2 * self.toa.ntoas assert cb_residuals.unit == [u.s, u.pc / u.cm**3] assert cb_chi2 == phase_res.chi2 + dm_res.chi2
def update_resids(self): # update the pre and post fit residuals using all_toas track_mode = "use_pulse_numbers" if self.use_pulse_numbers else None self.prefit_resids = Residuals( self.all_toas, self.prefit_model, track_mode=track_mode ) if self.fitted: self.postfit_resids = Residuals( self.all_toas, self.postfit_model, track_mode=track_mode )
def formresiduals(self): """Form the residuals""" log.info("Computing residuals...") t0 = time.time() self.resids_us = Residuals(self.t, self.model).time_resids.to(u.us) time_phase = time.time() - t0 log.info("Computed phases and residuals in %.3f sec" % time_phase) # resids in (approximate) us: log.info("RMS PINT residuals are %.3f us" % self.resids_us.std().value)
def test_phase_commands(self): model = pint.models.get_model(parfile) toas = pint.toa.get_TOAs(timfile) # This TOA has PHASE -0.3. Check that assert np.isclose(toas.table[32]["flags"]["phase"], -0.3) # This TOA should have PHASE 0.2 and -padd -0.2 assert np.isclose(toas.table["flags"][9]["padd"], -0.2) assert np.isclose(toas.table["flags"][9]["phase"], 0.2) # The end result should be these residuals if the commands are respected res = Residuals(toas=toas, model=model) assert (res.rms_weighted() - 1602.0293 * u.us) < 0.1 * u.us
def __init__(self, toas, model, residuals=None): self.toas = toas self.model_init = model if residuals is None: self.resids_init = Residuals(toas=toas, model=model) self.reset_model() else: # residuals were provided, we're just going to use them # probably using GLSFitter to compute a chi-squared self.model = copy.deepcopy(self.model_init) self.resids = residuals self.fitresult = [] self.method = None
def test_residual_respects_pulse_numbers(model, fake_toas): t = fake_toas delta_f = (1 / (t.last_MJD - t.first_MJD)).to(u.Hz) m_2 = deepcopy(model) m_2.F0.quantity += 2 * delta_f # Check tracking does the right thing for residuals # and that we're wrapping as much as we think we are with pytest.raises(ValueError): Residuals(t, m_2, track_mode="capybara") r = Residuals(t, m_2, track_mode="nearest") assert np.amax(r.phase_resids) - np.amin(r.phase_resids) <= 1 r = Residuals(t, m_2, track_mode="use_pulse_numbers") assert np.amax(r.phase_resids) - np.amin(r.phase_resids) > 1.9
def test_J0023(self): pint_resids_us = Residuals( self.toasJ0023, self.modelJ0023, use_weighted_mean=False ).time_resids.to(u.s) assert np.all( np.abs(pint_resids_us.value - self.ltres) < 1e-8 ), "J0023 residuals test failed."
def test_B1855(self): pint_resids_us = Residuals( self.toasB1855, self.modelB1855, use_weighted_mean=False ).time_resids.to(u.s) assert np.all( np.abs(pint_resids_us.value - self.ltres) < 1e-7 ), "DD B1855 TEST FAILED"
def test_residuals_wideband_chi2(wideband_fake): toas, model = wideband_fake r = WidebandTOAResiduals(toas, model) rn = Residuals(toas, model) f = WidebandTOAFitter(toas, model) assert_allclose(f.fit_toas(), r.chi2) assert f.fit_toas() >= rn.chi2
def test_J0613(self): pint_resids_us = Residuals(self.toasJ0613, self.modelJ0613, False).time_resids.to(u.s) # Due to the gps2utc clock correction. We are at 3e-8 seconds level. assert np.all( np.abs(pint_resids_us.value - self.ltres) < 3e-8), "J0613 residuals test failed."
def test_B1953(self): pint_resids_us = Residuals( self.toasB1953, self.modelB1953, use_weighted_mean=False ).time_resids.to(u.s) # Due to the gps2utc clock correction. We are at 3e-8 seconds level. assert np.all( np.abs(pint_resids_us.value - self.ltres) < 3e-8 ), "B1953 residuals test failed."
def test_K96(self): log = logging.getLogger("TestJ1713 Switch of K96") self.modelJ1713.K96.value = False res = Residuals(self.toasJ1713, self.modelJ1713, False).time_resids.to(u.s) delay = self.modelJ1713.delay(self.toasJ1713) testp = tdu.get_derivative_params(self.modelJ1713) for p in testp.keys(): adf = self.modelJ1713.d_phase_d_param(self.toasJ1713, delay, p)
def test_J1713(self): log = logging.getLogger("TestJ1713.test_J1713") pint_resids_us = Residuals(self.toasJ1713, self.modelJ1713, False).time_resids.to(u.s) diff = pint_resids_us.value - self.ltres log.debug("Max diff %lf" % np.abs(diff - diff.mean()).max()) assert np.all( np.abs(diff - diff.mean()) < 5e-7), 'DDK J1713 TEST FAILED'
def test_residuals(self): model = mb.get_model(self.parfile) toas = toa.get_TOAs(self.tim, ephem="DE436", planets=False, include_bipm=True) r = Residuals(toas, model) assert np.all(np.abs(r.time_resids.to(u.us)) < 800 * u.us), \ "Residuals did not computed correctly for early CHIME data."
def test_J1853(self): pint_resids_us = Residuals(self.toasJ1853, self.modelJ1853, False).time_resids.to(u.s) # Due to PINT has higher order of ELL1 model, Tempo2 gives a difference around 3e-8 # Changed to 4e-8 since modification to get_PSR_freq() makes this 3.1e-8 log = logging.getLogger("TestJ1853.J1853_residuals") diffs = np.abs(pint_resids_us.value - self.ltres) log.debug("Diffs: %s\nMax: %s" % (diffs, np.max(diffs))) assert np.all(diffs < 4e-8), "J1853 residuals test failed."
def test_combined_residuals(self): phase_res = Residuals(toas=self.toa, model=self.model) dm_res = Residuals(toas=self.toa, model=self.model, residual_type="dm") cb_residuals = CombinedResiduals([phase_res, dm_res]) cb_chi2 = cb_residuals.chi2 assert len(cb_residuals._combined_resids) == 2 * self.toa.ntoas assert cb_residuals.unit["toa"] == u.s assert cb_residuals.unit["dm"] == u.pc / u.cm**3 assert cb_chi2 == phase_res.chi2 + dm_res.chi2 with pytest.raises(AttributeError): cb_residuals.dof with pytest.raises(AttributeError): cb_residuals.residual_objs["toa"].dof with pytest.raises(AttributeError): cb_residuals.residual_objs["dm"].dof with pytest.raises(AttributeError): cb_residuals.model
def test_residuals_scaled_uncertainties(): model = get_model( StringIO(""" PSRJ J1234+5678 ELAT 0 ELONG 0 DM 10 F0 1 PEPOCH 58000 EFAC mjd 57000 58000 2 """)) toas = make_fake_toas(57000, 59000, 20, model=model, error=1 * u.us) r = Residuals(toas, model) e = r.get_data_error(scaled=True) assert np.all(e != 0) assert 0 < np.sum(e > 1.5 * u.us) < len(toas) with pytest.raises(ValueError): model.as_parfile().index("EQUAD")
def __init__(self, parfile=None, timfile=None, ephem=None): super(Pulsar, self).__init__() log.info("STARTING LOADING OF PULSAR %s" % str(parfile)) if parfile is not None and timfile is not None: self.parfile = parfile self.timfile = timfile else: raise ValueError("No valid pulsar to load") self.prefit_model = pint.models.get_model(self.parfile) if ephem is not None: # TODO: EPHEM overwrite message? self.all_toas = get_TOAs(self.timfile, ephem=ephem, planets=True) self.prefit_model.EPHEM.value = ephem elif getattr(self.prefit_model, "EPHEM").value is not None: self.all_toas = get_TOAs( self.timfile, ephem=self.prefit_model.EPHEM.value, planets=True ) else: self.all_toas = get_TOAs(self.timfile, planets=True) # turns pre-existing jump flags in toas.table['flags'] into parameters in parfile # TODO: fix jump_flags_to_params self.prefit_model.jump_flags_to_params(self.all_toas) # adds flags to toas.table for existing jump parameters from .par file if "PhaseJump" in self.prefit_model.components: self.prefit_model.jump_params_to_flags(self.all_toas) self.selected_toas = copy.deepcopy(self.all_toas) print("prefit_model.as_parfile():") print(self.prefit_model.as_parfile()) self.all_toas.print_summary() self.prefit_resids = Residuals(self.selected_toas, self.prefit_model) print( "RMS PINT residuals are %.3f us\n" % self.prefit_resids.rms_weighted().to(u.us).value ) self.fitter = Fitters.WLS self.fitted = False self.use_pulse_numbers = False
def test_J1853(toasJ1853, modelJ1853, tempo2_res): """Test J1853 residuals with TEMPO2""" pint_resids_us = Residuals(toasJ1853, modelJ1853, use_weighted_mean=False).time_resids.to(u.s) # Due to PINT has higher order of ELL1 model, Tempo2 gives a difference around 3e-8 # Changed to 4e-8 since modification to get_PSR_freq() makes this 3.1e-8 log = logging.getLogger("TestJ1853.J1853_residuals") diffs = np.abs(pint_resids_us.value - tempo2_res[0]) log.debug("Diffs: %s\nMax: %s" % (diffs, np.max(diffs))) assert np.all(diffs < 4e-8), "J1853 residuals test failed."
def test_K96(self): modelJ1713 = copy.deepcopy(self.modelJ1713) log = logging.getLogger("TestJ1713 Switch of K96") modelJ1713.K96.value = False res = Residuals(self.toasJ1713, modelJ1713, use_weighted_mean=False).time_resids.to(u.s) delay = self.modelJ1713.delay(self.toasJ1713) testp = tdu.get_derivative_params(modelJ1713) for p in testp.keys(): self.modelJ1713.d_phase_d_param(self.toasJ1713, delay, p)
def wb_toas_all(wb_model): toas = get_TOAs(io.StringIO(tim_all)) for i in range(9): r = Residuals(toas, wb_model) if np.all(r.time_resids < 1 * u.ns): break toas.adjust_TOAs(TimeDelta(-r.time_resids)) else: raise ValueError return toas
def test_gls_chi2_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 """)) model.free_params = ["ELAT", "ELONG"] toas = make_fake_toas(57000, 59000, 100, 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) assert_allclose(r.calc_chi2(full_cov=True), r.calc_chi2(full_cov=False))
def test_build_dm_residual(self): dm_res = Residuals(toas=self.toa, model=self.model, residual_type="dm") assert len(dm_res.resids) == self.toa.ntoas # Test no mean subtraction dm_res_nomean = Residuals( toas=self.toa, model=self.model, residual_type="dm", subtract_mean=True ) assert len(dm_res_nomean.resids) == self.toa.ntoas weight = 1.0 / (dm_res.dm_error**2) wm = np.average(dm_res.resids, weights=weight) assert np.all(dm_res.resids - wm == dm_res_nomean.resids) dm_res_noweight = Residuals( toas=self.toa, model=self.model, residual_type="dm", subtract_mean=True, use_weighted_mean=False, ) assert np.all(dm_res.resids - dm_res.resids.mean() == dm_res_noweight.resids)
def test_parameter_overrides_model(model): t = make_fake_toas(56000, 59000, 10, model, obs="@") t.table["error"] = 1 * u.us delta_f = (1 / (t.last_MJD - t.first_MJD)).to(u.Hz) m_2 = deepcopy(model) m_2.F0.quantity += 2 * delta_f m_2.TRACK.value = "-2" r = Residuals(t, m_2) assert np.amax(r.phase_resids) - np.amin(r.phase_resids) > 1 r = Residuals(t, m_2, track_mode="nearest") assert np.amax(r.phase_resids) - np.amin(r.phase_resids) <= 1 r = Residuals(t, m_2, track_mode="use_pulse_numbers") assert np.amax(r.phase_resids) - np.amin(r.phase_resids) > 1 m_2.TRACK.value = "0" r = Residuals(t, m_2) assert np.amax(r.phase_resids) - np.amin(r.phase_resids) <= 1 r = Residuals(t, m_2, track_mode="nearest") assert np.amax(r.phase_resids) - np.amin(r.phase_resids) <= 1 r = Residuals(t, m_2, track_mode="use_pulse_numbers") assert np.amax(r.phase_resids) - np.amin(r.phase_resids) > 1