def test_generate_data_produces_correct_distribution(self):
        model = models.Const1D()

        model.amplitude = 2.0

        p = model(self.ps.freq)

        seed = 100
        rng = np.random.RandomState(seed)

        noise = rng.exponential(size=len(p))
        power = noise*p

        ps = Powerspectrum()
        ps.freq = self.ps.freq
        ps.power = power
        ps.m = 1
        ps.df = self.ps.freq[1]-self.ps.freq[0]
        ps.norm = "leahy"

        lpost = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        pe = PSDParEst(ps)

        rng2 = np.random.RandomState(seed)
        sim_data = pe._generate_data(lpost, [2.0], rng2)

        assert np.allclose(ps.power, sim_data.power)
예제 #2
0
    def test_simulate_highest_outlier_works(self):
        m = 1
        nfreq = 100
        seed = 100
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(seed)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        nsim = 5

        loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        s_all = np.atleast_2d(np.ones(nsim) * 2.0).T

        pe = PSDParEst(ps)

        maxpow_sim = pe.simulate_highest_outlier(s_all, loglike, [2.0],
                                                 max_post=False, seed=seed)

        assert maxpow_sim.shape[0] == nsim
        assert np.all(maxpow_sim > 9.00) and np.all(maxpow_sim < 31.0)
    def test_fit_method_returns_optimization_results_object(self):
        pe = PSDParEst(self.ps)

        t0 = [2.0, 1, 1, 1]
        res = pe.fit(self.lpost, t0)
        assert isinstance(res, OptimizationResults), "res must be of type " \
                                                     "OptimizationResults"
예제 #4
0
    def test_calibrate_highest_outlier_works_with_mvn(self):
        m = 1
        nfreq = 10000
        seed = 100
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(seed)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        nsim = 10

        loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        pe = PSDParEst(ps)

        pval = pe.calibrate_highest_outlier(loglike, [2.0], sample=None,
                                            max_post=False, seed=seed,
                                            nsim=nsim)

        assert pval > 0.001
예제 #5
0
    def test_generate_data_produces_correct_distribution(self):
        model = models.Const1D()

        model.amplitude = 2.0

        p = model(self.ps.freq)

        seed = 100
        rng = np.random.RandomState(seed)

        noise = rng.exponential(size=len(p))
        power = noise*p

        ps = Powerspectrum()
        ps.freq = self.ps.freq
        ps.power = power
        ps.m = 1
        ps.df = self.ps.freq[1]-self.ps.freq[0]
        ps.norm = "leahy"

        lpost = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        pe = PSDParEst(ps)

        rng2 = np.random.RandomState(seed)
        sim_data = pe._generate_data(lpost, [2.0], rng2)

        assert np.allclose(ps.power, sim_data.power)
예제 #6
0
def dask_fit_fourier_pl_c(power_spectrum):
    """
    Fits the power law + constant observation model

    Parameters
    ----------
    power_spectrum :

    Return
    ------

    """

    # Make the random data into a Powerspectrum object
    ps = Powerspectrum()
    ps.freq = power_spectrum[0]
    ps.power = power_spectrum[1]
    ps.df = ps.freq[1] - ps.freq[0]
    ps.m = 1

    # Define the log-likelihood of the data given the model
    loglike = PSDLogLikelihood(ps.freq, ps.power, observation_model, m=ps.m)
    # Parameter estimation object
    parameter_estimate = PSDParEst(ps, fitmethod="L-BFGS-B", max_post=False)

    # Estimate the starting parameters
    ipe = InitialParameterEstimatePlC(ps.freq, ps.power)
    return parameter_estimate.fit(loglike, [ipe.amplitude, ipe.index, ipe.background],
                                  scipy_optimize_options=scipy_optimize_options)
예제 #7
0
    def test_compute_highest_outlier_works(self):

        mp_ind = 5
        max_power = 1000.0

        ps = Powerspectrum()
        ps.freq = np.arange(10)
        ps.power = np.ones_like(ps.freq)
        ps.power[mp_ind] = max_power
        ps.m = 1
        ps.df = ps.freq[1]-ps.freq[0]
        ps.norm = "leahy"

        model = models.Const1D()
        p_amplitude = lambda amplitude: \
            scipy.stats.norm(loc=1.0, scale=1.0).pdf(
                amplitude)

        priors = {"amplitude": p_amplitude}

        lpost = PSDPosterior(ps.freq, ps.power, model, 1)
        lpost.logprior = set_logprior(lpost, priors)

        pe = PSDParEst(ps)

        res = pe.fit(lpost, [1.0])

        res.mfit = np.ones_like(ps.freq)

        max_y, max_x, max_ind = pe._compute_highest_outlier(lpost, res)

        assert np.isclose(max_y[0], 2*max_power)
        assert np.isclose(max_x[0], ps.freq[mp_ind])
        assert max_ind == mp_ind
    def test_compute_highest_outlier_works(self):

        mp_ind = 5
        max_power = 1000.0

        ps = Powerspectrum()
        ps.freq = np.arange(10)
        ps.power = np.ones_like(ps.freq)
        ps.power[mp_ind] = max_power
        ps.m = 1
        ps.df = ps.freq[1]-ps.freq[0]
        ps.norm = "leahy"

        model = models.Const1D()
        p_amplitude = lambda amplitude: \
            scipy.stats.norm(loc=1.0, scale=1.0).pdf(
                amplitude)

        priors = {"amplitude": p_amplitude}

        lpost = PSDPosterior(ps.freq, ps.power, model, 1)
        lpost.logprior = set_logprior(lpost, priors)

        pe = PSDParEst(ps)

        res = pe.fit(lpost, [1.0])

        res.mfit = np.ones_like(ps.freq)

        max_y, max_x, max_ind = pe._compute_highest_outlier(lpost, res)

        assert np.isclose(max_y[0], 2*max_power)
        assert np.isclose(max_x[0], ps.freq[mp_ind])
        assert max_ind == mp_ind
    def test_simulate_highest_outlier_works(self):
        m = 1
        nfreq = 100000
        seed = 100
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(seed)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        nsim = 10

        loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        s_all = np.atleast_2d(np.ones(nsim) * 2.0).T

        pe = PSDParEst(ps)

        res = pe.fit(loglike, [2.0], neg=True)

        maxpow_sim = pe.simulate_highest_outlier(s_all, loglike, [2.0],
                                                 max_post=False, seed=seed)

        assert maxpow_sim.shape[0] == nsim
        assert np.all(maxpow_sim > 20.00) and np.all(maxpow_sim < 31.0)
예제 #10
0
 def test_fit_method_returns_optimization_results_object(self):
     pe = PSDParEst(self.ps)
     lpost = PSDPosterior(self.ps, self.model, self.priors)
     t0 = [2.0, 1, 1, 1]
     res = pe.fit(self.lpost, t0)
     assert isinstance(res, OptimizationResults), "res must be of type " \
                                                  "OptimizationResults"
예제 #11
0
    def test_calibrate_lrt_works_with_mvn(self):

        m = 1
        nfreq = 10000
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(100)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        model2 = models.PowerLaw1D() + models.Const1D()
        model2.x_0_0.fixed = True
        loglike2 = PSDLogLikelihood(ps.freq, ps.power, model2, 1)

        pe = PSDParEst(ps)

        pval = pe.calibrate_lrt(loglike, [2.0], loglike2,
                                [2.0, 1.0, 2.0], sample=None,
                                max_post=False, nsim=10,
                                seed=100)

        assert pval > 0.001
예제 #12
0
    def test_calibrate_lrt_works_with_sampling(self):
        m = 1
        nfreq = 100
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(100)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        lpost = PSDPosterior(ps.freq, ps.power, model, m=1)

        p_amplitude_1 = lambda amplitude: \
            scipy.stats.norm(loc=2.0, scale=1.0).pdf(amplitude)

        p_alpha_0 = lambda alpha: \
            scipy.stats.uniform(0.0, 5.0).pdf(alpha)

        p_amplitude_0 = lambda amplitude: \
            scipy.stats.norm(loc=self.a2_mean, scale=self.a2_var).pdf(
                amplitude)

        priors = {"amplitude": p_amplitude_1}

        priors2 = {
            "amplitude_1": p_amplitude_1,
            "amplitude_0": p_amplitude_0,
            "alpha_0": p_alpha_0
        }

        lpost.logprior = set_logprior(lpost, priors)

        model2 = models.PowerLaw1D() + models.Const1D()
        model2.x_0_0.fixed = True
        lpost2 = PSDPosterior(ps.freq, ps.power, model2, 1)
        lpost2.logprior = set_logprior(lpost2, priors2)

        pe = PSDParEst(ps)

        with catch_warnings(RuntimeWarning):
            pval = pe.calibrate_lrt(lpost, [2.0],
                                    lpost2, [2.0, 1.0, 2.0],
                                    sample=None,
                                    max_post=True,
                                    nsim=10,
                                    nwalkers=10,
                                    burnin=10,
                                    niter=10,
                                    seed=100)

        assert pval > 0.001
    def test_pvalue_calculated_correctly(self):
        a = [1, 1, 1, 2]
        obs_val = 1.5

        pe = PSDParEst(self.ps)
        pval = pe._compute_pvalue(obs_val, a)

        assert np.isclose(pval, 1./len(a))
예제 #14
0
    def test_pvalue_calculated_correctly(self):
        a = [1, 1, 1, 2]
        obs_val = 1.5

        pe = PSDParEst(self.ps)
        pval = pe._compute_pvalue(obs_val, a)

        assert np.isclose(pval, 1./len(a))
예제 #15
0
    def test_compute_lrt_sets_max_post_to_false(self):
        t0 = [2.0, 1, 1, 1]
        pe = PSDParEst(self.ps, max_post=True)

        assert pe.max_post is True
        delta_deviance = pe.compute_lrt(self.lpost, t0, self.lpost, t0)

        assert pe.max_post is False
    def test_compute_lrt_sets_max_post_to_false(self):
        t0 = [2.0, 1, 1, 1]
        pe = PSDParEst(self.ps, max_post=True)

        assert pe.max_post is True
        delta_deviance, _, _ = pe.compute_lrt(self.lpost, t0, self.lpost, t0)

        assert pe.max_post is False
예제 #17
0
    def test_compute_lrt_works(self):
        t0 = [2.0, 1, 1, 1]
        pe = PSDParEst(self.ps, max_post=True)

        assert pe.max_post is True
        delta_deviance, _, _ = pe.compute_lrt(self.lpost, t0, self.lpost, t0)

        assert pe.max_post is False
        assert np.absolute(delta_deviance) < 1.5e-4
    def test_compute_lrt_fails_when_garbage_goes_in(self):
        pe = PSDParEst(self.ps)
        t0 = [2.0, 1, 1, 1]

        with pytest.raises(TypeError):
            pe.compute_lrt(self.lpost, t0, None, t0)

        with pytest.raises(ValueError):
            pe.compute_lrt(self.lpost, t0[:-1], self.lpost, t0)
예제 #19
0
    def generate_data_rng_object_works(self):
        pe = PSDParEst(self.ps)

        sim_data1 = pe._generate_data(self.lpost, [2.0, 0.1, 100.0, 2.0],
                                      seed=1)
        sim_data2 = pe._generate_data(self.lpost, [2.0, 0.1, 100.0, 2.0],
                                      seed=1)

        assert np.allclose(sim_data1.power, sim_data2.power)
예제 #20
0
 def test_fit_method_works_with_correct_parameter(self):
     pe = PSDParEst(self.ps)
     lpost = PSDPosterior(self.ps.freq,
                          self.ps.power,
                          self.model,
                          self.priors,
                          m=self.ps.m)
     t0 = [2.0, 1, 1, 1]
     res = pe.fit(lpost, t0)
예제 #21
0
    def test_compute_lrt_computes_deviance_correctly(self):

        t0 = [2.0, 1, 1, 1]
        pe = PSDParEst(self.ps, max_post=True)

        # MB: This is a little too random
        delta_deviance = pe.compute_lrt(self.lpost, t0, self.lpost, t0)

        assert np.absolute(delta_deviance) < 1.5e-4
    def test_compute_lrt_computes_deviance_correctly(self):

        t0 = [2.0, 1, 1, 1]
        pe = PSDParEst(self.ps, max_post=True)

        # MB: This is a little too random
        delta_deviance, _, _ = pe.compute_lrt(self.lpost, t0,
                                        self.lpost, t0)

        assert np.absolute(delta_deviance) < 1.5e-4
예제 #23
0
    def test_plotfits_log_leahy(self):
        pe = PSDParEst(self.ps)
        t0 = [2.0, 1, 1, 1]

        res = pe.fit(self.lpost, t0)

        pe.plotfits(res, save_plot=True, log=True)

        assert os.path.exists("test_ps_fit.png")
        os.unlink("test_ps_fit.png")
예제 #24
0
    def test_generate_model_data(self):
        pe = PSDParEst(self.ps)

        m = self.model
        _fitter_to_model_params(m, self.t0)

        model = m(self.ps.freq)

        pe_model = pe._generate_model(self.lpost, [2.0, 0.1, 100, 2.0])

        assert np.allclose(model, pe_model)
예제 #25
0
    def test_sampler_runs(self):

        pe = PSDParEst(self.ps)

        sample_res = pe.sample(self.lpost, [2.0, 0.1, 100, 2.0], nwalkers=50,
                               niter=10, burnin=15, print_results=True,
                               plot=True)
        assert os.path.exists("test_corner.pdf")
        os.unlink("test_corner.pdf")
        assert sample_res.acceptance > 0.25
        assert isinstance(sample_res, SamplingResults)
    def generate_data_rng_object_works(self):
        pe = PSDParEst(self.ps)

        sim_data1 = pe._generate_data(self.lpost,
                                      [2.0, 0.1, 100.0, 2.0],
                                      seed=1)
        sim_data2 = pe._generate_data(self.lpost,
                                      [2.0, 0.1, 100.0, 2.0],
                                      seed=1)

        assert np.allclose(sim_data1.power, sim_data2.power)
예제 #27
0
    def test_plotfits_leahy(self):
        pe = PSDParEst(self.ps)
        t0 = [2.0, 1, 1, 1]
        lpost = PSDPosterior(self.ps, self.model, self.priors)

        res = pe.fit(lpost, t0)

        pe.plotfits(res, save_plot=True)

        assert os.path.exists("test_ps_fit.png")
        os.unlink("test_ps_fit.png")
    def test_calibrate_lrt_works_with_sampling(self):
        m = 1
        nfreq = 10000
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(100)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        lpost = PSDPosterior(ps.freq, ps.power, model, m=1)

        p_amplitude_1 = lambda amplitude: \
            scipy.stats.norm(loc=2.0, scale=1.0).pdf(amplitude)

        p_alpha_0 = lambda alpha: \
            scipy.stats.uniform(0.0, 5.0).pdf(alpha)

        p_amplitude_0 = lambda amplitude: \
            scipy.stats.norm(loc=self.a2_mean, scale=self.a2_var).pdf(
                amplitude)


        priors = {"amplitude": p_amplitude_1}

        priors2 = {"amplitude_1": p_amplitude_1,
                      "amplitude_0": p_amplitude_0,
                      "alpha_0": p_alpha_0}


        lpost.logprior = set_logprior(lpost, priors)

        model2 = models.PowerLaw1D() + models.Const1D()
        model2.x_0_0.fixed = True
        lpost2 = PSDPosterior(ps.freq, ps.power, model2, 1)
        lpost2.logprior = set_logprior(lpost2, priors2)

        pe = PSDParEst(ps)

        pval = pe.calibrate_lrt(lpost, [2.0], lpost2,
                                [2.0, 1.0, 2.0], sample=None,
                                max_post=True, nsim=10, nwalkers=100,
                                burnin=100, niter=20,
                                seed=100)

        assert pval > 0.001
    def test_plotfits_leahy(self):
        pe = PSDParEst(self.ps)
        t0 = [2.0, 1, 1, 1]
        lpost = PSDPosterior(self.ps.freq, self.ps.power,
                             self.model, self.priors, m=self.ps.m)

        res = pe.fit(lpost, t0)

        pe.plotfits(res, save_plot=True)

        assert os.path.exists("test_ps_fit.png")
        os.unlink("test_ps_fit.png")
예제 #30
0
    def generate_data_rng_object_works(self):
        pe = PSDParEst(self.ps)

        sim_data1 = pe._generate_data(
            self.lpost,
            [self.x_0_0, self.fwhm_0, self.amplitude_0, self.amplitude_1],
            seed=1)
        sim_data2 = pe._generate_data(
            self.lpost,
            [self.x_0_0, self.fwhm_0, self.amplitude_0, self.amplitude_1],
            seed=1)

        assert np.allclose(sim_data1.power, sim_data2.power)
예제 #31
0
    def test_generate_model_data(self):
        pe = PSDParEst(self.ps)

        m = self.model
        _fitter_to_model_params(m, self.t0)

        model = m(self.ps.freq)

        pe_model = pe._generate_model(self.lpost, [self.x_0_0, self.fwhm_0,
                                                   self.amplitude_0,
                                                   self.amplitude_1])

        assert np.allclose(model, pe_model)
예제 #32
0
    def test_fitting_with_ties_and_bounds(self, capsys):
        double_f = lambda model: model.x_0_0 * 2
        model = self.model.copy()
        model = self.model + models.Lorentz1D(amplitude=model.amplitude_0,
                                              x_0=model.x_0_0 * 2,
                                              fwhm=model.fwhm_0)
        model.x_0_0 = self.model.x_0_0
        model.amplitude_0 = self.model.amplitude_0
        model.amplitude_1 = self.model.amplitude_1
        model.fwhm_0 = self.model.fwhm_0
        model.x_0_2.tied = double_f
        model.fwhm_0.bounds = [0, 10]
        model.amplitude_0.fixed = True

        p = model(self.ps.freq)

        noise = np.random.exponential(size=len(p))
        power = noise * p

        ps = Powerspectrum()
        ps.freq = self.ps.freq
        ps.power = power
        ps.m = self.ps.m
        ps.df = self.ps.df
        ps.norm = "leahy"

        pe = PSDParEst(ps)
        llike = PSDLogLikelihood(ps.freq, ps.power, model)

        true_pars = [
            self.amplitude_0, self.x_0_0, self.fwhm_0, self.amplitude_1,
            model.amplitude_2.value, model.x_0_2.value, model.fwhm_2.value
        ]
        res = pe.fit(llike, true_pars)

        res.print_summary(llike)
        out, err = capsys.readouterr()
        assert "100.00000            (Fixed)" in out
        pattern = \
            re.compile(r"5\) Parameter x_0_2\s+: [0-9]\.[0-9]{5}\s+\(Tied\)")
        assert pattern.search(out)

        compare_pars = [
            self.x_0_0, self.fwhm_0, self.amplitude_1, model.amplitude_2.value,
            model.fwhm_2.value
        ]

        assert np.all(np.isclose(compare_pars, res.p_opt, rtol=0.5))
예제 #33
0
    def test_plotfits_log_pow(self):
        ps = Powerspectrum()
        ps.freq = self.ps.freq
        ps.power = self.ps.power
        ps.m = self.ps.m
        ps.df = self.ps.df
        ps.norm = "none"
        pe = PSDParEst(ps)

        t0 = [2.0, 1, 1, 1]
        res = pe.fit(self.lpost, t0)

        pe.plotfits(res, res2=res, save_plot=True, log=True)

        assert os.path.exists("test_ps_fit.png")
        os.unlink("test_ps_fit.png")
예제 #34
0
    def test_parest_stores_max_post_correctly(self):
        """
        Make sure the keyword for Maximum A Posteriori fits is stored correctly
        as a default.
        """
        pe = PSDParEst(self.ps)

        assert pe.max_post is True, "max_post should be set to True as a default."
예제 #35
0
    def test_plotfits_pow(self):
        t0 = [2.0, 1, 1, 1]
        ps = Powerspectrum()
        ps.freq = self.ps.freq
        ps.power = self.ps.power
        ps.m = self.ps.m
        ps.df = self.ps.df
        ps.norm = "none"
        pe = PSDParEst(ps)
        lpost = PSDPosterior(self.ps, self.model, self.priors)

        res = pe.fit(self.lpost, t0)

        pe.plotfits(res, res2=res, save_plot=True)

        assert os.path.exists("test_ps_fit.png")
        os.unlink("test_ps_fit.png")
예제 #36
0
    def test_fitting_with_ties_and_bounds(self, capsys, rebin):
        double_f = lambda model : model.x_0_0 * 2
        model = self.model.copy()
        model += models.Lorentz1D(amplitude=model.amplitude_0,
                                   x_0 = model.x_0_0 * 2,
                                   fwhm = model.fwhm_0)
        model.x_0_0 = self.model.x_0_0
        model.amplitude_0 = self.model.amplitude_0
        model.amplitude_1 = self.model.amplitude_1
        model.fwhm_0 = self.model.fwhm_0
        model.x_0_2.tied = double_f
        model.fwhm_0.bounds = [0, 10]
        model.amplitude_0.fixed = True

        p = model(self.ps.freq)

        noise = np.random.exponential(size=len(p))
        power = noise*p

        ps = Powerspectrum()
        ps.freq = self.ps.freq
        ps.power = power
        ps.m = self.ps.m
        ps.df = self.ps.df
        ps.norm = "leahy"

        if rebin != 0:
            ps = ps.rebin_log(rebin)

        pe = PSDParEst(ps, fitmethod="TNC")
        llike = PSDLogLikelihood(ps.freq, ps.power, model)

        true_pars = [self.x_0_0, self.fwhm_0,
                     self.amplitude_1,
                     model.amplitude_2.value,
                     model.fwhm_2.value]

        res = pe.fit(llike, true_pars, neg=True)

        compare_pars = [self.x_0_0, self.fwhm_0,
                        self.amplitude_1,
                        model.amplitude_2.value,
                        model.fwhm_2.value]

        assert np.allclose(compare_pars, res.p_opt, rtol=0.5)
    def test_find_highest_outlier_works_as_expected(self):

        mp_ind = 5
        max_power = 1000.0

        ps = Powerspectrum()
        ps.freq = np.arange(10)
        ps.power = np.ones_like(ps.freq)
        ps.power[mp_ind] = max_power
        ps.m = 1
        ps.df = ps.freq[1]-ps.freq[0]
        ps.norm = "leahy"

        pe = PSDParEst(ps)

        max_x, max_ind = pe._find_outlier(ps.freq, ps.power, max_power)

        assert np.isclose(max_x, ps.freq[mp_ind])
        assert max_ind == mp_ind
예제 #38
0
    def test_find_highest_outlier_works_as_expected(self):

        mp_ind = 5
        max_power = 1000.0

        ps = Powerspectrum()
        ps.freq = np.arange(10)
        ps.power = np.ones_like(ps.freq)
        ps.power[mp_ind] = max_power
        ps.m = 1
        ps.df = ps.freq[1]-ps.freq[0]
        ps.norm = "leahy"

        pe = PSDParEst(ps)

        max_x, max_ind = pe._find_outlier(ps.freq, ps.power, max_power)

        assert np.isclose(max_x, ps.freq[mp_ind])
        assert max_ind == mp_ind
예제 #39
0
    def test_calibrate_highest_outlier_works_with_sampling(self):
        m = 1
        nfreq = 100
        seed = 100
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(seed)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        nsim = 5

        lpost = PSDPosterior(ps.freq, ps.power, model, m=1)
        p_amplitude = lambda amplitude: \
            scipy.stats.norm(loc=1.0, scale=1.0).pdf(
                amplitude)

        priors = {"amplitude": p_amplitude}
        lpost.logprior = set_logprior(lpost, priors)

        pe = PSDParEst(ps)

        with catch_warnings(RuntimeWarning):
            pval = pe.calibrate_highest_outlier(lpost, [2.0],
                                                sample=None,
                                                max_post=True,
                                                seed=seed,
                                                nsim=nsim,
                                                niter=10,
                                                nwalkers=20,
                                                burnin=10)

        assert pval > 0.001
    def test_fitting_with_ties_and_bounds(self, capsys):
        double_f = lambda model : model.x_0_0 * 2
        model = self.model.copy()
        model += models.Lorentz1D(amplitude=model.amplitude_0,
                                   x_0 = model.x_0_0 * 2,
                                   fwhm = model.fwhm_0)
        model.x_0_0 = self.model.x_0_0
        model.amplitude_0 = self.model.amplitude_0
        model.amplitude_1 = self.model.amplitude_1
        model.fwhm_0 = self.model.fwhm_0
        model.x_0_2.tied = double_f
        model.fwhm_0.bounds = [0, 10]
        model.amplitude_0.fixed = True

        p = model(self.ps.freq)

        noise = np.random.exponential(size=len(p))
        power = noise*p

        ps = Powerspectrum()
        ps.freq = self.ps.freq
        ps.power = power
        ps.m = self.ps.m
        ps.df = self.ps.df
        ps.norm = "leahy"

        pe = PSDParEst(ps, fitmethod="TNC")
        llike = PSDLogLikelihood(ps.freq, ps.power, model)

        true_pars = [self.x_0_0, self.fwhm_0,
                     self.amplitude_1,
                     model.amplitude_2.value,
                     model.fwhm_2.value]

        res = pe.fit(llike, true_pars, neg=True)

        compare_pars = [self.x_0_0, self.fwhm_0,
                        self.amplitude_1,
                        model.amplitude_2.value,
                        model.fwhm_2.value]

        assert np.allclose(compare_pars, res.p_opt, rtol=0.5)
예제 #41
0
    def test_compute_lrt_works(self):

        m = 1
        nfreq = 100000
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(100)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1)
        loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        s_all = np.atleast_2d(np.ones(10) * 2.0).T

        model2 = models.PowerLaw1D() + models.Const1D()
        model2.x_0_0.fixed = True
        loglike2 = PSDLogLikelihood(ps.freq, ps.power, model2, 1)

        pe = PSDParEst(ps)

        lrt_obs, res1, res2 = pe.compute_lrt(loglike, [2.0],
                                             loglike2, [2.0, 1.0, 2.0],
                                             neg=True)
        lrt_sim = pe.simulate_lrts(s_all,
                                   loglike, [2.0],
                                   loglike2, [2.0, 1.0, 2.0],
                                   max_post=False,
                                   seed=100)

        assert (lrt_obs > 0.4) and (lrt_obs < 0.6)
        assert np.all(lrt_sim < 10.0) and np.all(lrt_sim > 0.01)
    def test_calibrate_highest_outlier_works_with_sampling(self):
        m = 1
        nfreq = 100000
        seed = 100
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(seed)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        nsim = 10

        lpost = PSDPosterior(ps.freq, ps.power, model, m=1)
        p_amplitude = lambda amplitude: \
            scipy.stats.norm(loc=1.0, scale=1.0).pdf(
                amplitude)

        priors = {"amplitude": p_amplitude}
        lpost.logprior = set_logprior(lpost, priors)

        pe = PSDParEst(ps)

        pval = pe.calibrate_highest_outlier(lpost, [2.0], sample=None,
                                            max_post=True, seed=seed,
                                            nsim=nsim, niter=20, nwalkers=100,
                                            burnin=100)

        assert pval > 0.001
예제 #43
0
    def test_compute_lrt_fails_when_garbage_goes_in(self):
        pe = PSDParEst(self.ps)
        t0 = [2.0, 1, 1, 1]

        with pytest.raises(TypeError):
            pe.compute_lrt(self.lpost, t0, None, t0)

        with pytest.raises(ValueError):
            pe.compute_lrt(self.lpost, t0[:-1], self.lpost, t0)
    def test_compute_lrt_works(self):

        m = 1
        nfreq = 100000
        freq = np.linspace(1, 10, nfreq)
        rng = np.random.RandomState(100)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = freq[1] - freq[0]
        ps.norm = "leahy"

        loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        s_all = np.atleast_2d(np.ones(10) * 2.0).T

        model2 = models.PowerLaw1D() + models.Const1D()
        model2.x_0_0.fixed = True
        loglike2 = PSDLogLikelihood(ps.freq, ps.power, model2, 1)

        pe = PSDParEst(ps)

        lrt_obs, res1, res2 = pe.compute_lrt(loglike, [2.0], loglike2,
                                             [2.0, 1.0, 2.0], neg=True)
        lrt_sim = pe.simulate_lrts(s_all, loglike, [2.0], loglike2,
                                           [2.0, 1.0, 2.0],
                                           seed=100)

        assert (lrt_obs > 0.4) and (lrt_obs < 0.6)
        assert np.all(lrt_sim < 10.0) and np.all(lrt_sim > 0.01)
예제 #45
0
    def test_calibrate_lrt_works_as_expected(self):

        m = 1
        df = 0.01
        freq = np.arange(df, 5 + df, df)
        nfreq = freq.size
        rng = np.random.RandomState(100)
        noise = rng.exponential(size=nfreq)
        model = models.Const1D()
        model.amplitude = 2.0
        p = model(freq)
        power = noise * p

        ps = Powerspectrum()
        ps.freq = freq
        ps.power = power
        ps.m = m
        ps.df = df
        ps.norm = "leahy"

        loglike = PSDLogLikelihood(ps.freq, ps.power, model, m=1)

        s_all = np.atleast_2d(np.ones(10) * 2.0).T

        model2 = models.PowerLaw1D() + models.Const1D()
        model2.x_0_0.fixed = True
        loglike2 = PSDLogLikelihood(ps.freq, ps.power, model2, m=1)

        pe = PSDParEst(ps)

        pval = pe.calibrate_lrt(loglike, [2.0], loglike2,
                                [2.0, 1.0, 2.0], sample=s_all,
                                max_post=False, nsim=5,
                                seed=100)

        assert pval > 0.001
    def test_generate_model_breaks_with_wrong_input(self):

        pe = PSDParEst(self.ps)

        with pytest.raises(AssertionError):
            pe_model = pe._generate_model([1, 2, 3, 4], [1, 2, 3, 4])
 def test_fit_fails_when_object_is_not_posterior_or_likelihood(self):
     x = np.ones(10)
     y = np.ones(10)
     pe = PSDParEst(self.ps)
     with pytest.raises(TypeError):
         res = pe.fit(x, y)
 def test_fit_fails_without_lpost_or_t0(self):
     pe = PSDParEst(self.ps)
     with pytest.raises(TypeError):
         res = pe.fit()
 def test_fit_fails_without_t0(self):
     pe = PSDParEst(self.ps)
     with pytest.raises(TypeError):
         res = pe.fit(np.ones(10))
 def test_fit_fails_with_incorrect_number_of_parameters(self):
     pe = PSDParEst(self.ps)
     t0 = [1,2]
     with pytest.raises(ValueError):
         res = pe.fit(self.lpost, t0)
 def test_fit_method_works_with_correct_parameter(self):
     pe = PSDParEst(self.ps)
     lpost = PSDPosterior(self.ps.freq, self.ps.power,
                          self.model, self.priors, m=self.ps.m)
     t0 = [2.0, 1, 1, 1]
     res = pe.fit(lpost, t0)
    def  test_generate_model_breaks_for_wrong_number_of_parameters(self):
        pe = PSDParEst(self.ps)

        with pytest.raises(AssertionError):
            pe_model = pe._generate_model(self.lpost, [1, 2, 3])
예제 #53
0
def fit_powerspectrum(ps, model, starting_pars=None, max_post=False,
                      priors=None, fitmethod="L-BFGS-B"):
    """
    Fit a number of Lorentzians to a power spectrum, possibly including white
    noise. Each Lorentzian has three parameters (amplitude, centroid position,
    full-width at half maximum), plus one extra parameter if the white noise
    level should be fit as well. Priors for each parameter can be included in
    case `max_post = True`, in which case the function will attempt a
    Maximum-A-Posteriori fit. Priors must be specified as a dictionary with one
    entry for each parameter.
    The parameter names are `(amplitude_i, x_0_i, fwhm_i)` for each `i` out of
    a total of `N` Lorentzians. The white noise level has a parameter
    `amplitude_(N+1)`. For example, a model with two Lorentzians and a
    white noise level would have parameters:
    [amplitude_0, x_0_0, fwhm_0, amplitude_1, x_0_1, fwhm_1, amplitude_2].

    Parameters
    ----------
    ps : Powerspectrum
        A Powerspectrum object with the data to be fit

    model: astropy.modeling.models class instance
        The parametric model supposed to represent the data. For details
        see the astropy.modeling documentation

    starting_pars : iterable, optional, default None
        The list of starting guesses for the optimizer. If it is not provided,
        then default parameters are taken from `model`. See explanation above
        for ordering of parameters in this list.

    fit_whitenoise : bool, optional, default True
        If True, the code will attempt to fit a white noise level along with
        the Lorentzians. Be sure to include a starting parameter for the
        optimizer in `starting_pars`!

    max_post : bool, optional, default False
        If True, perform a Maximum-A-Posteriori fit of the data rather than a
        Maximum Likelihood fit. Note that this requires priors to be specified,
        otherwise this will cause an exception!

    priors : {dict | None}, optional, default None
        Dictionary with priors for the MAP fit. This should be of the form
        {"parameter name": probability distribution, ...}

    fitmethod : string, optional, default "L-BFGS-B"
        Specifies an optimization algorithm to use. Supply any valid option for
        `scipy.optimize.minimize`.

    Returns
    -------
    parest : PSDParEst object
        A PSDParEst object for further analysis

    res : OptimizationResults object
        The OptimizationResults object storing useful results and quantities
        relating to the fit

    Examples
    --------

    We start by making an example power spectrum with three Lorentzians
    >>> m = 1
    >>> nfreq = 100000
    >>> freq = np.linspace(1, 1000, nfreq)

    >>> np.random.seed(100)  # set the seed for the random number generator
    >>> noise = np.random.exponential(size=nfreq)

    >>> model = models.PowerLaw1D() + models.Const1D()
    >>> model.x_0_0.fixed = True

    >>> alpha_0 = 2.0
    >>> amplitude_0 = 100.0
    >>> amplitude_1 = 2.0

    >>> model.alpha_0 = alpha_0
    >>> model.amplitude_0 = amplitude_0
    >>> model.amplitude_1 = amplitude_1

    >>> p = model(freq)
    >>> power = noise * p

    >>> ps = Powerspectrum()
    >>> ps.freq = freq
    >>> ps.power = power
    >>> ps.m = m
    >>> ps.df = freq[1] - freq[0]
    >>> ps.norm = "leahy"

    Now we have to guess starting parameters. For each Lorentzian, we have
    amplitude, centroid position and fwhm, and this pattern repeats for each
    Lorentzian in the fit. The white noise level is the last parameter.
    >>> t0 = [80, 1.5, 2.5]

    Let's also make a model to test:
    >>> model_to_test = models.PowerLaw1D() + models.Const1D()
    >>> model_to_test.amplitude_1.fixed = True

    We're ready for doing the fit:
    >>> parest, res = fit_powerspectrum(ps, model_to_test, t0)

    `res` contains a whole array of useful information about the fit, for
    example the parameters at the optimum:
    >>> p_opt = res.p_opt

    """
    if not (isinstance(starting_pars, np.ndarray) or isinstance(starting_pars,
                                                                list)):
        starting_pars = model.parameters

    if priors:
        lpost = PSDPosterior(ps.freq, ps.power, model, priors=priors,
                             m=ps.m)
    else:
        lpost = PSDLogLikelihood(ps.freq, ps.power, model, m=ps.m)

    parest = PSDParEst(ps, fitmethod=fitmethod, max_post=max_post)
    res = parest.fit(lpost, starting_pars, neg=True)

    return parest, res
예제 #54
0
def fit_crossspectrum(cs, model, starting_pars=None, max_post=False,
                      priors=None, fitmethod="L-BFGS-B"):
    """
    Fit a number of Lorentzians to a cross spectrum, possibly including white
    noise. Each Lorentzian has three parameters (amplitude, centroid position,
    full-width at half maximum), plus one extra parameter if the white noise
    level should be fit as well. Priors for each parameter can be included in
    case `max_post = True`, in which case the function will attempt a
    Maximum-A-Posteriori fit. Priors must be specified as a dictionary with one
    entry for each parameter.
    The parameter names are `(amplitude_i, x_0_i, fwhm_i)` for each `i` out of
    a total of `N` Lorentzians. The white noise level has a parameter
    `amplitude_(N+1)`. For example, a model with two Lorentzians and a
    white noise level would have parameters:
    [amplitude_0, x_0_0, fwhm_0, amplitude_1, x_0_1, fwhm_1, amplitude_2].

    Parameters
    ----------
    cs : Crossspectrum
        A Crossspectrum object with the data to be fit

    model: astropy.modeling.models class instance
        The parametric model supposed to represent the data. For details
        see the astropy.modeling documentation

    starting_pars : iterable, optional, default None
        The list of starting guesses for the optimizer. If it is not provided,
        then default parameters are taken from `model`. See explanation above
        for ordering of parameters in this list.

    max_post : bool, optional, default False
        If True, perform a Maximum-A-Posteriori fit of the data rather than a
        Maximum Likelihood fit. Note that this requires priors to be specified,
        otherwise this will cause an exception!

    priors : {dict | None}, optional, default None
        Dictionary with priors for the MAP fit. This should be of the form
        {"parameter name": probability distribution, ...}

    fitmethod : string, optional, default "L-BFGS-B"
        Specifies an optimization algorithm to use. Supply any valid option for
        `scipy.optimize.minimize`.

    Returns
    -------
    parest : PSDParEst object
        A PSDParEst object for further analysis

    res : OptimizationResults object
        The OptimizationResults object storing useful results and quantities
        relating to the fit
    """
    if not (isinstance(starting_pars, np.ndarray) or isinstance(starting_pars,
                                                                list)):
        starting_pars = model.parameters
    if priors:
        lgauss = GaussianPosterior(cs.freq, np.abs(cs.power), cs.power_err,
                                   model, priors)
    else:
        lgauss = GaussianLogLikelihood(cs.freq, np.abs(cs.power), model=model,
                                       yerr=cs.power_err)

    parest = PSDParEst(cs, fitmethod=fitmethod, max_post=max_post)
    res = parest.fit(lgauss, starting_pars, neg=True)

    return parest, res