def get_scales(self, fit, myscales=None): scales = [] thawedpars = [par for par in fit.model.pars if not par.frozen] if None == myscales: oldestmethod = fit.estmethod covar = Covariance() covar.config['sigma'] = self.sigma fit.estmethod = Covariance() try: r = fit.est_errors() finally: fit.estmethod = oldestmethod for par, val, lo, hi in izip(thawedpars, r.parvals, r.parmins, r.parmaxes): scale = None if lo is not None and hi is not None: scale = numpy.abs(lo) else: warning("Covariance failed for '%s', trying Confidence..." % par.fullname) conf = Confidence() conf.config['sigma'] = self.sigma fit.estmethod = conf try: t = fit.est_errors(parlist=(par,)) if t.parmins[0] is not None and t.parmaxes[0] is not None: scale = numpy.abs(t.parmins[0]) else: if t.parmins[0] is None and t.parmaxes[0] is not None: scale = numpy.abs(t.parmaxes[0]) else: warning('1 sigma bounds for parameter ' + par.fullname + ' could not be found, using soft limit minimum') if 0.0 == numpy.abs(par.min): scale = 1.0e-16 else: scale = numpy.abs(par.min) finally: fit.estmethod = oldestmethod scales.append(scale) else: if not numpy.iterable(myscales): raise TypeError( "scales option must be iterable of length %d " % len(thawedpars)) scales = map(abs, myscales) scales = numpy.asarray(scales).transpose() return scales
def get_scales(self, fit, myscales=None): scales = [] thawedpars = [par for par in fit.model.pars if not par.frozen] if None == myscales: oldestmethod = fit.estmethod covar = Covariance() covar.config['sigma'] = self.sigma fit.estmethod = Covariance() try: r = fit.est_errors() finally: fit.estmethod = oldestmethod for par, val, lo, hi in zip(thawedpars, r.parvals, r.parmins, r.parmaxes): scale = None if lo is not None and hi is not None: scale = numpy.abs(lo) else: warning("Covariance failed for '%s', trying Confidence..." % par.fullname) conf = Confidence() conf.config['sigma'] = self.sigma fit.estmethod = conf try: t = fit.est_errors(parlist=(par,)) if t.parmins[0] is not None and t.parmaxes[0] is not None: scale = numpy.abs(t.parmins[0]) else: if t.parmins[0] is None and t.parmaxes[0] is not None: scale = numpy.abs(t.parmaxes[0]) else: warning('1 sigma bounds for parameter ' + par.fullname + ' could not be found, using soft limit minimum') if 0.0 == numpy.abs(par.min): scale = 1.0e-16 else: scale = numpy.abs(par.min) finally: fit.estmethod = oldestmethod scales.append(scale) else: if not numpy.iterable(myscales): raise TypeError( "scales option must be iterable of length %d " % len(thawedpars)) scales = list(map(abs, myscales)) scales = numpy.asarray(scales).transpose() return scales
def test_covar(): standard = numpy.array([[0.4935702, 0.06857833, numpy.nan], [0.06857833, 0.26405554, numpy.nan], [numpy.nan, numpy.nan, 2.58857314]]) cov = Covariance() results = cov.compute(stat, None, fittedpars, minpars, maxpars, hardminpars, hardmaxpars, limit_parnums, freeze_par, thaw_par, report_progress, get_par_name) # These tests used to have a tolerance of 1e-4 but it appears to # be able to use a more-restrictive tolerance. # expected = standard.diagonal() assert results[1] == pytest.approx(expected)
def setUp(self): self.method = LevMar() self.stat = Chi2Gehrels() self.est = Covariance() self.gro_fname = self.make_path('gro.txt') self.gro_delta_fname = self.make_path('gro_delta.txt') return
def setUp(self): try: from sherpa.astro.io import read_pha from sherpa.astro.xspec import XSwabs, XSpowerlaw except: return # self.startdir = os.getcwd() self.old_level = logger.getEffectiveLevel() logger.setLevel(logging.CRITICAL) pha = self.make_path("refake_0934_1_21_1e4.fak") # rmf = self.make_path("ccdid7_default.rmf") # arf = self.make_path("quiet_0934.arf") self.simarf = self.make_path("aref_sample.fits") self.pcaarf = self.make_path("aref_Cedge.fits") data = read_pha(pha) data.ignore(None, 0.3) data.ignore(7.0, None) rsp = Response1D(data) self.abs1 = XSwabs('abs1') self.p1 = XSpowerlaw('p1') model = rsp(self.abs1 * self.p1) self.fit = Fit(data, model, CStat(), NelderMead(), Covariance())
def fit(self, current): self._fit.model.thawedpars = current # nm = NelderMead() # nm.config['iquad'] = 0 # nm.config['finalsimplex'] = 1 #lm = LevMar() #lm.config['maxfev'] = 5 cv = Covariance() # Use the fit method defined before called get_draws(). This way the user # does not have to pass in the fitting method and method options. fit = Fit(self._fit.data, self._fit.model, self._fit.stat, self._fit.method, cv) fit_result = fit.fit() covar_result = fit.est_errors() sigma = np.array(covar_result.extra_output) if np.isnan(sigma).any(): raise CovarError("NaNs found in covariance matrix") # cache the fitting scales self._sigma = sigma
def setup(make_data_path): from sherpa.astro.io import read_pha from sherpa.astro.xspec import XSwabs, XSpowerlaw old_level = logger.getEffectiveLevel() logger.setLevel(logging.CRITICAL) pha = make_data_path("refake_0934_1_21_1e4.fak") simarf = make_data_path("aref_sample.fits") pcaarf = make_data_path("aref_Cedge.fits") data = read_pha(pha) data.ignore(None, 0.3) data.ignore(7.0, None) rsp = Response1D(data) abs1 = XSwabs('abs1') p1 = XSpowerlaw('p1') model = rsp(abs1 * p1) abs1.nh = 0.092886 p1.phoindex = 0.994544 p1.norm = 9.26369 fit = Fit(data, model, CStat(), NelderMead(), Covariance()) yield {'simarf': simarf, 'pcaarf': pcaarf, 'niter': 10, 'fit': fit} # Reset the logger logger.setLevel(old_level)
def setup(): data = Data1D('fake', _x, _y, _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) fit = Fit(data, model, Chi2DataVar(), method, Covariance()) results = fit.fit() for key in ["succeeded", "numpoints", "nfev"]: assert _fit_results_bench[key] == int(getattr(results, key)) for key in ["rstat", "qval", "statval", "dof"]: # used rel and abs tol of 1e-7 with numpy allclose assert float(getattr(results, key)) == pytest.approx(_fit_results_bench[key]) for key in ["parvals"]: try: # used rel and abs tol of 1e-4 with numpy allclose assert getattr(results, key) == pytest.approx(_fit_results_bench[key]) except AssertionError: print('parvals bench: ', _fit_results_bench[key]) print('parvals fit: ', getattr(results, key)) print('results', results) raise fields = [ 'data', 'model', 'method', 'fit', 'results', 'covresults', 'dof', 'mu', 'num' ] out = namedtuple('Results', fields) out.data = data out.model = model out.method = method out.fit = fit out.results = results out.covresults = fit.est_errors() out.dof = results.dof out.mu = numpy.array(results.parvals) out.cov = numpy.array(out.covresults.extra_output) out.num = 10 return out
def test_covar(self): standard = numpy.array([[ 0.4935702, 0.06857833, numpy.nan], [ 0.06857833, 0.26405554, numpy.nan], [ numpy.nan, numpy.nan, 2.58857314]]) results = Covariance().compute(stat, None, fittedpars, minpars, maxpars, hardminpars, hardmaxpars, limit_parnums, freeze_par, thaw_par, report_progress, get_par_name) self.assertEqualWithinTol(standard.diagonal(), # results[2].diagonal(), 1e-4) results[1], 1e-4)
def test_covar_failures(self): self.assertRaises(TypeError, Covariance().compute, None, fitter, fittedpars, minpars, maxpars, hardminpars, hardmaxpars, limit_parnums, freeze_par, thaw_par, report_progress) self.assertRaises(RuntimeError, Covariance().compute, stat, fitter, None, minpars, maxpars, hardminpars, hardmaxpars, limit_parnums, freeze_par, thaw_par, report_progress, get_par_name) self.assertRaises(RuntimeError, Covariance().compute, stat, fitter, numpy.array([1, 2]), minpars, maxpars, hardminpars, hardmaxpars, limit_parnums, freeze_par, thaw_par, report_progress, get_par_name) self.assertRaises(RuntimeError, Covariance().compute, stat, fitter, fittedpars, numpy.array([1, 2]), maxpars, hardminpars, hardmaxpars, limit_parnums, freeze_par, thaw_par, report_progress, get_par_name)
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
def get_scales(self, fit, myscales=None): def get_size_of_covar(pars): thawedpars = [par for par in pars if not par.frozen] npar = len(thawedpars) msg = 'scales must be a numpy array of size (%d,%d)' % (npar, npar) return npar, msg if myscales is None: oldestmethod = fit.estmethod fit.estmethod = Covariance() try: r = fit.est_errors() finally: fit.estmethod = oldestmethod cov = r.extra_output else: if isinstance(myscales, (numpy.ndarray)): npar, msg = get_size_of_covar(fit.model.pars) if (npar, npar) == myscales.shape: cov = myscales else: raise EstErr(msg) else: npar, msg = get_size_of_covar(fit.model.pars) raise EstErr(msg) cov = myscales if cov is None: raise EstErr('nocov') cov = numpy.asarray(cov) # Investigate spectral decomposition to avoid requirement that the cov be # semi-positive definite. Nevermind, NumPy already uses SVD to generate # deviates from a multivariate normal. An alternative is to use Cholesky # decomposition, but it assumes that the matrix is semi-positive # definite. if numpy.min(numpy.linalg.eigvalsh(cov)) <= 0: raise TypeError("The covariance matrix is not positive definite") return cov
) center = SkyCoord(83.633083, 22.0145, unit="deg").galactic source_model.gamma = 2.2 source_model.xpos = center.l.value source_model.ypos = center.b.value source_model.fwhm = 0.12 source_model.ampl = 1.0 # Define the model flux_factor = 1e-11 model = bkg + flux_factor * source_model fit = Fit( data=cube, model=model, stat=Cash(), method=NelderMead(), estmethod=Covariance(), ) fit_results = fit.fit() print(fit_results.format()) fit = Fit( data=cube, model=model, stat=Cash(), method=NelderMead(), estmethod=Covariance(), ) fit_results = fit.fit() fit_results fit_results.format() print(fit_results.format()) err_est_results = fit.est_errors()
def get_scales(self, fit, myscales=None): """Return the samples. Parameters ---------- fit : sherpa.fit.Fit instance This defines the thawed parameters that are used to generate the samples, along with any possible error analysis. myscales : numpy array or None, optional The scales to use. If None then they are calculated from the fit. Returns ------- scales : numpy array One-dimensional scales array (npar elements, matching the free parameters in fit). The values are the sigma errors for the parameters (or the input values if given). """ scales = [] thawedpars = [par for par in fit.model.pars if not par.frozen] if myscales is None: oldestmethod = fit.estmethod covar = Covariance() covar.config['sigma'] = self.sigma fit.estmethod = Covariance() try: r = fit.est_errors() finally: fit.estmethod = oldestmethod for par, val, lo, hi in zip(thawedpars, r.parvals, r.parmins, r.parmaxes): scale = None if lo is not None and hi is not None: scale = numpy.abs(lo) else: wmsg = "Covariance failed for '{}',".format(par.fullname) + \ " trying Confidence..." warning(wmsg) conf = Confidence() conf.config['sigma'] = self.sigma fit.estmethod = conf try: t = fit.est_errors(parlist=(par,)) if t.parmins[0] is not None and t.parmaxes[0] is not None: scale = numpy.abs(t.parmins[0]) else: if t.parmins[0] is None and t.parmaxes[0] is not None: scale = numpy.abs(t.parmaxes[0]) else: warning('1 sigma bounds for parameter ' + par.fullname + ' could not be found, using soft limit minimum') if 0.0 == numpy.abs(par.min): scale = 1.0e-16 else: scale = numpy.abs(par.min) finally: fit.estmethod = oldestmethod scales.append(scale) else: if not numpy.iterable(myscales): emsg = "scales option must be iterable of " + \ "length {}".format(len(thawedpars)) raise TypeError(emsg) scales = list(map(abs, myscales)) scales = numpy.asarray(scales).transpose() return scales
def get_scales(self, fit, myscales=None): """Return the samples. Parameters ---------- fit : sherpa.fit.Fit instance This defines the thawed parameters that are used to generate the samples, along with any possible error analysis. myscales : numpy array or None, optional The scales to use. If None then they are calculated from the fit. Returns ------- scales : numpy array Two-dimensional scales array (npar by npar elements, matching the free parameters in fit). The values are the covariance matrix for the parameters (or the input values if given). """ if myscales is None: oldestmethod = fit.estmethod fit.estmethod = Covariance() try: r = fit.est_errors() finally: fit.estmethod = oldestmethod cov = r.extra_output else: thawedpars = [par for par in fit.model.pars if not par.frozen] npar = len(thawedpars) msg = 'scales must be a numpy array of size ({0},{0})'.format(npar) if not isinstance(myscales, numpy.ndarray): raise EstErr(msg) if (npar, npar) != myscales.shape: raise EstErr(msg) cov = myscales if cov is None: raise EstErr('nocov') cov = numpy.asarray(cov) # Investigate spectral decomposition to avoid requirement that the cov be # semi-positive definite. Nevermind, NumPy already uses SVD to generate # deviates from a multivariate normal. An alternative is to use Cholesky # decomposition, but it assumes that the matrix is semi-positive # definite. if numpy.min(numpy.linalg.eigvalsh(cov)) <= 0: raise TypeError("The covariance matrix is not positive definite") return cov
def test_covar_failures1(): with pytest.raises(TypeError): Covariance().compute(None, fitter, fittedpars, minpars, maxpars, hardminpars, hardmaxpars, limit_parnums, freeze_par, thaw_par, report_progress)
def test_covar_failures4(): with pytest.raises(RuntimeError): Covariance().compute(stat, fitter, fittedpars, numpy.array([1, 2]), maxpars, hardminpars, hardmaxpars, limit_parnums, freeze_par, thaw_par, report_progress, get_par_name)
bkg = TableModel('bkg') bkg.load(None, bkg_3D.data[index_region_selected_3d].value.ravel()) # Freeze bkg amplitude bkg.ampl = 1 bkg.ampl.freeze() model = bkg + 1E-11 * (source_model_SgrA) # Fit # For now only Chi2 statistics seems to work, using Cash, the optimizer doesn't run at all, # maybe because of missing background model? fit = Fit(data=cube, model=model, stat=Cash(), method=NelderMead(), estmethod=Covariance()) result = fit.fit() err = fit.est_errors() print(err) # Set starting values G0p9 if "dec" in input_param["param_G0p9"]["sourde_name_skycoord"]: source_center_G0p9 = SkyCoord( input_param["param_G0p9"]["sourde_name_skycoord"]["ra"], input_param["param_G0p9"]["sourde_name_skycoord"]["dec"], unit="deg").galactic else: source_center_G0p9 = SkyCoord.from_name( input_param["param_G0p9"]["sourde_name_skycoord"]).galactic spatial_model_G0p9 = NormGauss2DInt('spatial-model_G0p9') spectral_model_G0p9 = PowLaw1D('spectral-model_G0p9')
def run(fit, null_comp, alt_comp, conv_mdl=None, stat=None, method=None, niter=500, numcores=None): if stat is None: stat = CStat() if method is None: method = NelderMead() if not isinstance(stat, (Cash, CStat)): raise TypeError("Sherpa fit statistic must be Cash or CStat" + " for likelihood ratio test") niter = int(niter) alt = alt_comp null = null_comp oldaltvals = numpy.array(alt.thawedpars) oldnullvals = numpy.array(null.thawedpars) data = fit.data if conv_mdl is not None: # Copy the PSF null_conv_mdl = deepcopy(conv_mdl) alt = conv_mdl(alt_comp) if hasattr(conv_mdl, 'fold'): conv_mdl.fold(data) # Convolve the null model null = null_conv_mdl(null_comp) if hasattr(null_conv_mdl, 'fold'): null_conv_mdl.fold(data) nullfit = Fit(data, null, stat, method, Covariance()) # Fit with null model nullfit_results = nullfit.fit() debug(nullfit_results.format()) null_stat = nullfit_results.statval null_vals = nullfit_results.parvals # Calculate niter samples using null best-fit and covariance sampler = NormalParameterSampleFromScaleMatrix() samples = sampler.get_sample(nullfit, None, niter) # Fit with alt model, null component starts at null's best fit params. altfit = Fit(data, alt, stat, method, Covariance()) altfit_results = altfit.fit() debug(altfit_results.format()) alt_stat = altfit_results.statval alt_vals = altfit_results.parvals LR = -(alt_stat - null_stat) def worker(proposal, *args, **kwargs): return LikelihoodRatioTest.calculate(nullfit, altfit, proposal, null_vals, alt_vals) olddep = data.get_dep(filter=False) try: #statistics = map(worker, samples) statistics = parallel_map(worker, samples, numcores) finally: data.set_dep(olddep) alt.thawedpars = list(oldaltvals) null.thawedpars = list(oldnullvals) debug("statistic null = " + repr(null_stat)) debug("statistic alt = " + repr(alt_stat)) debug("LR = " + repr(LR)) statistics = numpy.asarray(statistics) pppvalue = numpy.sum(statistics[:, 2] > LR) / (1.0 * niter) debug('ppp value = ' + str(pppvalue)) return LikelihoodRatioResults(statistics[:, 2], statistics[:, 0:2], samples, LR, pppvalue, null_stat, alt_stat)
def testCombinedModel3DInt(): from sherpa.models import PowLaw1D, TableModel from sherpa.estmethods import Covariance from sherpa.optmethods import NelderMead from sherpa.stats import Cash from sherpa.fit import Fit from ..sherpa_ import CombinedModel3DInt, NormGauss2DInt # Set the counts filename = gammapy_extra.filename('test_datasets/cube/counts_cube.fits') counts_3d = SkyCube.read(filename) cube = counts_3d.to_sherpa_data3d(dstype='Data3DInt') # Set the bkg filename = gammapy_extra.filename('test_datasets/cube/bkg_cube.fits') bkg_3d = SkyCube.read(filename) bkg = TableModel('bkg') bkg.load(None, bkg_3d.data.value.ravel()) bkg.ampl = 1 bkg.ampl.freeze() # Set the exposure filename = gammapy_extra.filename('test_datasets/cube/exposure_cube.fits') exposure_3d = SkyCube.read(filename) i_nan = np.where(np.isnan(exposure_3d.data)) exposure_3d.data[i_nan] = 0 # In order to have the exposure in cm2 s exposure_3d.data = exposure_3d.data * 1e4 # Set the mean psf model filename = gammapy_extra.filename('test_datasets/cube/psf_cube.fits') psf_3d = SkyCube.read(filename) # Setup combined spatial and spectral model spatial_model = NormGauss2DInt('spatial-model') spectral_model = PowLaw1D('spectral-model') coord = counts_3d.sky_image_ref.coordinates(mode="edges") energies = counts_3d.energies(mode='edges').to("TeV") source_model = CombinedModel3DInt(coord=coord, energies=energies, use_psf=True, exposure=exposure_3d, psf=psf_3d, spatial_model=spatial_model, spectral_model=spectral_model) # Set starting values center = SkyCoord(83.633083, 22.0145, unit="deg").galactic source_model.gamma = 2.2 source_model.xpos = center.l.value source_model.ypos = center.b.value source_model.fwhm = 0.12 source_model.ampl = 1.0 # Fit model = bkg + 1E-11 * (source_model) fit = Fit(data=cube, model=model, stat=Cash(), method=NelderMead(), estmethod=Covariance()) result = fit.fit() # TODO: The fact that it doesn't converge to the right Crab postion is due to the dummy psf reference = [ 184.19524957441664, -6.1693008203971562, 6.1666646581766011, 0.076340497278248376, 2.305912037549 ] assert_allclose(result.parvals, reference, rtol=1E-5) # Add a region to exclude in the fit: Here we will exclude some events from the Crab since there is no region to # exclude in the FOV for this example. It's just an example to show how it works and how to proceed in the fit. # Read the mask for the exclude region filename_mask = gammapy_extra.filename('test_datasets/cube/mask.fits') cube_mask = SkyCube.read(filename_mask) index_region_selected_3d = np.where(cube_mask.data.value == 1) # Set the counts and create a gammapy Data3DInt object on which we apply a mask for the region we don't want to use in the fit cube = counts_3d.to_sherpa_data3d(dstype='Data3DInt') cube.mask = cube_mask.data.value.ravel() # Set the bkg and select only the data points of the selected region bkg = TableModel('bkg') bkg.load(None, bkg_3d.data.value[index_region_selected_3d].ravel()) bkg.ampl = 1 bkg.ampl.freeze() # The model is evaluated on all the points then it is compared with the data only on the selected_region source_model = CombinedModel3DInt( coord=coord, energies=energies, use_psf=True, exposure=exposure_3d, psf=psf_3d, spatial_model=spatial_model, spectral_model=spectral_model, select_region=True, index_selected_region=index_region_selected_3d) # Set starting values source_model.gamma = 2.2 source_model.xpos = center.l.value source_model.ypos = center.b.value source_model.fwhm = 0.12 source_model.ampl = 1.0 # Fit model = bkg + 1E-11 * (source_model) fit = Fit(data=cube, model=model, stat=Cash(), method=NelderMead(), estmethod=Covariance()) result2 = fit.fit() # TODO: The fact that it doesn't converge to the right Crab postion is due to the dummy psf reference2 = [ 184.20146538191321, -6.1600047997645975, 5.4193056837212374, 0.08635929788659219, 2.2979723660330 ] assert_allclose(result2.parvals, reference2, rtol=1E-5)
def testCombinedModel3DIntConvolveEdisp(): from sherpa.models import PowLaw1D, TableModel from sherpa.estmethods import Covariance from sherpa.optmethods import NelderMead from sherpa.stats import Cash from sherpa.fit import Fit from ..sherpa_ import CombinedModel3DIntConvolveEdisp, NormGauss2DInt # Set the counts filename = gammapy_extra.filename('test_datasets/cube/counts_cube.fits') counts_3d = SkyCube.read(filename) cube = counts_3d.to_sherpa_data3d(dstype='Data3DInt') # Set the bkg filename = gammapy_extra.filename('test_datasets/cube/bkg_cube.fits') bkg_3d = SkyCube.read(filename) bkg = TableModel('bkg') bkg.load(None, bkg_3d.data.value.ravel()) bkg.ampl = 1 bkg.ampl.freeze() # Set the exposure filename = gammapy_extra.filename( 'test_datasets/cube/exposure_cube_etrue.fits') exposure_3d = SkyCube.read(filename) i_nan = np.where(np.isnan(exposure_3d.data)) exposure_3d.data[i_nan] = 0 # In order to have the exposure in cm2 s exposure_3d.data = exposure_3d.data * 1e4 # Set the mean psf model filename = gammapy_extra.filename('test_datasets/cube/psf_cube_etrue.fits') psf_3d = SkyCube.read(filename) # Set the mean rmf filename = gammapy_extra.filename('test_datasets/cube/rmf.fits') rmf = EnergyDispersion.read(filename) # Setup combined spatial and spectral model spatial_model = NormGauss2DInt('spatial-model') spectral_model = PowLaw1D('spectral-model') # dimensions = [exposure_3d.data.shape[1], exposure_3d.data.shape[2], rmf.data.data.shape[1], # exposure_3d.data.shape[0]] coord = counts_3d.sky_image_ref.coordinates(mode="edges") energies = counts_3d.energies(mode='edges').to("TeV") source_model = CombinedModel3DIntConvolveEdisp( coord=coord, energies=energies, use_psf=True, exposure=exposure_3d, psf=psf_3d, spatial_model=spatial_model, spectral_model=spectral_model, edisp=rmf.data.data) # Set starting values center = SkyCoord(83.633083, 22.0145, unit="deg").galactic source_model.gamma = 2.2 source_model.xpos = center.l.value source_model.ypos = center.b.value source_model.fwhm = 0.12 source_model.ampl = 1.0 # Fit model = bkg + 1E-11 * (source_model) fit = Fit(data=cube, model=model, stat=Cash(), method=NelderMead(), estmethod=Covariance()) result = fit.fit() # TODO: The fact that it doesn't converge to the right Crab postion, flux and source size is due to the dummy psf reference = [ 184.19189525423425, -6.1758238877562386, 6.2283155506945755, 0.071013932890499717, 2.2685809241308674 ] assert_allclose(result.parvals, reference, rtol=1E-5) # Add a region to exclude in the fit: Here we will exclude some events from the Crab since there is no region to # exclude in the FOV for this example. It's just an example to show how it works and how to proceed in the fit. # Read the mask for the exclude region filename_mask = gammapy_extra.filename('test_datasets/cube/mask.fits') cube_mask = SkyCube.read(filename_mask) index_region_selected_3d = np.where(cube_mask.data.value == 1) # Set the counts and create a gammapy Data3DInt object on which we apply a mask for the region we don't want to use in the fit cube = counts_3d.to_sherpa_data3d(dstype='Data3DInt') cube.mask = cube_mask.data.value.ravel() # Set the bkg and select only the data points of the selected region bkg = TableModel('bkg') bkg.load(None, bkg_3d.data.value[index_region_selected_3d].ravel()) bkg.ampl = 1 bkg.ampl.freeze() # The model is evaluated on all the points then it is compared with the data only on the selected_region source_model = CombinedModel3DIntConvolveEdisp( coord=coord, energies=energies, use_psf=True, exposure=exposure_3d, psf=psf_3d, spatial_model=spatial_model, spectral_model=spectral_model, edisp=rmf.data.data, select_region=True, index_selected_region=index_region_selected_3d) # Set starting values source_model.gamma = 2.2 source_model.xpos = center.l.value source_model.ypos = center.b.value source_model.fwhm = 0.12 source_model.ampl = 1.0 # Fit model = bkg + 1E-11 * (source_model) fit = Fit(data=cube, model=model, stat=Cash(), method=NelderMead(), estmethod=Covariance()) result2 = fit.fit() # TODO: The fact that it doesn't converge to the right Crab postion is due to the dummy psf reference2 = [ 184.1919580251583, -6.1692775561065769, 5.4976586957354581, 0.074821281329729109, 2.2504892463464699 ] assert_allclose(result2.parvals, reference2, rtol=1E-5)
# Adding this constant background components the fit works with cash statistics as well #spatial_model_bkg = Const2D('spatial-model-bkg') #spectral_model_bkg = PowLaw1D('spectral-model-bkg') #bkg_model = CombinedModel3D(spatial_model=spatial_model_bkg, spectral_model=spectral_model_bkg) bkg = TableModel('bkg') bkg.load(None, bkg_3D.data.value.ravel()) # Freeze bkg amplitude bkg.ampl=1 bkg.ampl.freeze() model = bkg+1E-11 * (source_model) # Fit # For now only Chi2 statistics seems to work, using Cash, the optimizer doesn't run at all, # maybe because of missing background model? fit = Fit(data=cube, model=model, stat=Cash(), method=NelderMead(), estmethod=Covariance()) result = fit.fit() err=fit.est_errors() print(err) def PWL(E,phi_0,gamma): return phi_0*E**(-gamma) def EXP(E,phi_0,gamma,beta): return phi_0*E**(-gamma)*np.exp(-beta*E) coord=exposure_3D.sky_image_ref.coordinates(mode="edges") d = coord.separation(center) pix_size=exposure_3D.wcs.to_header()["CDELT2"] i=np.where(d<pix_size*u.deg) #i permet de faire la moyenne exposure autour de pixel autour de la source mean_exposure=list()