Exemplo n.º 1
0
def test_random_models(fitter):
    # Get model and TOAs
    m, t = get_model_and_toas(os.path.join(datadir, "NGC6440E.par"),
                              os.path.join(datadir, "NGC6440E.tim"))

    f = fitter(toas=t, model=m)
    # Do a 4-parameter fit
    f.model.free_params = ("F0", "F1", "RAJ", "DECJ")
    f.fit_toas()

    # this contains TOAs up through 54200
    # make new ones starting there
    tnew = simulation.make_fake_toas_uniform(54200, 59000, 59000 - 54200,
                                             f.model)
    dphase, mrand = simulation.calculate_random_models(f, tnew, Nmodels=30)

    # this is a bit stochastic, but I see typically < 0.14 cycles
    # for the uncertainty at 59000
    assert np.all(dphase.std(axis=0) < 0.2)

    # redo it with only F0 free
    dphase_F, mrand_F = simulation.calculate_random_models(f,
                                                           tnew,
                                                           Nmodels=100,
                                                           params=["F0"])

    # this should be less than the fully free version
    assert dphase_F.std(axis=0).max() < dphase.std(axis=0).max()
Exemplo n.º 2
0
def test_random_models_wb(fitter):
    model = get_model(
        os.path.join(datadir, "J1614-2230_NANOGrav_12yv3.wb.gls.par"))
    toas = get_TOAs(
        os.path.join(datadir, "J1614-2230_NANOGrav_12yv3.wb.tim"),
        ephem="DE436",
        bipm_version="BIPM2015",
    )
    f = fitter(toas, model)
    # Do a 4-parameter fit
    f.model.free_params = ("F0", "F1", "ELONG", "ELAT")
    f.fit_toas()

    tnew = simulation.make_fake_toas_uniform(54200, 59000,
                                             (59000 - 54200) // 10, f.model)
    dphase, mrand = simulation.calculate_random_models(f, tnew, Nmodels=30)

    # this is a bit stochastic, but I see typically < 1e-4 cycles for this
    # for the uncertainty at 59000
    assert np.all(dphase.std(axis=0) < 1e-4)
Exemplo n.º 3
0
    def random_models(self, selected):
        """Compute and plot random models
        """
        log.info("Computing random models based on parameter covariance matrix.")
        if [p for p in self.postfit_model.free_params if p.startswith("DM")]:
            log.warning(
                "Fitting for DM while using random models can cause strange behavior."
            )

        # These are the currently selected TOAs in the fit
        sim_sel = copy.deepcopy(self.selected_toas)
        # These are single TOAs from each cluster of TOAs
        inds = np.zeros(sim_sel.ntoas, dtype=bool)
        inds[np.unique(sim_sel.get_clusters(), return_index=True)[1]] |= True
        sim_sel = sim_sel[inds]
        # Get the range of MJDs we are using in the fit
        mjds = sim_sel.get_mjds().value
        minselMJD, maxselMJD = mjds.min(), mjds.max()

        extra = 0.1  # Fraction beyond TOAs to plot or calculate random models
        if self.faketoas1 is None:
            mjds = self.all_toas.get_mjds().value
            minallMJD, maxallMJD = mjds.min(), mjds.max()
            spanMJD = maxallMJD - minallMJD
            # want roughly 1 per day up to 3 years
            if spanMJD < 1000:
                Ntoas = min(400, int(spanMJD))
            elif spanMJD < 4000:
                Ntoas = min(750, int(spanMJD) // 2)
            else:
                Ntoas = min(1500, int(spanMJD) // 4)
            log.debug(f"Generating {Ntoas} fake TOAs for the random models")
            # By default we will use TOAs from the TopoCenter.  This gets done only once.
            self.faketoas1 = make_fake_toas_uniform(
                minallMJD - extra * spanMJD,
                maxallMJD + extra * spanMJD,
                Ntoas,
                self.postfit_model,
                obs="coe",
                freq=1 * u.THz,  # effectively infinite frequency
                include_bipm=sim_sel.clock_corr_info["include_bipm"],
                include_gps=sim_sel.clock_corr_info["include_gps"],
            )
        self.faketoas1.compute_pulse_numbers(self.postfit_model)

        # Combine our TOAs
        toas = merge_TOAs([sim_sel, self.faketoas1])
        zero_residuals(toas, self.postfit_model)
        toas.table.sort("tdbld")  # for plotting

        # Get a selection array to select the non-fake TOAs
        refs = np.asarray(toas.get_flag_value("name")[0]) != "fake"

        # Compute the new random timing models
        rs = calculate_random_models(
            self.fitter, toas, Nmodels=15, keep_models=False, return_time=True,
        )

        # Get a selection array for the fake TOAs that covers the fit TOAs (plus extra)
        mjds = toas.get_mjds().value
        spanMJD = maxselMJD - minselMJD
        toplot = np.bitwise_and(
            mjds > (minselMJD - extra * spanMJD), mjds < (maxselMJD + extra * spanMJD)
        )

        # This is the mean of the reference resids for the selected TOAs
        if selected.sum():  # shorthand for having some selected
            ref_mean = self.postfit_resids.time_resids[selected][inds].mean()
        else:
            ref_mean = self.postfit_resids.time_resids[inds].mean()
        # This is the means of the corresponding resids from the random models
        ran_mean = rs[:, refs].mean(axis=1)
        #  Now adjust each set of random resids so that the ran_mean == ref_mean
        rs -= ran_mean[:, np.newaxis]
        rs += ref_mean
        # And store the key things for plotting
        self.faketoas = toas
        self.random_resids = rs
Exemplo n.º 4
0
    def fit(self, selected, iters=1):
        """
        Run a fit using the specified fitter
        """
        # Select all the TOAs if none are explicitly set
        if not any(selected):
            selected = ~selected

        if self.fitted:
            self.prefit_model = self.postfit_model
            self.prefit_resids = self.postfit_resids

        if self.fitter == Fitters.POWELL:
            fitter = pint.fitter.PowellFitter(self.selected_toas, self.prefit_model)
        elif self.fitter == Fitters.WLS:
            fitter = pint.fitter.WLSFitter(self.selected_toas, self.prefit_model)
        elif self.fitter == Fitters.GLS:
            fitter = pint.fitter.GLSFitter(self.selected_toas, self.prefit_model)
        chi2 = self.prefit_resids.chi2
        wrms = self.prefit_resids.rms_weighted()
        print("Pre-Fit Chi2:\t\t%.8g" % chi2)
        print("Pre-Fit Weighted RMS:\t%.8g us" % wrms.to(u.us).value)

        fitter.fit_toas(maxiter=1)
        self.postfit_model = fitter.model
        self.postfit_resids = Residuals(self.all_toas, self.postfit_model)
        self.fitted = True
        self.write_fit_summary()

        # TODO: delta_pulse_numbers need some work. They serve both for PHASE and -padd functions from the TOAs
        # as well as for phase jumps added manually in the GUI. They really should not be zeroed out here because
        # that will wipe out preexisting values
        self.all_toas.table["delta_pulse_numbers"] = np.zeros(self.all_toas.ntoas)
        self.selected_toas.table["delta_pulse_number"] = np.zeros(
            self.selected_toas.ntoas
        )

        # plot the prefit without jumps
        pm_no_jumps = copy.deepcopy(self.prefit_model)
        for param in pm_no_jumps.params:
            if param.startswith("JUMP"):
                getattr(pm_no_jumps, param).value = 0.0
                getattr(pm_no_jumps, param).frozen = True
        self.prefit_resids_no_jumps = Residuals(self.selected_toas, pm_no_jumps)

        f = copy.deepcopy(fitter)
        no_jumps = [
            False if "jump" in dict.keys() else True for dict in f.toas.table["flags"]
        ]
        f.toas.select(no_jumps)

        selectedMJDs = self.selected_toas.get_mjds()
        if all(no_jumps):
            q = list(self.all_toas.get_mjds())
            index = q.index(
                [i for i in self.all_toas.get_mjds() if i > selectedMJDs.min()][0]
            )
            rs_mean = (
                Residuals(self.all_toas, f.model)
                .phase_resids[index : index + len(selectedMJDs)]
                .mean()
            )
        else:
            rs_mean = self.prefit_resids_no_jumps.phase_resids[no_jumps].mean()

        # determines how far on either side fake toas go
        # TODO: hard limit on how far fake toas can go --> can get clkcorr
        # errors if go before GBT existed, etc.
        minMJD, maxMJD = selectedMJDs.min(), selectedMJDs.max()
        spanMJDs = maxMJD - minMJD
        if spanMJDs < 30 * u.d:
            redge = ledge = 4
            npoints = 400
        elif spanMJDs < 90 * u.d:
            redge = ledge = 2
            npoints = 300
        elif spanMJDs < 200 * u.d:
            redge = ledge = 1
            npoints = 300
        elif spanMJDs < 400 * u.d:
            redge = ledge = 0.5
            npoints = 200
        else:
            redge = ledge = 1.0
            npoints = 250
        # Check to see if too recent
        nowish = (Time.now().mjd - 40) * u.d
        if maxMJD + spanMJDs * redge > nowish:
            redge = (nowish - maxMJD) / spanMJDs
            if redge < 0.0:
                redge = 0.0
        f_toas = make_fake_toas_uniform(
            minMJD - spanMJDs * ledge, maxMJD + spanMJDs * redge, npoints, f.model
        )
        rs = calculate_random_models(
            f, f_toas, Nmodels=10, keep_models=False, return_time=True
        )

        # subtract the mean residual of each random model from the respective residual set
        # based ONLY on the mean of the random residuals in the real data range
        start_index = np.where(abs(f_toas.get_mjds() - minMJD) < 1 * u.d)
        end_index = np.where(abs(f_toas.get_mjds() - maxMJD) < 1 * u.d)
        for i in range(len(rs)):
            # use start_index[0][0] since np.where returns np.array([], dtype), extract index from list in array
            rs_mean = rs[i][start_index[0][0] : end_index[0][0]].mean()
            rs[i][:] = [resid - rs_mean for resid in rs[i]]

        self.random_resids = rs
        self.fake_toas = f_toas
Exemplo n.º 5
0
# %%
print("Current last TOA: MJD {}".format(f.model.FINISH.quantity))

# %%
# pretend we have new observations starting at MJD 59000
# we don't need to track things continuously over that gap, but it helps us visualize what's happening
# so make fake TOAs to cover the gap
MJDmax = 59000
# the number of TOAs is arbitrary since it's mostly for visualization
tnew = pint.simulation.make_fake_toas_uniform(f.model.FINISH.value, MJDmax, 50,
                                              f.model)

# %%
# make fake models crossing from the last existing TOA to the start of new observations
dphase, mrand = simulation.calculate_random_models(f, tnew, Nmodels=100)
# this is the difference in time across the gap
dt = tnew.get_mjds() - f.model.PEPOCH.value * u.d

# %% [markdown]
# Compare against an analytic prediction which focused on the uncertainties from $F_0$ and $F_1 = \dot F$:
# $$
# \Delta \phi^2 = (\sigma_{F0} \Delta t)^2 + (0.5 \sigma_{F1} \Delta t^2)^2
# $$
# where $\Delta t$ is the gap over which we are extrapolating the solution.

# %%
analytic = np.sqrt((f.model.F0.uncertainty * dt)**2 +
                   (0.5 * f.model.F1.uncertainty * dt**2)**2).decompose()

# %%