Ejemplo n.º 1
0
def image_model_sherpa(exposure,
                       psf,
                       sources,
                       model_image,
                       overwrite):
    """Compute source model image with Sherpa.

    Inputs:

    * Source list (JSON file)
    * PSF (JSON file)
    * Exposure image (FITS file)

    Outputs:

    * Source model flux image (FITS file)
    * Source model excess image (FITS file)
    """
    import sherpa.astro.ui as sau
    from ..image.models.psf import Sherpa
    from ..image.models.utils import read_json

    log.info('Reading exposure: {0}'.format(exposure))
    # Note: We don't really need the exposure as data,
    # but this is a simple way to init the dataspace to the correct shape
    sau.load_data(exposure)
    sau.load_table_model('exposure', exposure)

    log.info('Reading PSF: {0}'.format(psf))
    Sherpa(psf).set()

    log.info('Reading sources: {0}'.format(sources))
    read_json(sources, sau.set_source)

    name = sau.get_source().name
    full_model = 'exposure * psf({})'.format(name)
    sau.set_full_model(full_model)

    log.info('Computing and writing model_image: {0}'.format(model_image))
    sau.save_model(model_image, clobber=overwrite)
    sau.clean()
    sau.delete_psf()
Ejemplo n.º 2
0
def sherpa_model_image(exposure, psf, sources, model_image, overwrite):
    """Compute source model image with Sherpa.

    Inputs:

    * Source list (JSON file)
    * PSF (JSON file)
    * Exposure image (FITS file)

    Outputs:

    * Source model flux image (FITS file)
    * Source model excess image (FITS file)
    """
    import logging
    logging.basicConfig(level=logging.DEBUG,
                        format='%(levelname)s - %(message)s')
    import sherpa.astro.ui as sau  # @UnresolvedImport
    from ..morphology.psf import Sherpa
    from ..morphology.utils import read_json

    logging.info('Reading exposure: {0}'.format(exposure))
    # Note: We don't really need the exposure as data,
    # but this is a simple way to init the dataspace to the correct shape
    sau.load_data(exposure)
    sau.load_table_model('exposure', exposure)

    logging.info('Reading PSF: {0}'.format(psf))
    Sherpa(psf).set()

    logging.info('Reading sources: {0}'.format(sources))
    read_json(sources, sau.set_source)

    name = sau.get_source().name
    full_model = 'exposure * psf({})'.format(name)
    sau.set_full_model(full_model)

    logging.info('Computing and writing model_image: {0}'.format(model_image))
    sau.save_model(model_image, clobber=overwrite)
Ejemplo n.º 3
0
# pure python verstion of single_gaussian_component_model.ipynb because this is faster
import sherpa.astro.ui as shp
import utils

shp.set_stat('cash')
shp.set_method('simplex')
shp.set_method_opt('verbose', 1)

utils.setup('numosaic_fin_combined_40-50keV.img')

utils.load_components('40-50 keV/bg 150-212.5.model')

# CHXE model
shp.set_full_model(psf(shp.gauss2d.chxe * emap) + bg * emap)

# inner radii chosen
for r in [20, 24, 28, 32]:
    # from KP15, (ra, dec) = (266.4172 deg, -29.00716 deg)
    # systematic shifting error = 6" = 2.4 px
    # ellip = .52
    # theta = 57 deg (from positive north)
    shp.set_par(chxe.xpos, 497.4, 497.4 - 4, 497.4 + 4)
    shp.set_par(chxe.ypos, 499.1, 499.1 - 4, 499.1 + 4)
    shp.set_par(chxe.fwhm, 30, 1, 200)
    shp.set_par(chxe.ellip, .5)
    shp.set_par(chxe.theta, -.9948)
    shp.set_par(chxe.ampl, 1e-5)
    shp.thaw(chxe.ellip, chxe.xpos, chxe.ypos)

    print(shp.get_model())
Ejemplo n.º 4
0
sh.set_method("simplex")

sh.load_image("analysis_3d/counts_2D.fits")
sh.set_coord("logical")

sh.load_table_model("expo", "analysis_3d/exposure_2D.fits")
sh.load_table_model("bkg", "analysis_3d/background_2D.fits")
sh.load_psf("psf", "analysis_3d/psf_2D.fits")


# In principle one might first want to fit the background amplitude. However the background estimation method already yields the correct normalization, so we freeze the background amplitude to unity instead of adjusting it. The (smoothed) residuals from this background model are then computed and shown.

# In[ ]:


sh.set_full_model(bkg)
bkg.ampl = 1
sh.freeze(bkg)


# In[ ]:


resid = Map.read("analysis_3d/counts_2D.fits")
resid.data = sh.get_data_image().y - sh.get_model_image().y
resid_smooth = resid.smooth(width=4)
resid_smooth.plot(add_cbar=True);


# ### Find and fit the brightest source
# We then find the position of the maximum in the (smoothed) residuals map, and fit a (symmetrical) Gaussian source with that initial position:
Ejemplo n.º 5
0
# In[53]:

import sherpa.astro.ui as sh
sh.set_stat("cash")
sh.set_method("simplex")
sh.load_image('../datasets/images/MSH15-52_counts.fits.gz')
sh.set_coord("logical")

sh.load_table_model("expo", "../datasets/images/MSH15-52_exposure.fits.gz")
sh.load_table_model("bkg", "../datasets/images/MSH15-52_background.fits.gz")
sh.load_psf("psf", "../datasets/images/MSH15-52_psf.fits.gz")

# In[54]:

sh.set_full_model(bkg)
bkg.ampl = 1
sh.freeze(bkg)

data = sh.get_data_image().y - sh.get_model_image().y
resid = SkyImage(data=data, wcs=ref_image.wcs)

resid_table = []  #Keep residual images in a list to show them later
resid_smo6 = resid.smooth(radius=6)
resid_smo6.plot(vmax=5, add_cbar=True)
resid_table.append(resid_smo6)

# In[55]:

maxcoord = resid_smo6.lookup_max()
maxpix = resid_smo6.wcs_skycoord_to_pixel(maxcoord[0])
Ejemplo n.º 6
0
    prefix += 'zfree_'
    parameters += [redshift]
    priors += [priorfuncs.create_uniform_prior_for(redshift)]

assert len(priors) == len(
    parameters), 'priors: %d parameters: %d' % (len(priors), len(parameters))

################
# set model
#    find background automatically using PCA method

print('setting source and background model ...')
set_model(id, model * galabso)
convmodel = get_model(id)
bkg_model = auto_background(id)
set_full_model(id, get_response(id)(model) + bkg_model * get_bkg_scale(id))
#plot_bkg_fit(id)

## we allow the background normalisation to be a free fitting parameter
p = bkg_model.pars[0]
p.max = p.val + 2
p.min = p.val - 2
parameters.append(p)
priors += [priorfuncs.create_uniform_prior_for(p)]

priorfunction = priorfuncs.create_prior_function(priors=priors)
assert not numpy.isnan(
    calc_stat(id)), 'NaN on calc_stat, probably a bad RMF/ARF file for PC'

print('running BXA ...')
Ejemplo n.º 7
0
    def fit(self):
        # try a PCA decomposition of this spectrum
        initial = self.decompose()
        ui.set_method('neldermead')
        bkgmodel = PCAModel('pca%s' % self.id, data=self.pca)
        self.bkgmodel = bkgmodel
        response = get_identity_response(self.id)
        convbkgmodel = response(bkgmodel)
        ui.set_bkg_full_model(self.id, convbkgmodel)
        for p, v in zip(bkgmodel.pars, initial):
            p.val = v
        srcmodel = ui.get_model(self.id)
        ui.set_full_model(self.id, srcmodel)
        initial_v = self.calc_bkg_stat()
        # print('before fit: stat: %s' % (initial_v))
        ui.fit_bkg(id=self.id)
        # print('fit: first full fit done')
        final = [p.val for p in ui.get_bkg_model(self.id).pars]
        # print('fit: parameters: %s' % (final))
        initial_v = self.calc_bkg_stat()
        # print('fit: stat: %s' % (initial_v))

        # lets try from zero
        # logf.info('fit: second full fit from zero')
        for p in bkgmodel.pars:
            p.val = 0
        ui.fit_bkg(id=self.id)
        initial_v0 = self.calc_bkg_stat()
        # logf.info('fit: parameters: %s' % (final))
        # logf.info('fit: stat: %s' % (initial_v0))

        # pick the better starting point
        if initial_v0 < initial_v:
            # logf.info('fit: using zero-fit')
            initial_v = initial_v0
            final = [p.val for p in ui.get_bkg_model(self.id).pars]
        else:
            # logf.info('fit: using decomposed-fit')
            for p, v in zip(bkgmodel.pars, final):
                p.val = v

        # start with the full fit and remove(freeze) parameters
        print('%d parameters, stat=%.2f' % (len(initial), initial_v))
        results = [(2 * len(final) + initial_v, final, len(final), initial_v)]
        for i in range(len(initial) - 1, 0, -1):
            bkgmodel.pars[i].val = 0
            bkgmodel.pars[i].freeze()
            ui.fit_bkg(id=self.id)
            final = [p.val for p in ui.get_bkg_model(self.id).pars]
            v = self.calc_bkg_stat()
            print('--> %d parameters, stat=%.2f' % (i, v))
            results.insert(0, (v + 2 * i, final, i, v))

        print()
        print('Background PCA fitting AIC results:')
        print('-----------------------------------')
        print()
        print('stat Ncomp AIC')
        for aic, params, nparams, val in results:
            print('%-05.1f %2d %-05.1f' % (val, nparams, aic))
        aic, final, nparams, val = min(results)
        for p, v in zip(bkgmodel.pars, final):
            p.val = v
        for i in range(nparams):
            bkgmodel.pars[i].thaw()

        print()
        print('Increasing parameters again...')
        # now increase the number of parameters again
        # results = [(aic, final, nparams, val)]
        last_aic, last_final, last_nparams, last_val = aic, final, nparams, val
        for i in range(last_nparams, len(bkgmodel.pars)):
            next_nparams = i + 1
            bkgmodel.pars[i].thaw()
            for p, v in zip(bkgmodel.pars, last_final):
                p.val = v
            ui.fit_bkg(id=self.id)
            next_final = [p.val for p in ui.get_bkg_model(self.id).pars]
            v = self.calc_bkg_stat()
            next_aic = v + 2 * next_nparams
            if next_aic < last_aic:  # accept
                print('%d parameters, aic=%.2f ** accepting' %
                      (next_nparams, next_aic))
                last_aic, last_final, last_nparams, last_val = next_aic, next_final, next_nparams, v
            else:
                print('%d parameters, aic=%.2f' % (next_nparams, next_aic))
            # stop if we are 3 parameters ahead what we needed
            if next_nparams >= last_nparams + 3:
                break

        print('Final choice: %d parameters, aic=%.2f' %
              (last_nparams, last_aic))
        # reset to the last good solution
        for p, v in zip(bkgmodel.pars, last_final):
            p.val = v

        last_model = convbkgmodel
        for i in range(10):
            print('Adding Gaussian#%d' % (i + 1))
            # find largest discrepancy
            ui.set_analysis(self.id, "ener", "rate")
            m = ui.get_bkg_fit_plot(self.id)
            y = m.dataplot.y.cumsum()
            z = m.modelplot.y.cumsum()
            diff_rate = np.abs(y - z)
            ui.set_analysis(self.id, "ener", "counts")
            m = ui.get_bkg_fit_plot(self.id)
            x = m.dataplot.x
            y = m.dataplot.y.cumsum()
            z = m.modelplot.y.cumsum()
            diff = np.abs(y - z)
            i = np.argmax(diff)
            energies = x
            e = x[i]
            print(
                'largest remaining discrepancy at %.3fkeV[%d], need %d counts'
                % (x[i], i, diff[i]))
            # e = x[i]
            power = diff_rate[i]
            # lets try to inject a gaussian there

            g = ui.xsgaussian('g_%d_%d' % (self.id, i))
            print('placing gaussian at %.2fkeV, with power %s' % (e, power))
            # we work in energy bins, not energy
            g.LineE.min = energies[0]
            g.LineE.max = energies[-1]
            g.LineE.val = e
            if i > len(diff) - 2:
                i = len(diff) - 2
            if i < 2:
                i = 2
            g.Sigma = (x[i + 1] - x[i - 1])
            g.Sigma.min = (x[i + 1] - x[i - 1]) / 3
            g.Sigma.max = x[-1] - x[0]
            g.norm.min = power * 1e-6
            g.norm.val = power
            convbkgmodel2 = response(g)
            next_model = last_model + convbkgmodel2
            ui.set_bkg_full_model(self.id, next_model)
            ui.fit_bkg(id=self.id)
            next_final = [p.val for p in ui.get_bkg_model(self.id).pars]
            next_nparams = len(next_final)
            v = self.calc_bkg_stat()
            next_aic = v + 2 * next_nparams
            print('with Gaussian:', next_aic,
                  '; change: %.1f (negative is good)' % (next_aic - last_aic))
            if next_aic < last_aic:
                print('accepting')
                last_model = next_model
                last_aic, last_final, last_nparams, last_val = next_aic, next_final, next_nparams, v
            else:
                print('not significant, rejecting')
                ui.set_bkg_full_model(self.id, last_model)
                for p, v in zip(last_model.pars, last_final):
                    p.val = v
                    if v == 0:  # the parameter was frozen.
                        ui.freeze(p)
                break

        self.cstat, self.dof = self.calc_bkg_stat(
            dof=True)  # Save the final cstat and dof (dof = ihi - ilo)
        self.filter_energy = ui.get_filter(
        )  # Save the filter for background fitting.
        ui.set_analysis('channel')
        ui.ignore()
        ui.notice(self.filter0)  # restore filter
        ui.set_analysis('energy')
Ejemplo n.º 8
0
sh.set_stat("cash")
sh.set_method("simplex")
sh.load_image("G300-0_test_counts.fits")
sh.set_coord("logical")

sh.load_table_model("expo", "G300-0_test_exposure.fits")
sh.load_table_model("bkg", "G300-0_test_background.fits")
sh.load_psf("psf", "G300-0_test_psf.fits")


# In principle one might first want to fit the background amplitude. However the background estimation method already yields the correct normalization, so we freeze the background amplitude to unity instead of adjusting it. The (smoothed) residuals from this background model are then computed and shown.

# In[3]:


sh.set_full_model(bkg)
bkg.ampl = 1
sh.freeze(bkg)

data = sh.get_data_image().y -  sh.get_model_image().y
resid = SkyImage(data=data, wcs=wcs)

resid_table = []  # Keep residual images in a list to show them later
resid_smo6 = resid.smooth(radius = 6)
resid_smo6.plot()
resid_table.append(resid_smo6)


# ### Find and fit the brightest source
# We then find the position of the maximum in the (smoothed) residuals map, and fit a (symmetrical) Gaussian source with that initial position: