示例#1
0
    def test_correct_number_of_parameters(self):
        lpost = PSDPosterior(self.ps.freq, self.ps.power,
                             self.model, m=self.ps.m)
        lpost.logprior = set_logprior(lpost, self.priors)

        with pytest.raises(IncorrectParameterError):
            lpost([2,3])
示例#2
0
    def test_making_posterior(self):
        lpost = PSDPosterior(self.ps.freq, self.ps.power,
                             self.model, m=self.ps.m)
        lpost.logprior = set_logprior(lpost, self.priors)

        assert lpost.x.all() == self.ps.freq.all()
        assert lpost.y.all() == self.ps.power.all()
    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
示例#4
0
    def test_logprior(self):
        t0 = [2.0]

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

        lp_test = lpost.logprior(t0)
        lp = np.log(scipy.stats.norm(2.0, 1.0).pdf(t0))
        assert lp == lp_test
    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
示例#6
0
    def test_negative_loglikelihood(self):
        t0 = [2.0]
        m = self.model(self.ps.freq[1:], t0)
        loglike = np.sum(self.ps.power[1:]/m + np.log(m))

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

        loglike_test = lpost.loglikelihood(t0, neg=True)

        assert np.isclose(loglike, loglike_test)
示例#7
0
    def test_counts_are_nan(self):
        y = np.nan * np.ones_like(self.ps.freq)

        ps_nan = copy.copy(self.ps)
        ps_nan.power = np.nan*np.ones_like(self.ps.freq)

        t0 = [2.0]
        m = self.model(self.ps.freq[1:], t0)
        lpost = PSDPosterior(ps_nan.freq, ps_nan.power, self.model)
        lpost.logprior = set_logprior(lpost, self.priors)

        assert np.isclose(lpost(t0), logmin, 1e-5)
示例#8
0
    def test_negative_posterior(self):
        t0 = [2.0]
        m = self.model(self.ps.freq[1:], t0)
        lpost = PSDPosterior(self.ps.freq, self.ps.power,
                             self.model, m=self.ps.m)
        lpost.logprior = set_logprior(lpost, self.priors)

        post_test = lpost(t0, neg=True)

        loglike = -np.sum(self.ps.power[1:]/m + np.log(m))
        logprior = np.log(scipy.stats.norm(2.0, 1.0).pdf(t0))
        post = -loglike - logprior

        assert np.isclose(post_test, post, atol=1.e-10)
示例#9
0
    def test_loglikelihood(self):
        t0 = [2.0]
        self.model.amplitude = t0[0]
        mean_model = self.model(self.ps.freq)

        loglike = -np.sum(np.log(mean_model)) - np.sum(self.ps.power/mean_model)

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

        loglike_test = lpost.loglikelihood(t0, neg=False)

        assert np.isclose(loglike, loglike_test)
示例#10
0
    def test_negative_loglikelihood(self):
        t0 = [2.0]
        self.model.amplitude = t0[0]

        mean_model = self.model(self.ps.freq)

        loglike = 2.0*self.m*(np.sum(np.log(mean_model)) +
                               np.sum(self.ps.power/mean_model) +
                               np.sum((2.0 / (2. * self.m) - 1.0) *
                                      np.log(self.ps.power)))


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

        loglike_test = lpost.loglikelihood(t0, neg=True)

        assert np.isclose(loglike, loglike_test)
示例#11
0
    def test_negative_posterior(self):
        t0 = [2.0]
        self.model.amplitude = t0[0]

        mean_model = self.model(self.ps.freq)
        lpost = PSDPosterior(self.ps.freq, self.ps.power,
                             self.model, m=self.ps.m)
        lpost.logprior = set_logprior(lpost, self.priors)

        post_test = lpost(t0, neg=True)

        loglike = -2.0*self.m*(np.sum(np.log(mean_model)) +
                               np.sum(self.ps.power/mean_model) +
                               np.sum((2.0 / (2. * self.m) - 1.0) *
                                      np.log(self.ps.power)))

        logprior = np.log(scipy.stats.norm(2.0, 1.0).pdf(t0))
        post = -loglike - logprior

        assert np.isclose(post_test, post, atol=1.e-10)
    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
示例#13
0
    def setup_class(cls):
        m = 1
        nfreq = 100000
        freq = np.arange(nfreq)
        noise = np.random.exponential(size=nfreq)
        power = noise * 2.0

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

        cls.ps = ps
        cls.a_mean, cls.a_var = 2.0, 1.0

        cls.model = models.Const1D()

        p_amplitude = lambda amplitude: \
            scipy.stats.norm(loc=cls.a_mean, scale=cls.a_var).pdf(amplitude)

        cls.priors = {"amplitude": p_amplitude}
        cls.lpost = PSDPosterior(cls.ps.freq,
                                 cls.ps.power,
                                 cls.model,
                                 m=cls.ps.m)
        cls.lpost.logprior = set_logprior(cls.lpost, cls.priors)

        cls.fitmethod = "BFGS"
        cls.max_post = True
        cls.t0 = [2.0]
        cls.neg = True
        cls.opt = scipy.optimize.minimize(cls.lpost,
                                          cls.t0,
                                          method=cls.fitmethod,
                                          args=cls.neg,
                                          tol=1.e-10)
    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)
        assert isinstance(res, OptimizationResults), "res must be of type " \
                                                     "OptimizationResults"

        pe.plotfits(res, save_plot=True)

        assert os.path.exists("test_ps_fit.png")
        os.unlink("test_ps_fit.png")

        pe.plotfits(res, save_plot=True, log=True)
        assert os.path.exists("test_ps_fit.png")
        os.unlink("test_ps_fit.png")

        pe.plotfits(res, res2=res, save_plot=True)
        assert os.path.exists("test_ps_fit.png")
        os.unlink("test_ps_fit.png")
示例#15
0
def fit_powerspectrum(ps,
                      model,
                      starting_pars,
                      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
        The list of starting guesses for the optimizer. 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

    Example
    -------

    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.x_0_0.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 priors:
        lpost = PSDPosterior(ps, model, priors=priors)
    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
示例#16
0
    def test_logprior_fails_without_prior(self):
        lpost = PSDPosterior(self.ps.freq, self.ps.power,
                             self.model, m=self.ps.m)

        with pytest.raises(AttributeError):
            lpost.logprior([1])
示例#17
0
    def test_correct_number_of_parameters(self):
        lpost = PSDPosterior(self.ps, self.model)
        lpost.logprior = set_logprior(lpost, self.priors)

        with pytest.raises(IncorrectParameterError):
            lpost([2,3])
示例#18
0
    def test_making_posterior(self):
        lpost = PSDPosterior(self.ps, self.model)
        lpost.logprior = set_logprior(lpost, self.priors)

        assert lpost.x.all() == self.ps.freq.all()
        assert lpost.y.all() == self.ps.power.all()
示例#19
0
    def test_logprior_fails_without_prior(self):
        lpost = PSDPosterior(self.ps, self.model)

        with pytest.raises(AttributeError):
            lpost.logprior([1])
示例#20
0
    def setup_class(cls):

        m = 1
        nfreq = 100
        freq = np.linspace(0, 10.0, nfreq + 1)[1:]


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

        cls.model = models.Lorentz1D() + models.Const1D()

        cls.x_0_0 = 2.0
        cls.fwhm_0 = 0.05
        cls.amplitude_0 = 1000.0

        cls.amplitude_1 = 2.0
        cls.model.x_0_0 = cls.x_0_0
        cls.model.fwhm_0 = cls.fwhm_0
        cls.model.amplitude_0 = cls.amplitude_0
        cls.model.amplitude_1 = cls.amplitude_1

        p = cls.model(freq)

        np.random.seed(400)
        power = noise*p

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

        cls.ps = ps
        cls.a_mean, cls.a_var = 2.0, 1.0
        cls.a2_mean, cls.a2_var = 100.0, 10.0

        p_amplitude_1 = lambda amplitude: \
            scipy.stats.norm(loc=cls.a_mean, scale=cls.a_var).pdf(amplitude)

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

        p_fwhm_0 = lambda alpha: \
            scipy.stats.uniform(0.0, 0.5).pdf(alpha)

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

        cls.priors = {"amplitude_1": p_amplitude_1,
                      "amplitude_0": p_amplitude_0,
                      "x_0_0": p_x_0_0,
                      "fwhm_0": p_fwhm_0}

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

        cls.fitmethod = "powell"
        cls.max_post = True
        cls.t0 = [cls.x_0_0, cls.fwhm_0, cls.amplitude_0, cls.amplitude_1]
        cls.neg = True
示例#21
0
# flat prior for the power law index
p_alpha = lambda alpha: ((-1. <= alpha) & (alpha <= 5.))

# flat prior for the power law amplitude
p_amplitude = lambda amplitude: ((0.01 <= amplitude) & (amplitude <= 10.0))

# normal prior for the white noise parameter
p_whitenoise = lambda white_noise: scipy.stats.norm(2.0, 0.1).pdf(white_noise)

priors = {}
priors["alpha_0"] = p_alpha
priors["amplitude_0"] = p_amplitude
priors["amplitude_1"] = p_whitenoise

starting_pars = [3.0, 1.0, 2.4]
lpost = PSDPosterior(ps.freq, ps.power, plc, priors=priors, m=ps.m)
parest = PSDParEst(ps, fitmethod='BFGS', max_post=True)
res = parest.fit(lpost, starting_pars)

sample = parest.sample(lpost,
                       res.p_opt,
                       cov=res.cov,
                       nwalkers=400,
                       niter=100,
                       burnin=200,
                       namestr="psd_modeling_test")

max_power, max_freq, max_ind = parest._compute_highest_outlier(lpost, res)
print(max_power)
pval = parest.calibrate_highest_outlier(lpost,
                                        starting_pars,
示例#22
0
 def test_fit_method_works_with_correct_parameter(self):
     pe = PSDParEst(self.ps)
     lpost = PSDPosterior(self.ps, self.model, self.priors)
     t0 = [2.0, 1, 1, 1]
     res = pe.fit(lpost, t0)
示例#23
0
    def setup_class(cls):
        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)

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

        cls.alpha_0 = 2.0
        cls.amplitude_0 = 100.0
        cls.amplitude_1 = 2.0

        cls.model.alpha_0 = cls.alpha_0
        cls.model.amplitude_0 = cls.amplitude_0
        cls.model.amplitude_1 = cls.amplitude_1

        p = cls.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"

        cls.ps = ps
        cls.a_mean, cls.a_var = 2.0, 1.0
        cls.a2_mean, cls.a2_var = 100.0, 10.0

        p_amplitude_1 = lambda amplitude: \
            scipy.stats.norm(loc=cls.a_mean, scale=cls.a_var).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=cls.a2_mean, scale=cls.a2_var).pdf(
                amplitude)

        cls.priors = {
            "amplitude_1": p_amplitude_1,
            "amplitude_0": p_amplitude_0,
            "alpha_0": p_alpha_0
        }

        cls.lpost = PSDPosterior(cls.ps, cls.model)
        cls.lpost.logprior = set_logprior(cls.lpost, cls.priors)

        cls.fitmethod = "BFGS"
        cls.max_post = True
        cls.t0 = [cls.amplitude_0, cls.alpha_0, cls.amplitude_1]
        cls.neg = True
        cls.opt = scipy.optimize.minimize(cls.lpost,
                                          cls.t0,
                                          method=cls.fitmethod,
                                          args=cls.neg,
                                          tol=1.e-5)

        cls.optres = OptimizationResultsSubclassDummy(cls.lpost,
                                                      cls.opt,
                                                      neg=True)
示例#24
0
    def test_logprior_fails_without_prior(self):
        lpost = PSDPosterior(self.ps.freq, self.ps.power,
                             self.model, m=self.ps.m)

        with pytest.raises(AttributeError):
            lpost.logprior([1])