def test_fully_coherent(self): h0 = 1 sqrtSX = 1 F0 = 30 F1 = -1e-10 F2 = 0 minStartTime = 700000000 duration = 1 * 86400 maxStartTime = minStartTime + duration Alpha = 5e-3 Delta = 1.2 tref = minStartTime Writer = pyfstat.Writer( F0=F0, F1=F1, F2=F2, label=self.label, h0=h0, sqrtSX=sqrtSX, outdir=self.outdir, tstart=minStartTime, Alpha=Alpha, Delta=Delta, tref=tref, duration=duration, Band=4, ) Writer.make_data() predicted_FS = Writer.predict_fstat() theta = { "F0": {"type": "norm", "loc": F0, "scale": np.abs(1e-10 * F0)}, "F1": {"type": "norm", "loc": F1, "scale": np.abs(1e-10 * F1)}, "F2": F2, "Alpha": Alpha, "Delta": Delta, } search = pyfstat.MCMCSearch( label=self.label, outdir=self.outdir, theta_prior=theta, tref=tref, sftfilepattern="{}/*{}*sft".format(Writer.outdir, Writer.label), minStartTime=minStartTime, maxStartTime=maxStartTime, nsteps=[100, 100], nwalkers=100, ntemps=2, log10beta_min=-1, ) search.run(create_plots=False) _, FS = search.get_max_twoF() print(("Predicted twoF is {} while recovered is {}".format(predicted_FS, FS))) self.assertTrue( FS > predicted_FS or np.abs((FS - predicted_FS)) / predicted_FS < 0.3 )
def test_tp_parsing(self): this_writer = self.writer_class_to_test(outdir=self.outdir, **default_Writer_params, **self.signal_parameters) this_writer.make_data() theta_prior = { key: value for key, value in default_signal_params.items() if key not in ["h0", "cosi", "psi", "phi"] } theta_prior.update( {key: value for key, value in default_binary_params.items()}) theta_prior["tp"] = { "type": "unif", "lower": default_binary_params["tp"] - 0.5 * default_binary_params["period"], "upper": default_binary_params["tp"] + 0.5 * default_binary_params["period"], } theta_prior.pop mcmc_kwargs = { "nsteps": [50], "nwalkers": 150, "ntemps": 3, } print(theta_prior) mcmc = pyfstat.MCMCSearch( binary=True, label="tp_parsing", outdir=self.outdir, sftfilepattern=this_writer.sftfilepath, theta_prior=theta_prior, tref=this_writer.tstart, minStartTime=this_writer.tstart, maxStartTime=this_writer.tend, **mcmc_kwargs, ) mcmc.run(plot_walkers=False) max_twoF_sample, _ = mcmc.get_max_twoF() relative_difference = np.abs(1.0 - max_twoF_sample["tp"] / default_binary_params["tp"]) self.assertTrue(relative_difference < 1e-5)
} else: theta_prior["Alpha"] = inj["Alpha"] theta_prior["Delta"] = inj["Delta"] # ptemcee sampler settings - in a real application we might want higher values ntemps = 2 log10beta_min = -1 nwalkers = 100 nsteps = [200, 200] # [burnin,production] mcmcsearch = pyfstat.MCMCSearch( label="mcmc_search_" + search_keys_label, outdir=outdir, sftfilepattern=os.path.join(outdir, "*simulated_signal*sft"), theta_prior=theta_prior, tref=inj["tref"], nsteps=nsteps, nwalkers=nwalkers, ntemps=ntemps, log10beta_min=log10beta_min, ) # walker plot is generated during main run of the search class mcmcsearch.run( walker_plot_args={"plot_det_stat": True, "injection_parameters": inj} ) mcmcsearch.print_summary() # call some built-in plotting methods # these can all highlight the injection parameters, too print("Making MCMCSearch {:s} corner plot...".format("-".join(search_keys))) mcmcsearch.plot_corner(truths=inj)
} for key in "F2", "Alpha", "Delta": theta_prior[key] = signal_parameters[key] ntemps = 2 log10beta_min = -0.5 nwalkers = 100 nsteps = [300, 300] mcmc = pyfstat.MCMCSearch( label=label, outdir=outdir, sftfilepattern=os.path.join(outdir, "*{}*sft".format(label)), theta_prior=theta_prior, tref=mid_time, minStartTime=data_parameters["tstart"], maxStartTime=tend, nsteps=nsteps, nwalkers=nwalkers, ntemps=ntemps, log10beta_min=log10beta_min, ) mcmc.transform_dictionary = dict( F0=dict(subtractor=signal_parameters["F0"], symbol="$f-f^\\mathrm{s}$"), F1=dict(subtractor=signal_parameters["F1"], symbol="$\\dot{f}-\\dot{f}^\\mathrm{s}$"), ) mcmc.run(walker_plot_args={ "plot_det_stat": True, "injection_parameters": signal_parameters })
"F2": F2, "Alpha": Alpha, "Delta": Delta, } ntemps = 2 log10beta_min = -0.5 nwalkers = 100 nsteps = [500, 2000] mcmc = pyfstat.MCMCSearch( label=label, sftfilepattern="data/*1_glitch*sft", theta_prior=theta_prior, tref=tref, minStartTime=tstart, maxStartTime=tstart + duration, nsteps=nsteps, nwalkers=nwalkers, ntemps=ntemps, log10beta_min=log10beta_min, ) mcmc.transform_dictionary["F0"] = dict(subtractor=F0, symbol="$f-f^\mathrm{s}$") mcmc.transform_dictionary["F1"] = dict(subtractor=F1, symbol="$\dot{f}-\dot{f}^\mathrm{s}$") mcmc.run() mcmc.plot_corner() mcmc.print_summary()
"F1": {"type": "unif", "lower": F1 - DeltaF1 / 2.0, "upper": F1 + DeltaF1 / 2.0}, "F2": F2, "Alpha": Alpha, "Delta": Delta, } ntemps = 1 log10beta_min = -1 nwalkers = 100 nsteps = [50, 50] mcmc = pyfstat.MCMCSearch( label="twoF_cumulative", outdir="data", sftfilepattern="data/*" + data_label + "*sft", theta_prior=theta_prior, tref=tref, minStartTime=tstart, maxStartTime=tend, nsteps=nsteps, nwalkers=nwalkers, ntemps=ntemps, log10beta_min=log10beta_min, ) mcmc.run() mcmc.plot_corner(add_prior=True) mcmc.print_summary() mcmc.generate_loudest() mcmc.plot_cumulative_max(add_pfs=True)
"lower": F1 - DeltaF1 / 2.0, "upper": F1 + DeltaF1 / 2.0 }, "F2": F2, "Alpha": Alpha, "Delta": Delta, } ntemps = 1 log10beta_min = -1 nwalkers = 100 nsteps = [100, 100] mcmc = pyfstat.MCMCSearch( label=label, outdir=outdir, sftfilepattern="{}/*{}*sft".format(outdir, label), theta_prior=theta_prior, tref=tref, minStartTime=tstart, maxStartTime=tend, nsteps=nsteps, nwalkers=nwalkers, ntemps=ntemps, log10beta_min=log10beta_min, ) mcmc.setup_initialisation(100, scatter_val=1e-10) mcmc.run() mcmc.plot_corner(add_prior=True) mcmc.print_summary()
"Alpha": Alpha, "Delta": Delta, } ntemps = 2 log10beta_min = -0.5 nwalkers = 100 nsteps = [500, 2000] mcmc = pyfstat.MCMCSearch( label=label, outdir=outdir, sftfilepattern=os.path.join(outdir, "*1_glitch*sft"), theta_prior=theta_prior, tref=tref, minStartTime=tstart, maxStartTime=tstart + duration, nsteps=nsteps, nwalkers=nwalkers, ntemps=ntemps, log10beta_min=log10beta_min, ) mcmc.transform_dictionary["F0"] = dict(subtractor=F0, symbol="$f-f^\\mathrm{s}$") mcmc.transform_dictionary["F1"] = dict( subtractor=F1, symbol="$\\dot{f}-\\dot{f}^\\mathrm{s}$") mcmc.run() mcmc.print_summary() mcmc.plot_corner()
for key in ["ecc", "argp"]: theta_prior[key] = 0 search_keys.remove(key) # ptemcee sampler settings - in a real application we might want higher values ntemps = 2 log10beta_min = -1 nwalkers = 100 nsteps = [100, 100] # [burnin,production] mcmcsearch = pyfstat.MCMCSearch( label="mcmc_search", outdir=outdir, sftfilepattern=os.path.join(outdir, "*simulated_signal*sft"), theta_prior=theta_prior, tref=signal_parameters["tref"], nsteps=nsteps, nwalkers=nwalkers, ntemps=ntemps, log10beta_min=log10beta_min, binary=True, ) # walker plot is generated during main run of the search class mcmcsearch.run( plot_walkers=True, walker_plot_args={ "plot_det_stat": True, "injection_parameters": signal_parameters }, ) mcmcsearch.print_summary()
def test_fully_coherent_MCMC(self): # use a single test case with loop over multiple prior choices # this could be much more elegantly done with @pytest.mark.parametrize # but that cannot be mixed with unittest classes thetas = { "uniformF0-uniformF1-fixedSky": { "F0": { "type": "unif", "lower": self.F0 - 1e-6, "upper": self.F0 + 1e-6, }, "F1": { "type": "unif", "lower": self.F1 - 1e-10, "upper": self.F1 + 1e-10, }, "F2": self.F2, "Alpha": self.Alpha, "Delta": self.Delta, }, "log10uniformF0-uniformF1-fixedSky": { "F0": { "type": "log10unif", "log10lower": np.log10(self.F0 - 1e-6), "log10upper": np.log10(self.F0 + 1e-6), }, "F1": { "type": "unif", "lower": self.F1 - 1e-10, "upper": self.F1 + 1e-10, }, "F2": self.F2, "Alpha": self.Alpha, "Delta": self.Delta, }, "normF0-normF1-fixedSky": { "F0": { "type": "norm", "loc": self.F0, "scale": 1e-6 }, "F1": { "type": "norm", "loc": self.F1, "scale": 1e-10 }, "F2": self.F2, "Alpha": self.Alpha, "Delta": self.Delta, }, "lognormF0-halfnormF1-fixedSky": { # lognorm parametrization is weird, from the scipy docs: # "A common parametrization for a lognormal random variable Y # is in terms of the mean, mu, and standard deviation, sigma, # of the unique normally distributed random variable X # such that exp(X) = Y. # This parametrization corresponds to setting s = sigma # and scale = exp(mu)." # Hence, to set up a "lognorm" prior, we need # to give "loc" in log scale but "scale" in linear scale # Also, "lognorm" makes no sense for negative F1, # hence combining this with "halfnorm" into a single case. "F0": { "type": "lognorm", "loc": np.log(self.F0), "scale": 1e-6 }, "F1": { "type": "halfnorm", "loc": self.F1 - 1e-10, "scale": 1e-10 }, "F2": self.F2, "Alpha": self.Alpha, "Delta": self.Delta, }, "normF0-normF1-uniformSky": { # norm in sky is too dangerous, can easily jump out of range "F0": { "type": "norm", "loc": self.F0, "scale": 1e-6 }, "F1": { "type": "norm", "loc": self.F1, "scale": 1e-10 }, "F2": self.F2, "Alpha": { "type": "unif", "lower": self.Alpha - 0.01, "upper": self.Alpha + 0.01, }, "Delta": { "type": "unif", "lower": self.Delta - 0.01, "upper": self.Delta + 0.01, }, }, } for prior_choice in thetas: self.search = pyfstat.MCMCSearch( label=self.label + "-" + prior_choice, outdir=self.outdir, theta_prior=thetas[prior_choice], tref=self.tref, sftfilepattern=self.Writer.sftfilepath, nsteps=[20, 20], nwalkers=20, ntemps=2, log10beta_min=-1, BSGL=self.BSGL, ) self.search.run(plot_walkers=False) self.search.print_summary() self._check_twoF_predicted() self._check_mcmc_quantiles() self._test_plots()
def test_MCMC_search_on_data_with_line(self): # We reuse the default multi-IFO SFTs # but add an additional single-detector artifact to H1 only. # For simplicity, this is modelled here as a fully modulated CW-like signal, # just restricted to the single detector. SFTs_H1 = self.Writer.sftfilepath.split(";")[0] SFTs_L1 = self.Writer.sftfilepath.split(";")[1] extra_writer = pyfstat.Writer( label=self.label + "_with_line", outdir=self.outdir, tref=self.tref, F0=self.Writer.F0 + 0.5e-2, F1=0, F2=0, Alpha=self.Writer.Alpha, Delta=self.Writer.Delta, h0=10 * self.Writer.h0, cosi=self.Writer.cosi, sqrtSX=0, # don't add yet another set of Gaussian noise noiseSFTs=SFTs_H1, SFTWindowType=self.Writer.SFTWindowType, SFTWindowBeta=self.Writer.SFTWindowBeta, ) extra_writer.make_data() data_with_line = ";".join([SFTs_L1, extra_writer.sftfilepath]) # use a single fixed prior and search F0 only for speed thetas = { "F0": { "type": "unif", "lower": self.F0 - 1e-2, "upper": self.F0 + 1e-2, }, "F1": self.F1, "F2": self.F2, "Alpha": self.Alpha, "Delta": self.Delta, } # now run a standard F-stat search over this data self.search = pyfstat.MCMCSearch( label=self.label + "-F", outdir=self.outdir, theta_prior=thetas, tref=self.tref, sftfilepattern=data_with_line, nsteps=[20, 20], nwalkers=20, ntemps=2, log10beta_min=-1, BSGL=False, ) self.search.run(plot_walkers=True) self.search.print_summary() # The standard checks here are expected to fail, # as the F-search will get confused by the line # and recover a much higher maxTwoF than predicted. self._check_twoF_predicted(assertTrue=False) mode_F0_Fsearch = self.max_dict["F0"] maxTwoF_Fsearch = self.maxTwoF self._check_mcmc_quantiles(assertTrue=False) self.assertTrue(maxTwoF_Fsearch > self.twoF_predicted) self._test_plots() # also run a BSGL search over the same data self.search = pyfstat.MCMCSearch( label=self.label + "-BSGL", outdir=self.outdir, theta_prior=thetas, tref=self.tref, sftfilepattern=data_with_line, nsteps=[20, 20], nwalkers=20, ntemps=2, log10beta_min=-1, BSGL=True, ) self.search.run(plot_walkers=True) self.search.print_summary() # Still skipping the standard checks, # as we're using too cheap a MCMC setup here for them to be robust. self._check_twoF_predicted(assertTrue=False) mode_F0_BSGLsearch = self.max_dict["F0"] maxTwoF_BSGLsearch = self.maxTwoF self._check_mcmc_quantiles(assertTrue=False) # But for sure, the BSGL search should find a lower-F mode # closer to the true multi-IFO signal. self.assertTrue(maxTwoF_BSGLsearch < maxTwoF_Fsearch) self.assertTrue(mode_F0_BSGLsearch < mode_F0_Fsearch) self.assertTrue( np.abs(mode_F0_BSGLsearch - self.F0) < np.abs(mode_F0_Fsearch - self.F0)) self.assertTrue(maxTwoF_BSGLsearch < self.twoF_predicted) self._test_plots()