def make_psf(configuration):
    # The psf parameters in terms of the input parameters. To simulate the different pixel size
    # we set the sigma of the psf to be a multiple (according to the ratio input)
    # of the actual sigma in data pixel units.
    # This should correspond, when ratio>1 to the case when the PSF's resolution is bigger
    # than the image. If the ratio is 1 than they have the same pixel size.
    psf_sigma = configuration.psf_sigma * configuration.resolution_ratio
    psf_amplitude = configuration.psf_amplitude
    psf_position = configuration.psf_position

    # We model the PSF as a gaussian as well. Note we are using the psf_sigma variable,
    # that is the one which is scaled through the ration. In other terms, we are working in
    # units of Data Pixels to simulate the conditions of the bug, when the ratio != 1.
    psf, psf_x, psf_y = symmetric_gaussian_image(amplitude=psf_amplitude, sigma=psf_sigma,
                                                 position=psf_position, n_bins=configuration.psf_size)
    # Normalize PSF
    norm_psf = psf / psf.sum()

    cdelt = DATA_PIXEL_SIZE / configuration.resolution_ratio
    psf_wcs = WcsStub([cdelt, cdelt])

    # Create a Sherpa PSF model object using the psf arrays
    sherpa_kernel = DataIMG('kernel_data',
                            psf_x, psf_y, norm_psf,
                            shape=(configuration.psf_size, configuration.psf_size),
                            sky=psf_wcs
                            )

    psf_model = PSFModel('psf_model', kernel=sherpa_kernel)
    psf_model.norm = 1
    psf_model.origin = (psf_position + 1, psf_position + 1)

    return psf, psf_model
Beispiel #2
0
def make_data(data_class):
    """Create a test data object of the given class.

    Using a string means it is easier to support the various PHA
    "types" - eg basic, grouping, grouping+quality.

    """

    x0 = np.asarray([1, 3, 7, 12])
    y = np.asarray([2, 3, 4, 5])
    if data_class == "1d":
        return Data1D('x1', x0, y)

    if data_class == "1dint":
        return Data1DInt('xint1', x0, np.asarray([3, 5, 8, 15]), y)

    chans = np.arange(1, 5)
    if data_class == "pha":
        return DataPHA('pha', chans, y)

    # We want to provide PHA tests that check out the grouping and
    # quality handling (but it is not worth trying all different
    # variants), so we have "grp" for grouping and no quality [*], and
    # "qual" for grouping and quality.
    #
    # [*] by which I mean we have not called ignore_bad, not that
    # there is no quality array.
    #
    grp = np.asarray([1, -1, 1, 1])
    qual = np.asarray([0, 0, 2, 0])
    pha = DataPHA('pha', chans, y, grouping=grp, quality=qual)
    if data_class == "grp":
        return pha

    if data_class == "qual":
        pha.ignore_bad()
        return pha

    x0 = np.asarray([1, 2, 3] * 2)
    x1 = np.asarray([1, 1, 1, 2, 2, 2])
    y = np.asarray([2, 3, 4, 5, 6, 7])
    if data_class == "2d":
        return Data2D('x2', x0, x1, y, shape=(2, 3))

    if data_class == "2dint":
        return Data2DInt('xint2', x0, x1, x0 + 1, x1 + 1, y, shape=(2, 3))

    if data_class == "img":
        return DataIMG('img', x0, x1, y, shape=(2, 3))

    if data_class == "imgint":
        return DataIMGInt('imgi', x0, x1, x0 + 1, x1 + 1, y, shape=(2, 3))

    assert False
def make_image(configuration):
    source_position = configuration.source_position

    # The convolution of two gaussians is a gaussian with a stddev which is the sum
    # of those convolved, so we model the image as a Gaussian itself.
    image_sigma = sqrt(configuration.source_sigma ** 2 + configuration.psf_sigma ** 2)
    image_amplitude = configuration.source_amplitude * configuration.psf_amplitude
    image, image_x, image_y = symmetric_gaussian_image(amplitude=image_amplitude, sigma=image_sigma,
                                                       position=source_position, n_bins=configuration.image_size)

    data_image = DataIMG("image", image_x, image_y, image,
                         shape=(configuration.image_size, configuration.image_size),
                         sky=WcsStub([DATA_PIXEL_SIZE, DATA_PIXEL_SIZE])
                         )

    return data_image
Beispiel #4
0
    def get_kernel(self, data, subkernel=True):

        indep, dep, kshape, lo, hi = self._get_kernel_data(data, subkernel)

        # Use kernel data set WCS if available
        eqpos = getattr(self.kernel, 'eqpos', None)
        sky = getattr(self.kernel, 'sky', None)

        # If kernel is a model, use WCS from data if available
        if callable(self.kernel):
            eqpos = getattr(data, 'eqpos', None)
            sky = getattr(data, 'sky', None)

        dataset = None
        ndim = len(kshape)
        if ndim == 1:
            dataset = Data1D('kernel', indep[0], dep)

        elif ndim == 2:

            # Edit WCS to reflect the subkernel extraction in
            # physical coordinates.
            if (subkernel and sky is not None and lo is not None
                    and hi is not None):

                if (WCS is not None):
                    sky = WCS(sky.name, sky.type, sky.crval, sky.crpix - lo,
                              sky.cdelt, sky.crota, sky.epoch, sky.equinox)

                # FIXME: Support for WCS only (non-Chandra) coordinate
                # transformations?

            dataset = DataIMG('kernel',
                              indep[0],
                              indep[1],
                              dep,
                              kshape[::-1],
                              sky=sky,
                              eqpos=eqpos)
        else:
            raise PSFErr('ndim')

        return dataset
Beispiel #5
0
def make_test_image():
    """A simple image

    Note that normally you'd have logical axes of 1:31,
    1:21 here and then a WCS, but I've decided to number
    the axes differently (in physical units) as there is
    no requirement that the logical units are 1:nx/ny.
    """

    x1, x0 = np.mgrid[3830:3850, 4245:4275]

    # What is the ordering of shape? At the moment going for
    # NumPy style (ny, nx), but there is no credible documentation
    # (any documentation was added to describe the behavior we
    # have now).
    #
    shape = x0.shape

    x0 = x0.flatten()
    x1 = x1.flatten()
    y = np.ones(x0.size)
    return DataIMG('d', x0, x1, y, shape=shape)