Ejemplo n.º 1
0
                              1)  # misnomer ... this is really the integral
        self.r0 = Parameter(name, 'r0', 1, 0)
        self.width = Parameter(name, 'width', 0.1, 0)
        ArithmeticModel.__init__(
            self, name, (self.xpos, self.ypos, self.ampl, self.r0, self.width))

    def calc(self, p, x, y, *args, **kwargs):
        """Homogeneously emitting spherical shell,
        projected along the z-direction
        (this is not 100% correct for very large shells on the sky)."""
        xpos, ypos, ampl, r_0, width = p

        r2 = (x - xpos) * (x - xpos) + (y - ypos) * (y - ypos)
        r_out = r_0 + width
        r_in2, r_out2 = r_0 * r_0, r_out * r_out
        # r_in3, r_out3 = r_in * r_in2, r_out * r_out2
        # We only call abs() in sqrt() to avoid warning messages.
        sphere_out = np.sqrt(np.abs(r_out2 - r2))
        sphere_in = np.sqrt(np.abs(r_in2 - r2))
        # Note: for r > r_out 'np.select' fills automatically zeros!
        non_normalized = np.select([r2 <= r_in2, r2 <= r_out2],
                                   [sphere_out - sphere_in, sphere_out])
        # Computed with Mathematica:
        integral = 2 * np.pi / 3 * (r_out**3 - r_0**3)
        # integral = 1
        return ampl * non_normalized / integral


sau.add_model(normdisk2d)
sau.add_model(normshell2d)
Ejemplo n.º 2
0
        self.xpos = Parameter(name, 'xpos', 0)  # p[0]
        self.ypos = Parameter(name, 'ypos', 0)  # p[1]
        self.ampl = Parameter(name, 'ampl', 1)  # p[2]
        self.r0 = Parameter(name, 'r0', 1, 0)  # p[3]
        ArithmeticModel.__init__(self, name,
                                 (self.xpos, self.ypos, self.ampl, self.r0))

    def calc(self, p, x, y, *args, **kwargs):
        # Compute radii
        r2 = (x - p[0])**2 + (y - p[1])**2

        # Return ampl when r2 <= r0 else return 0
        return np.select([r2 <= p[3]**2], [p[2]])


sau.add_model(disk2d)


class shell2d(ArithmeticModel):
    def __init__(self, name='shell2d'):
        self.xpos = Parameter(name, 'xpos', 0)  # p[0]
        self.ypos = Parameter(name, 'ypos', 0)  # p[1]
        self.ampl = Parameter(name, 'ampl', 1)  # p[2]
        self.r0 = Parameter(name, 'r0', 1, 0)  # p[3]
        self.width = Parameter(name, 'width', 0.1, 0)
        ArithmeticModel.__init__(
            self, name, (self.xpos, self.ypos, self.ampl, self.r0, self.width))

    def calc(self, p, x, y, *args, **kwargs):
        """Homogeneously emitting spherical shell,
        projected along the z-direction
Ejemplo n.º 3
0
layer.

The added models are reported to the user using Sherpa's logger
at the logging.INFO level. If the model exists in Sherpa's XSPEC
module then we skip it here.

"""

import logging

from sherpa.astro import ui
from sherpa.astro import xspec

import xspeclmodels

logger = logging.getLogger('sherpa')

# For now process all models (including convolution style) the
# same way.
#
xsmodels = set([n for n in dir(xspec) if n.startswith('XS')])

for name in xspeclmodels.__all__:
    if not name.startswith('XS') or name in xsmodels:
        continue

    cls = getattr(xspeclmodels, name)
    ui.add_model(cls)

    logger.info("Adding XSPEC local model: {}".format(name.lower()))
Ejemplo n.º 4
0
        if self._cur_cache_key != cache_key:
            self._cached_vals = [None] * self._kt_array.size

            for i in range(self._kt_array.size):
                apec_params = [self._kt_array[i], abund, redshift, 1.]
                self._cached_vals[i] = _xspec.xsaped(apec_params, *args,
                                                     **kwargs)

            self._cur_cache_key = cache_key
            self._cached_vals = np.array(self._cached_vals).T

        scales = norm * self._kt_array**gfac
        return (self._cached_vals * scales).sum(axis=1)


ui.add_model(PowerLawApecDemModel)


def make_fixed_temp_multi_apec(kTs, name_template='apec%d', norm=None):
    """Create a model summing multiple APEC components at fixed temperatures.

    *kTs*
      An iterable of temperatures for the components, in keV.
    *name_template* = 'apec%d'
      A template to use for the names of each component; it is string-formatted
      with the 0-based component number as an argument.
    *norm* = None
      An initial normalization to be used for every component, or None to use
      the Sherpa default.
    Returns:
      A tuple ``(total_model, sub_models)``, where *total_model* is a Sherpa
Ejemplo n.º 5
0
        self.ypos = Parameter(name, 'ypos', 0)
        self.ampl = Parameter(name, 'ampl', 1) # misnomer ... this is really the integral
        self.r0 = Parameter(name, 'r0', 1, 0)
        self.width = Parameter(name, 'width', 0.1, 0)
        ArithmeticModel.__init__(self, name, (self.xpos, self.ypos, self.ampl, self.r0, self.width))
 
    def calc(self, p, x, y, *args, **kwargs):
        """Homogeneously emitting spherical shell,
        projected along the z-direction
        (this is not 100% correct for very large shells on the sky)."""
        xpos, ypos, ampl, r_0, width = p
 
        r2 = (x - xpos) * (x - xpos) + (y - ypos) * (y - ypos)
        r_out = r_0 + width
        r_in2, r_out2 = r_0 * r_0, r_out * r_out
        # r_in3, r_out3 = r_in * r_in2, r_out * r_out2
        # We only call abs() in sqrt() to avoid warning messages.
        sphere_out = np.sqrt(np.abs(r_out2 - r2))
        sphere_in = np.sqrt(np.abs(r_in2 - r2))
        # Note: for r > r_out 'np.select' fills automatically zeros!
        non_normalized = np.select([r2 <= r_in2, r2 <= r_out2],
                                   [sphere_out - sphere_in, sphere_out])
        # Computed with Mathematica:
        integral = 2 * np.pi / 3 * (r_out ** 3 - r_0 ** 3)
        # integral = 1
        return ampl * non_normalized / integral

 
sau.add_model(normdisk2d)
sau.add_model(normshell2d)
Ejemplo n.º 6
0
        ArithmeticModel.__init__(self, name,
                                 (self.xpos, self.ypos, self.ampl, self.fwhm))

    def set_wcs(self, wcs):
        self.wcs = wcs
        # We assume bins have the same size along x and y axis
        self.binsize = np.abs(self.wcs.wcs.cdelt[0])
        if self.wcs.wcs.ctype[0][0:4] == 'GLON':
            self.coordsys = 'galactic'
        elif self.wcs.wcs.ctype[0][0:2] == 'RA':
            self.coordsys = 'fk5'
            #        print self.coordsys

    def calc(self, p, xlo, xhi, ylo, yhi, *args, **kwargs):
        """
        The normgauss2dint model uses the error function to evaluate the
        the gaussian. This corresponds to an integration over bins.
        """

        return self.normgauss2d(p, xlo, xhi, ylo, yhi)

    def normgauss2d(self, p, xlo, xhi, ylo, yhi):
        sigma_erf = p[3] * fwhm_to_sigma_erf
        return p[2] / 4. * ((erf.calc.calc([1, p[0], sigma_erf], xhi) -
                             erf.calc.calc([1, p[0], sigma_erf], xlo)) *
                            (erf.calc.calc([1, p[1], sigma_erf], yhi) -
                             erf.calc.calc([1, p[1], sigma_erf], ylo)))


sau.add_model(NormGauss2DInt)