Exemplo n.º 1
0
    def setUp(self):
        data = Data1D('fake', self._x, self._y, self._err)

        g1 = Gauss1D('g1')
        g1.fwhm.set(1.0, _tiny, _max, frozen=False)
        g1.pos.set(1.0, -_max, _max, frozen=False)
        g1.ampl.set(1.0, -_max, _max, frozen=False)
        p1 = PowLaw1D('p1')
        p1.gamma.set(1.0, -10, 10, frozen=False)
        p1.ampl.set(1.0, 0.0, _max, frozen=False)
        p1.ref.set(1.0, -_max, _max, frozen=True)      
        model = p1 + g1

        method = LevMar()
        method.config['maxfev'] = 10000
        method.config['ftol'] = float(_eps)
        method.config['epsfcn'] = float(_eps)
        method.config['gtol'] = float(_eps)
        method.config['xtol'] = float(_eps)
        method.config['factor'] = float(100)

        self.fit = Fit(data, model, Chi2DataVar(), method, Covariance())
        results = self.fit.fit()

        for key in ["succeeded", "numpoints", "nfev"]:
            assert self._fit_results_bench[key] == int(getattr(results, key))

        for key in ["rstat", "qval", "statval", "dof"]:
            assert numpy.allclose(float(self._fit_results_bench[key]),
                                  float(getattr(results, key)),
                                  1.e-7, 1.e-7)

        for key in ["parvals"]:
            try:
                assert numpy.allclose(self._fit_results_bench[key],
                                      getattr(results, key),
                                      1.e-4, 1.e-4)
            except AssertionError:
                print 'parvals bench: ', self._fit_results_bench[key]
                print 'parvals fit:   ', getattr(results, key)
                print 'results', results
                raise

        covresults = self.fit.est_errors()
        self.dof = results.dof
        self.mu = numpy.array(results.parvals)
        self.cov = numpy.array(covresults.extra_output)
        self.num = 10
Exemplo n.º 2
0
 def test_mychi_datahasbkg_modelhasnobkg(self):
     fit = Fit(self.data, self.model, MyChiNoBkg(), LevMar())
     results = fit.fit()
     self.compare_results(self._fit_mychi_results_bench, results)
Exemplo n.º 3
0
 def test_mychi_nobkgdata_modelhasbkg(self):
     data = self.bkg
     fit = Fit(data, self.model, MyChiWithBkg(), LevMar())
     results = fit.fit()
     self.compare_results(self._fit_mychinobkg_results_bench, results)
Exemplo n.º 4
0
 def test_mychi_data_and_model_have_bkg(self):
     fit = Fit(self.data, self.model, MyChiWithBkg(), LevMar())
     results = fit.fit()
     self.compare_results(self._fit_mychi_results_bench, results)
Exemplo n.º 5
0
 def test_mychi_data_and_model_donothave_bkg(self):
     data = self.bkg
     fit = Fit(data, self.model, MyChiNoBkg(), LevMar())
     results = fit.fit()
     self.compare_results(self._fit_mychinobkg_results_bench, results)
Exemplo n.º 6
0
def multifit(star_name, data_list, model_list, silent=False):
    """A function that will fit 2 models to 2 spectra simultaneously.
        This was created to fit the NaI doublets at ~3300 and ~5890 Angstroms.

    :param star_name: Name of the target star
    :type star_name: str
    :param data_list: List of spectrum data in the form [(wave, flux), (wave, flux),...]
    :type data_list: tuple
    :param model_list:  A list of unfit spectrum models
    :type model_list: list
    :param silent:  If true, no plots will generate, defaults to False
    :type silent: bool

    :return: models that are fit to the data
    :rtype: list

    """

    wave1, flux1 = data_list[0]
    wave2, flux2 = data_list[1]

    model1 = model_list[0]
    model2 = model_list[1]

    name_1 = star_name + " 1"
    name_2 = star_name + " 2"

    d1 = Data1D(name_1, wave1, flux1)
    d2 = Data1D(name_2, wave2, flux2)

    dall = DataSimulFit("combined", (d1, d2))
    mall = SimulFitModel("combined", (model1, model2))

    # # ==========================================
    # # Initial guesses

    # Dataset 1
    dplot1 = DataPlot()
    dplot1.prepare(d1)
    if silent is False:
        dplot1.plot()

    mplot1 = ModelPlot()
    mplot1.prepare(d1, model1)
    if silent is False:
        dplot1.plot()
        mplot1.overplot()
        plt.show()

        # Dataset 2
    dplot2 = DataPlot()
    dplot2.prepare(d2)
    if silent is False:
        dplot2.plot()

    mplot2 = ModelPlot()
    mplot2.prepare(d2, model2)
    if silent is False:
        dplot2.plot()
        mplot2.overplot()
        plt.show()

    # # =========================================
    # # Fitting happens here - don't break please
    stat = LeastSq()

    opt = LevMar()
    opt.verbose = 0
    opt.ftol = 1e-15
    opt.xtol = 1e-15
    opt.gtol = 1e-15
    opt.epsfcn = 1e-15
    print(opt)

    vfit = Fit(dall, mall, stat=stat, method=opt)
    print(vfit)
    vres = vfit.fit()

    print()
    print()
    print("Did the fit succeed? [bool]")
    print(vres.succeeded)
    print()
    print()
    print(vres.format())

    # # =========================================
    # # Plotting after fit
    if silent is False:
        # Dataset 1
        fplot1 = FitPlot()
        mplot1.prepare(d1, model1)
        fplot1.prepare(dplot1, mplot1)
        fplot1.plot()

        # residual
        title = "Data 1"
        plt.title(title)
        plt.plot(wave1, flux1 - model1(wave1))
        plt.show()

        # Dataset 2
        fplot2 = FitPlot()
        mplot2.prepare(d2, model2)
        fplot2.prepare(dplot2, mplot2)
        fplot2.plot()

        # residual
        title = "Data 2"
        plt.title(title)
        plt.plot(wave2, flux2 - model2(wave2))
        plt.show()

        # both datasets - no residuals
        splot = SplitPlot()
        splot.addplot(fplot1)
        splot.addplot(fplot2)

        plt.tight_layout()
        plt.show()

    return model_list
Exemplo n.º 7
0
def fit(star_name, data, model, silent=False, breakdown=False):
    """A function that will fit a given multi-part model to a given spectrum.



    :param star_name: Name of the target star
    :type star_name: str
    :param data: Spectrum data in the form (wave, flux)
    :type data: tuple
    :param model: An unfit spectrum model
    :type model: object
    :param silent:  If true, no plots will generate, defaults to False
    :type silent: bool

    :return: model that is fit to the data
    :rtype: object


    """

    wave, flux = data

    # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    d = Data1D(star_name, wave, flux)

    # ==========================================
    # Initial guesses

    # Dataset 1
    dplot = DataPlot()
    dplot.prepare(d)
    if silent is False:
        dplot.plot()

    mplot = ModelPlot()
    mplot.prepare(d, model)
    if silent is False:
        dplot.plot()
        mplot.overplot()
        plt.show()

    # =========================================
    # Fitting happens here - don't break please
    start = time.time()

    stat = LeastSq()

    opt = LevMar()

    opt.verbose = 0
    opt.ftol = 1e-15
    opt.xtol = 1e-15
    opt.gtol = 1e-15
    opt.epsfcn = 1e-15

    if silent is False:
        print(opt)

    vfit = Fit(d, model, stat=stat, method=opt)

    if silent is False:
        print(vfit)

    vres = vfit.fit()

    if silent is False:
        print()
        print()
        print(vres.format())

    # =========================================
    # Plotting after fit

    # Dataset 1
    if silent is False:
        fplot = FitPlot()
        mplot.prepare(d, model)
        fplot.prepare(dplot, mplot)
        fplot.plot()

        # residual
        plt.title(star_name)
        plt.plot(wave, flux - model(wave))

        # plt.xaxis(fontsize = )
        plt.xlabel("Wavelength (AA)", fontsize=12)
        plt.ylabel("Flux", fontsize=12)
        plt.tick_params(axis="both", labelsize=12)

    if silent is False:
        duration = time.time() - start
        print()
        print("Time taken: " + str(duration))
        print()

    plt.show()

    if breakdown is True:
        params = []

        cont = model[0]

        if silent is False:
            plt.scatter(wave, flux, marker=".", c="black")
            plt.plot(wave, model(wave), c="C1")

        for line in model:
            if line.name[0] != "(":
                if line.name == "Cont_flux":
                    if silent is False:
                        print(line)
                        plt.plot(wave, line(wave), linestyle="--")
                else:
                    params.append(line)
                    if silent is False:
                        print()
                        print(line)
                        plt.plot(wave, line(wave) * cont(wave), linestyle="--")

        plt.show()

        return model, params

    return model
Exemplo n.º 8
0
 def test_chi2constvar_stat(self):
     fit = Fit(self.data, self.model, Chi2ConstVar(), LevMar())
     results = fit.fit()
     self.compare_results(self._fit_chi2constvar_results_bench, results)
Exemplo n.º 9
0
 def test_leastsq_stat(self):
     fit = Fit(self.data, self.model, LeastSq(), LevMar())
     results = fit.fit()
     self.compare_results(self._fit_leastsq_results_bench, results)
Exemplo n.º 10
0
    def call(self, niter, seed):

        pars = {}
        pars_index = {}
        index = 0
        for par in self.model.pars:
            if par.frozen is False:
                name = '%s.%s' % (par.modelname, par.name)
                pars_index[index] = name
                pars[name] = []
                index += 1

        data = self.data
        y = data.y
        x = data.x
        if type(data) == Data1DAsymmetricErrs:
            y_l = y - data.elo
            y_h = y + data.ehi
        elif isinstance(data, (Data1D, )):
            y_l = data.staterror
            y_h = data.staterror
        else:
            msg = "{0} {1}".format(ReSampleData.__name__, type(data))
            raise NotImplementedError(msg)

        numpy.random.seed(seed)
        for j in range(niter):
            ry = []
            for i in range(len(y_l)):
                a = y_l[i]
                b = y_h[i]
                r = -1
                while r < a or r > b:
                    sigma = b - y[i]
                    u = numpy.random.random_sample()
                    if u < 0.5:
                        sigma = y[i] - a
                    r = numpy.random.normal(loc=y[i], scale=sigma, size=None)
                    if u < 0.5 and r > y[i]:
                        r = -1
                    if u > 0.5 and r < y[i]:
                        r = -1
                ry.append(r)

            ry = numpy.asarray(ry)
            # fit is performed for each simulated data point
            fit = Fit(Data1D('tmp', x, ry), self.model, LeastSq(), LevMar())
            fit_result = fit.fit()

            for index, val in enumerate(fit_result.parvals):
                name = pars_index[index]
                pars[name].append(val)

        result = {}
        for index, name in pars_index.items():
            avg = numpy.average(pars[name])
            std = numpy.std(pars[name])
            print(name, ': avg =', avg, ', std =', std)
            result[name] = pars[name]

        return result
Exemplo n.º 11
0
def main():
    config = read_config('config.yaml')
    # ref_cube = make_ref_cube(config)
    # target_position = SkyCoord(config['model']['ra1'], config['model']['dec1'], unit="deg").galactic

    cubes = load_cubes(config)
    print('which available cubes:', cubes)

    # converting data SkyCube to sherpa-format cube
    counts = cubes['counts'].to_sherpa_data3d() #dstype='Data3DInt')
    print('counts: ', counts)
    # Define a 2D gaussian for the spatial model
    # spatial_model = NormGauss2DInt('spatial-model')

    # Define a power law for the spectral model
    # spectral_model = PowLaw1D('spectral-model')

    coord = cubes['counts'].sky_image_ref.coordinates(mode="edges")
    energies = cubes['counts'].energies(mode='edges').to("TeV")
    print('my energy bins: ', energies)
    # import IPython; IPython.embed();

    # Set up exposure table model
    exposure = TableModel('exposure')
    exposure.load(None, cubes['exposure'].data.ravel())
    exposure.ampl.freeze()

    use_psf = config['model']['use_psf']

    model_gammapy = get_model_gammapy(config)

    spectral_model_sherpa = model_gammapy.spectral_model.to_sherpa()
    spectral_model_sherpa.ampl.thaw()

    spatial_model_sherpa = model_gammapy.spatial_model.to_sherpa()
    spatial_model_sherpa.xpos.freeze()
    spatial_model_sherpa.ypos.freeze()
    spatial_model_sherpa.r0.freeze()
    spatial_model_sherpa.width.freeze()

    source_model = CombinedModel3D(
        spatial_model=spatial_model_sherpa,
        spectral_model=spectral_model_sherpa,
    )

    # source_model = CombinedModel3DInt(
    #     spatial_model=spatial_model_sherpa,
    #     spectral_model=spectral_model_sherpa,
    #     exposure=exposure,
    #     coord=coord,
    #     energies=energies,
    #     use_psf=use_psf,
    #     psf=None,
    # )

    print(source_model)
    # source_model_cube = source_model.evaluate_cube(ref_cube)
    # model = source_model  # + background_model

    # source_model2 = CombinedModel3DInt(
    #     coord=coord,
    #     energies=energies,
    #     use_psf=False,
    #     exposure=cubes['exposure'],
    #     psf=None,
    #     spatial_model=spatial_model,
    #     spectral_model=spectral_model,
    # )

    model = 1e-9 * exposure * source_model  # 1e-9 flux factor

    fit = Fit(
        data=counts,
        model=model,
        stat=Chi2ConstVar(),
        method=LevMar(),
        # estmethod=Covariance(),
    )


    fit_results = fit.fit()
    print(fit_results.format())

    print('------------------------------------ end fitting')
Exemplo n.º 12
0
    def call(self, niter, seed=None):
        """Resample the data and fit the model to each iteration.

        .. versionadded:: 4.12.2
           The samples and statistic keys were added to the return
           value, the parameter values are returned as NumPy arrays
           rather than as lists, and the seed parameter was made
           optional.

        Parameters
        ----------
        niter : int
            The number of iterations.
        seed : int or None, optional
            The seed value.

        Returns
        -------
        sampled : dict
           The keys are samples, which contains the resampled data
           used in the fits as a niter by ndata array, and the free
           parameters in the fit, containing a NumPy array containing
           the fit parameter for each iteration (of size niter).

        Notes
        -----
        The fit for each iteration uses the input values of the
        model parameters as the starting point. The parameters of
        the model are not changed by this method.

        """

        # Each fit is reset to this set of values as the starting point
        orig_pars = self.model.thawedpars

        pars = {}
        pars_index = []
        for par in self.model.pars:
            if par.frozen:
                continue

            name = par.fullname
            pars_index.append(name)
            pars[name] = numpy.zeros(niter)

        data = self.data
        y = data.y
        x = data.x
        if type(data) == Data1DAsymmetricErrs:
            y_l = y - data.elo
            y_h = y + data.ehi
        elif isinstance(data, (Data1D, )):
            y_l = data.staterror
            y_h = data.staterror
        else:
            msg = "{0} {1}".format(ReSampleData.__name__, type(data))
            raise NotImplementedError(msg)

        ny = len(y)

        fake_data = Data1D('tmp', x, numpy.zeros(ny))

        numpy.random.seed(seed)
        ry_all = numpy.zeros((niter, ny), dtype=y_l.dtype)
        stats = numpy.zeros(niter)
        for j in range(niter):
            ry = ry_all[j]
            for i in range(ny):
                a = y_l[i]
                b = y_h[i]
                r = None

                while r is None:

                    # Flip between low or hi
                    #  u = 0  pick low
                    #  u = 1  pick high
                    #
                    # Switching to randint rather than random_sample
                    # leads to different answers, so the tests fail,
                    # so leave as is.
                    #
                    # u = numpy.random.randint(low=0, high=2)
                    #
                    u = numpy.random.random_sample()
                    u = 0 if u < 0.5 else 1

                    # Rather than dropping this value, we could
                    # reflect it (ie multiply it by -1 if the sign
                    # is wrong). Would this affect the statistical
                    # properties?
                    #
                    dr = numpy.random.normal(loc=0, scale=1, size=None)
                    if u == 0:
                        if dr > 0:
                            continue

                        sigma = y[i] - a

                    else:
                        if dr < 0:
                            continue

                        sigma = b - y[i]

                    r = y[i] + dr * sigma

                ry[i] = r

            # fit is performed for each simulated data point, and we
            # always start at the original best-fit location to
            # start the fit (by making sure we always reset after a fit).
            #
            fake_data.y = ry
            fit = Fit(fake_data, self.model, LeastSq(), LevMar())
            try:
                fit_result = fit.fit()
            finally:
                self.model.thawedpars = orig_pars

            stats[j] = fit_result.statval
            for name, val in zip(fit_result.parnames, fit_result.parvals):
                pars[name][j] = val

        result = {'samples': ry_all, 'statistic': stats}
        for name in pars_index:
            avg = numpy.average(pars[name])
            std = numpy.std(pars[name])
            info('{} : avg = {} , std = {}'.format(name, avg, std))
            result[name] = pars[name]

        return result
Exemplo n.º 13
0
def fit_asymmetric_err(bench, data):
    model = PowLaw1D('p1')
    fit = Fit(data, model, Chi2Gehrels(), LevMar())
    results = fit.fit()
    compare(bench, results)
    return model
Exemplo n.º 14
0
 def test_wstat(self):
     fit = Fit(self.data, self.model, WStat(), LevMar())
     results = fit.fit()
     self.compare_results(self._fit_wstat_results_bench, results)