Exemplo n.º 1
0
def test_sbinterpolatedimage():
    """Test that we can make SBInterpolatedImages from Images of various types, and convert back.
    """
    import time
    t1 = time.time()
    # for each type, try to make an SBInterpolatedImage, and check that when we draw an image from
    # that SBInterpolatedImage that it is the same as the original
    lan3 = galsim.Lanczos(3, True, 1.E-4)
    lan3_2d = galsim.InterpolantXY(lan3)

    ftypes = [np.float32, np.float64]
    ref_array = np.array([[0.01, 0.08, 0.07, 0.02], [0.13, 0.38, 0.52, 0.06],
                          [0.09, 0.41, 0.44, 0.09], [0.04, 0.11, 0.10, 0.01]])

    for array_type in ftypes:
        image_in = galsim.ImageView[array_type](ref_array.astype(array_type))
        np.testing.assert_array_equal(
            ref_array.astype(array_type),
            image_in.array,
            err_msg=
            "Array from input Image differs from reference array for type %s" %
            array_type)
        sbinterp = galsim.SBInterpolatedImage(image_in, lan3_2d, dx=1.0)
        test_array = np.zeros(ref_array.shape, dtype=array_type)
        image_out = galsim.ImageView[array_type](test_array, scale=1.0)
        sbinterp.draw(image_out.view())
        np.testing.assert_array_equal(
            ref_array.astype(array_type),
            image_out.array,
            err_msg=
            "Array from output Image differs from reference array for type %s"
            % array_type)

        # Lanczos doesn't quite get the flux right.  Wrong at the 5th decimal place.
        # Gary says that's expected -- Lanczos isn't technically flux conserving.
        # He applied the 1st order correction to the flux, but expect to be wrong at around
        # the 10^-5 level.
        # Anyway, Quintic seems to be accurate enough.
        quint = galsim.Quintic(1.e-4)
        quint_2d = galsim.InterpolantXY(quint)
        sbinterp = galsim.SBInterpolatedImage(image_in, quint_2d, dx=1.0)
        sbinterp.setFlux(1.)
        do_shoot(galsim.GSObject(sbinterp), image_out, "InterpolatedImage")

        # Test kvalues
        do_kvalue(galsim.GSObject(sbinterp), "InterpolatedImage")

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Exemplo n.º 2
0
    def __init__(self,
                 lam_over_r0=None,
                 fwhm=None,
                 interpolant=None,
                 oversampling=1.5,
                 flux=1.,
                 gsparams=None):

        # The FWHM of the Kolmogorov PSF is ~0.976 lambda/r0 (e.g., Racine 1996, PASP 699, 108).
        if lam_over_r0 is None:
            if fwhm is not None:
                lam_over_r0 = fwhm / 0.976
            else:
                raise TypeError(
                    "Either lam_over_r0 or fwhm must be specified for AtmosphericPSF"
                )
        else:
            if fwhm is None:
                fwhm = 0.976 * lam_over_r0
            else:
                raise TypeError(
                    "Only one of lam_over_r0 and fwhm may be specified for AtmosphericPSF"
                )
        # Set the lookup table sample rate via FWHM / 2 / oversampling (BARNEY: is this enough??)
        dx_lookup = .5 * fwhm / oversampling

        # Fold at 10 times the FWHM
        stepk_kolmogorov = np.pi / (10. * fwhm)

        # Odd array to center the interpolant on the centroid. Might want to pad this later to
        # make a nice size array for FFT, but for typical seeing, arrays will be very small.
        npix = 1 + 2 * (np.ceil(np.pi / stepk_kolmogorov)).astype(int)
        atmoimage = kolmogorov_psf_image(array_shape=(npix, npix),
                                         dx=dx_lookup,
                                         lam_over_r0=lam_over_r0,
                                         flux=flux)

        # Run checks on the interpolant and build default if None
        if interpolant is None:
            quintic = galsim.Quintic(tol=1e-4)
            self.interpolant = galsim.InterpolantXY(quintic)
        else:
            self.interpolant = galsim.utilities.convert_interpolant_to_2d(
                interpolant)

        # Then initialize the SBProfile
        GSObject.__init__(
            self,
            galsim.SBInterpolatedImage(atmoimage,
                                       xInterp=self.interpolant,
                                       dx=dx_lookup,
                                       gsparams=gsparams))

        # The above procedure ends up with a larger image than we really need, which
        # means that the default stepK value will be smaller than we need.
        # Thus, we call the function calculateStepK() to refine the value.
        self.SBProfile.calculateStepK()
        self.SBProfile.calculateMaxK()
Exemplo n.º 3
0
def test_Quintic_spline():
    """Test the spline tabulation of the k space Quintic interpolant.
    """
    import time
    t1 = time.time()
    interp = galsim.InterpolantXY(galsim.Quintic(tol=1.e-4))
    testobj = galsim.SBInterpolatedImage(image.view(), interp, dx=dx)
    testKvals = np.zeros(len(KXVALS))
    # Make test kValues
    for i in xrange(len(KXVALS)):
        posk = galsim.PositionD(KXVALS[i], KYVALS[i])
        testKvals[i] = np.abs(testobj.kValue(posk))
    # Compare with saved array
    refKvals = np.loadtxt(os.path.join(TESTDIR, "absfKQuintic_test.txt"))
    np.testing.assert_array_almost_equal(
        refKvals,
        testKvals,
        DECIMAL,
        err_msg="Spline-interpolated kValues do not match saved " +
        "data for k space Quintic interpolant.")
    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Exemplo n.º 4
0
def simReal(real_galaxy,
            target_PSF,
            target_pixel_scale,
            g1=0.0,
            g2=0.0,
            rotation_angle=None,
            rand_rotate=True,
            rng=None,
            target_flux=1000.0,
            image=None):
    """Function to simulate images (no added noise) from real galaxy training data.

    This function takes a RealGalaxy from some training set, and manipulates it as needed to 
    simulate a (no-noise-added) image from some lower-resolution telescope.  It thus requires a
    target PSF (which could be an image, or one of our base classes) that represents all PSF 
    components including the pixel response, and a target pixel scale.  

    The default rotation option is to impose a random rotation to make irrelevant any real shears 
    in the galaxy training data (optionally, the RNG can be supplied).  This default can be turned 
    off by setting `rand_rotate = False` or by requesting a specific rotation angle using the
    `rotation_angle` keyword, in which case `rand_rotate` is ignored.

    Optionally, the user can specify a shear (default 0).  Finally, they can specify a flux 
    normalization for the final image, default 1000.

    @param real_galaxy         The RealGalaxy object to use, not modified in generating the
                               simulated image.
    @param target_PSF          The target PSF, either one of our base classes or an ImageView/Image.
    @param target_pixel_scale  The pixel scale for the final image, in arcsec.
    @param g1                  First component of shear to impose (components defined with respect
                               to pixel coordinates), default `g1 = 0.`
    @param g2                  Second component of shear to impose, default `g2 = 0.`
    @param rotation_angle      Angle by which to rotate the galaxy (must be a galsim.Angle 
                               instance).
    @param rand_rotate         If `rand_rotate = True` (default) then impose a random rotation on 
                               the training galaxy; this is ignored if `rotation_angle` is set.
    @param rng                 A random number generator to use for selection of the random 
                               rotation angle. (optional, may be any kind of galsim.BaseDeviate 
                               or None)
    @param target_flux         The target flux in the output galaxy image, default 
                               `target_flux = 1000.`
    @param image               As with the GSObject.draw() function, if an image is provided,
                               then it will be used and returned.
                               If `image=None`, then an appropriately sized image will be created.
    @return A simulated galaxy image.  The input RealGalaxy is unmodified. 
    """
    # do some checking of arguments
    if not isinstance(real_galaxy, galsim.RealGalaxy):
        raise RuntimeError("Error: simReal requires a RealGalaxy!")
    for Class in galsim.Image.itervalues():
        if isinstance(target_PSF, Class):
            lan5 = galsim.Lanczos(5, conserve_flux=True, tol=1.e-4)
            interp2d = galsim.InterpolantXY(lan5)
            target_PSF = galsim.SBInterpolatedImage(target_PSF.view(),
                                                    xInterp=interp2d,
                                                    dx=target_pixel_scale)
            break
    for Class in galsim.ImageView.itervalues():
        if isinstance(target_PSF, Class):
            lan5 = galsim.Lanczos(5, conserve_flux=True, tol=1.e-4)
            interp2d = galsim.InterpolantXY(lan5)
            target_PSF = galsim.SBInterpolatedImage(target_PSF,
                                                    xInterp=interp2d,
                                                    dx=target_pixel_scale)
            break
    if isinstance(target_PSF, galsim.GSObject):
        target_PSF = target_PSF.SBProfile
    if not isinstance(target_PSF, galsim.SBProfile):
        raise RuntimeError(
            "Error: target PSF is not an Image, ImageView, SBProfile, or GSObject!"
        )
    if rotation_angle != None and not isinstance(rotation_angle, galsim.Angle):
        raise RuntimeError(
            "Error: specified rotation angle is not an Angle instance!")
    if (target_pixel_scale < real_galaxy.pixel_scale):
        import warnings
        message = "Warning: requested pixel scale is higher resolution than original!"
        warnings.warn(message)
    import math  # needed for pi, sqrt below
    g = math.sqrt(g1**2 + g2**2)
    if g > 1:
        raise RuntimeError("Error: requested shear is >1!")

    # make sure target PSF is normalized
    target_PSF.setFlux(1.0)

    real_galaxy_copy = real_galaxy.copy()

    # rotate
    if rotation_angle != None:
        real_galaxy_copy.applyRotation(rotation_angle)
    elif rotation_angle == None and rand_rotate == True:
        if rng == None:
            uniform_deviate = galsim.UniformDeviate()
        elif isinstance(rng, galsim.BaseDeviate):
            uniform_deviate = galsim.UniformDeviate(rng)
        else:
            raise TypeError(
                "The rng provided to drawShoot is not a BaseDeviate")
        rand_angle = galsim.Angle(math.pi * uniform_deviate(), galsim.radians)
        real_galaxy_copy.applyRotation(rand_angle)

    # set fluxes
    real_galaxy_copy.setFlux(target_flux)

    # shear
    if (g1 != 0.0 or g2 != 0.0):
        real_galaxy_copy.applyShear(g1=g1, g2=g2)

    # convolve, resample
    out_gal = galsim.Convolve([real_galaxy_copy, galsim.GSObject(target_PSF)])
    image = out_gal.draw(image=image, dx=target_pixel_scale)

    # return simulated image
    return image
Exemplo n.º 5
0
    def __init__(self,
                 real_galaxy_catalog,
                 index=None,
                 id=None,
                 random=False,
                 rng=None,
                 x_interpolant=None,
                 k_interpolant=None,
                 flux=None,
                 pad_factor=0,
                 noise_pad=False,
                 pad_image=None,
                 use_cache=True,
                 gsparams=None):

        import pyfits
        import numpy as np

        # Code block below will be for galaxy selection; not all are currently implemented.  Each
        # option must return an index within the real_galaxy_catalog.
        if index is not None:
            if id is not None or random is True:
                raise AttributeError(
                    'Too many methods for selecting a galaxy!')
            use_index = index
        elif id is not None:
            if random is True:
                raise AttributeError(
                    'Too many methods for selecting a galaxy!')
            use_index = real_galaxy_catalog._get_index_for_id(id)
        elif random is True:
            if rng is None:
                uniform_deviate = galsim.UniformDeviate()
            elif isinstance(rng, galsim.BaseDeviate):
                uniform_deviate = galsim.UniformDeviate(rng)
            else:
                raise TypeError(
                    "The rng provided to RealGalaxy constructor is not a BaseDeviate"
                )
            use_index = int(real_galaxy_catalog.nobjects * uniform_deviate())
        else:
            raise AttributeError('No method specified for selecting a galaxy!')

        # read in the galaxy, PSF images; for now, rely on pyfits to make I/O errors. Should
        # consider exporting this code into fits.py in some function that takes a filename and HDU,
        # and returns an ImageView

        gal_image = real_galaxy_catalog.getGal(use_index)
        PSF_image = real_galaxy_catalog.getPSF(use_index)

        # choose proper interpolant
        if x_interpolant is None:
            lan5 = galsim.Lanczos(5, conserve_flux=True, tol=1.e-4)
            self.x_interpolant = galsim.InterpolantXY(lan5)
        else:
            self.x_interpolant = galsim.utilities.convert_interpolant_to_2d(
                x_interpolant)
        if k_interpolant is None:
            self.k_interpolant = galsim.InterpolantXY(
                galsim.Quintic(tol=1.e-4))
        else:
            self.k_interpolant = galsim.utilities.convert_interpolant_to_2d(
                k_interpolant)

        # read in data about galaxy from FITS binary table; store as normal attributes of RealGalaxy

        # save any other relevant information as instance attributes
        self.catalog_file = real_galaxy_catalog.file_name
        self.index = use_index
        self.pixel_scale = float(real_galaxy_catalog.pixel_scale[use_index])

        # handle padding by an image
        specify_size = False
        padded_size = gal_image.getPaddedSize(pad_factor)
        if pad_image is not None:
            specify_size = True
            if isinstance(pad_image, str):
                pad_image = galsim.fits.read(pad_image)
            if (not isinstance(pad_image, galsim.BaseImageF)
                    and not isinstance(pad_image, galsim.BaseImageD)):
                raise ValueError(
                    "Supplied pad_image is not one of the allowed types!")
            # If an image was supplied directly or from a file, check its size:
            #    Cannot use if too small.
            #    Use to define the final image size otherwise.
            deltax = ((1 + pad_image.getXMax() - pad_image.getXMin()) -
                      (1 + gal_image.getXMax() - gal_image.getXMin()))
            deltay = ((1 + pad_image.getYMax() - pad_image.getYMin()) -
                      (1 + gal_image.getYMax() - gal_image.getYMin()))
            if deltax < 0 or deltay < 0:
                raise RuntimeError("Image supplied for padding is too small!")
            if pad_factor != 1. and pad_factor != 0.:
                import warnings
                msg = "Warning: ignoring specified pad_factor because user also specified\n"
                msg += "         an image to use directly for the padding."
                warnings.warn(msg)
        else:
            if isinstance(gal_image, galsim.BaseImageF):
                pad_image = galsim.ImageF(padded_size, padded_size)
            if isinstance(gal_image, galsim.BaseImageD):
                pad_image = galsim.ImageD(padded_size, padded_size)

        # Set up the GaussianDeviate if not provided one, or check that the user-provided one
        # is of a valid type.  Note if random was selected, we can use that uniform_deviate safely.
        if random is True:
            gaussian_deviate = galsim.GaussianDeviate(uniform_deviate)
        else:
            if rng is None:
                gaussian_deviate = galsim.GaussianDeviate()
            elif isinstance(rng, galsim.BaseDeviate):
                # Even if it's already a GaussianDeviate, we still want to make a new Gaussian
                # deviate that would generate the same sequence, because later we change the sigma
                # and we don't want to change it for the original one that was passed in.  So don't
                # distinguish between GaussianDeviate and the other BaseDeviates here.
                gaussian_deviate = galsim.GaussianDeviate(rng)
            else:
                raise TypeError(
                    "rng provided to RealGalaxy constructor is not a BaseDeviate"
                )

        # handle noise-padding options
        try:
            noise_pad = galsim.config.value._GetBoolValue(noise_pad, '')
        except:
            pass
        if noise_pad:
            self.pad_variance = float(real_galaxy_catalog.variance[use_index])

            # Check, is it "True" or something else?  If True, we use Gaussian uncorrelated noise
            # using the stored variance in the catalog.  Otherwise, if it's a CorrelatedNoise we use
            # it directly; if it's an Image of some sort we use it to make a CorrelatedNoise; if
            # it's a string, we read in the image from file and make a CorrelatedNoise.
            if type(noise_pad) is not bool:
                if isinstance(noise_pad,
                              galsim.correlatednoise._BaseCorrelatedNoise):
                    cn = noise_pad.copy()
                    if rng:  # Let user supplied RNG take precedence over that in user CN
                        cn.setRNG(gaussian_deviate)
                    # This small patch may have different overall variance, so rescale while
                    # preserving the correlation structure by default
                    cn.setVariance(self.pad_variance)
                elif (isinstance(noise_pad, galsim.BaseImageF)
                      or isinstance(noise_pad, galsim.BaseImageD)):
                    cn = galsim.CorrelatedNoise(gaussian_deviate, noise_pad)
                elif use_cache and noise_pad in RealGalaxy._cache_noise_pad:
                    cn = RealGalaxy._cache_noise_pad[noise_pad]
                    # Make sure that we are using the desired RNG by resetting that in this cached
                    # CorrelatedNoise instance
                    if rng:
                        cn.setRNG(gaussian_deviate)
                    # This small patch may have different overall variance, so rescale while
                    # preserving the correlation structure
                    cn.setVariance(self.pad_variance)
                elif isinstance(noise_pad, str):
                    tmp_img = galsim.fits.read(noise_pad)
                    cn = galsim.CorrelatedNoise(gaussian_deviate, tmp_img)
                    if use_cache:
                        RealGalaxy._cache_noise_pad[noise_pad] = cn
                    # This small patch may have different overall variance, so rescale while
                    # preserving the correlation structure
                    cn.setVariance(self.pad_variance)
                else:
                    raise RuntimeError(
                        "noise_pad must be either a bool, CorrelatedNoise, Image, "
                        + "or a filename for reading in an Image")

            # Set the GaussianDeviate sigma
            gaussian_deviate.setSigma(np.sqrt(self.pad_variance))

            # populate padding image with noise field
            if type(noise_pad) is bool:
                pad_image.addNoise(galsim.DeviateNoise(gaussian_deviate))
            else:
                pad_image.addNoise(cn)
        else:
            self.pad_variance = 0.

        # Now we have to check: was the padding determined using pad_factor?  Or by passing in an
        # image for padding?  Treat these cases differently:
        # (1) If the former, then we can simply have the C++ handle the padding process.
        # (2) If the latter, then we have to do the padding ourselves, and pass the resulting image
        # to the C++ with pad_factor explicitly set to 1.
        if specify_size is False:
            # Make the SBInterpolatedImage out of the image.
            self.original_image = galsim.SBInterpolatedImage(
                gal_image,
                xInterp=self.x_interpolant,
                kInterp=self.k_interpolant,
                dx=self.pixel_scale,
                pad_factor=pad_factor,
                pad_image=pad_image,
                gsparams=gsparams)
        else:
            # Leave the original image as-is.  Instead, we shift around the image to be used for
            # padding.  Find out how much x and y margin there should be on lower end:
            x_marg = int(np.round(0.5 * deltax))
            y_marg = int(np.round(0.5 * deltay))
            # Now reset the pad_image to contain the original image in an even way
            pad_image = pad_image.view()
            pad_image.setScale(self.pixel_scale)
            pad_image.setOrigin(gal_image.getXMin() - x_marg,
                                gal_image.getYMin() - y_marg)
            # Set the central values of pad_image to be equal to the input image
            pad_image[gal_image.bounds] = gal_image
            self.original_image = galsim.SBInterpolatedImage(
                pad_image,
                xInterp=self.x_interpolant,
                kInterp=self.k_interpolant,
                dx=self.pixel_scale,
                pad_factor=1.,
                gsparams=gsparams)

        # also make the original PSF image, with far less fanfare: we don't need to pad with
        # anything interesting.
        self.original_PSF = galsim.SBInterpolatedImage(
            PSF_image,
            xInterp=self.x_interpolant,
            kInterp=self.k_interpolant,
            dx=self.pixel_scale,
            gsparams=gsparams)

        # recalculate Fourier-space attributes rather than using overly-conservative defaults
        self.original_image.calculateStepK()
        self.original_image.calculateMaxK()
        self.original_PSF.calculateStepK()
        self.original_PSF.calculateMaxK()

        if flux != None:
            self.original_image.setFlux(flux)
            self.original_image.__class__ = galsim.SBTransform  # correctly reflect SBProfile change
        self.original_PSF.setFlux(1.0)
        self.original_PSF.__class__ = galsim.SBTransform  # correctly reflect SBProfile change

        # Calculate the PSF "deconvolution" kernel
        psf_inv = galsim.SBDeconvolve(self.original_PSF, gsparams=gsparams)
        # Initialize the SBProfile attribute
        GSObject.__init__(
            self,
            galsim.SBConvolve([self.original_image, psf_inv],
                              gsparams=gsparams))
g2.applyShear(-0.4,0.3)
g2.applyShift(-0.3,0.5)
g3 = galsim.Gaussian(sigma = 4.1, flux=1.6)
g3.applyShear(0.1,-0.1)
g3.applyShift(0.7,-0.2)

final = g1 + g2 + g3
image = galsim.ImageD(128,128)
dx = 0.4
final.draw(image=image, dx=dx)

dir = '../../../tests/interpolant_comparison_files'

# First make a Cubic interpolant
interp = galsim.InterpolantXY(galsim.Cubic(tol=1.e-4))
testobj = galsim.SBInterpolatedImage(image.view(), interp, dx=dx)
for i in xrange(len(kxvals)):
    posk = galsim.PositionD(kxvals[i], kyvals[i])
    absoutk[i] = np.abs(testobj.kValue(posk))
print absoutk
np.savetxt(os.path.join(dir,'absfKCubic_test.txt'), absoutk)

# Then make a Quintic interpolant
interp = galsim.InterpolantXY(galsim.Quintic(tol=1.e-4))
testobj = galsim.SBInterpolatedImage(image.view(), interp, dx=dx)
for i in xrange(len(kxvals)):
    posk = galsim.PositionD(kxvals[i], kyvals[i])
    absoutk[i] = np.abs(testobj.kValue(posk))
print absoutk
np.savetxt(os.path.join(dir,'absfKQuintic_test.txt'), absoutk)
Exemplo n.º 7
0
    def __init__(self, image, x_interpolant = None, k_interpolant = None, normalization = 'flux',
                 dx = None, flux = None, pad_factor = 0., noise_pad = 0., rng = None,
                 pad_image = None, calculate_stepk=True, calculate_maxk=True,
                 use_cache=True, use_true_center=True, gsparams=None):

        import numpy as np

        # first try to read the image as a file.  If it's not either a string or a valid
        # pyfits hdu or hdulist, then an exception will be raised, which we ignore and move on.
        try:
            image = galsim.fits.read(image)
        except:
            pass

        # make sure image is really an image and has a float type
        if not isinstance(image, galsim.BaseImageF) and not isinstance(image, galsim.BaseImageD):
            raise ValueError("Supplied image is not an image of floats or doubles!")

        # it must have well-defined bounds, otherwise seg fault in SBInterpolatedImage constructor
        if not image.getBounds().isDefined():
            raise ValueError("Supplied image does not have bounds defined!")

        # check what normalization was specified for the image: is it an image of surface
        # brightness, or flux?
        if not normalization.lower() in ("flux", "f", "surface brightness", "sb"):
            raise ValueError(("Invalid normalization requested: '%s'. Expecting one of 'flux', "+
                              "'f', 'surface brightness', or 'sb'.") % normalization)

        # set up the interpolants if none was provided by user, or check that the user-provided ones
        # are of a valid type
        if x_interpolant is None:
            self.x_interpolant = galsim.InterpolantXY(galsim.Quintic(tol=1e-4))
        else:
            self.x_interpolant = galsim.utilities.convert_interpolant_to_2d(x_interpolant)
        if k_interpolant is None:
            self.k_interpolant = galsim.InterpolantXY(galsim.Quintic(tol=1e-4))
        else:
            self.k_interpolant = galsim.utilities.convert_interpolant_to_2d(k_interpolant)

        # Check for input dx, and check whether Image already has one set.  At the end of this
        # code block, either an exception will have been raised, or the input image will have a
        # valid scale set.
        if dx is None:
            dx = image.scale
            if dx == 0:
                raise ValueError("No information given with Image or keywords about pixel scale!")
        else:
            if type(dx) != float:
                dx = float(dx)
            # Don't change the original image.  Make a new view if we need to set the scale.
            image = image.view()
            image.setScale(dx)
            if dx == 0.0:
                raise ValueError("dx may not be 0.0")

        # Set up the GaussianDeviate if not provided one, or check that the user-provided one is
        # of a valid type.
        if rng is None:
            gaussian_deviate = galsim.GaussianDeviate()
        elif isinstance(rng, galsim.BaseDeviate):
            # Even if it's already a GaussianDeviate, we still want to make a new Gaussian deviate
            # that would generate the same sequence, because later we change the sigma and we don't
            # want to change it for the original one that was passed in.  So don't distinguish
            # between GaussianDeviate and the other BaseDeviates here.
            gaussian_deviate = galsim.GaussianDeviate(rng)
        else:
            raise TypeError("rng provided to InterpolatedImage constructor is not a BaseDeviate")

        # decide about deterministic image padding
        specify_size = False
        padded_size = image.getPaddedSize(pad_factor)
        if pad_image:
            specify_size = True
            if isinstance(pad_image, str):
                pad_image = galsim.fits.read(pad_image)
            if ( not isinstance(pad_image, galsim.BaseImageF) and 
                 not isinstance(pad_image, galsim.BaseImageD) ):
                raise ValueError("Supplied pad_image is not one of the allowed types!")

            # If an image was supplied directly or from a file, check its size:
            #    Cannot use if too small.
            #    Use to define the final image size otherwise.
            deltax = (1+pad_image.getXMax()-pad_image.getXMin())-(1+image.getXMax()-image.getXMin())
            deltay = (1+pad_image.getYMax()-pad_image.getYMin())-(1+image.getYMax()-image.getYMin())
            if deltax < 0 or deltay < 0:
                raise RuntimeError("Image supplied for padding is too small!")
            if pad_factor != 1. and pad_factor != 0.:
                import warnings
                msg =  "Warning: ignoring specified pad_factor because user also specified\n"
                msg += "         an image to use directly for the padding."
                warnings.warn(msg)
        elif noise_pad:
            if isinstance(image, galsim.BaseImageF):
                pad_image = galsim.ImageF(padded_size, padded_size)
            if isinstance(image, galsim.BaseImageD):
                pad_image = galsim.ImageD(padded_size, padded_size)

        # now decide about noise padding
        # First, see if the input is consistent with a float.
        # i.e. it could be an int, or a str that converts to a number.
        try:
            noise_pad = float(noise_pad)
        except:
            pass
        if isinstance(noise_pad, float):
            if noise_pad < 0.:
                raise ValueError("Noise variance cannot be negative!")
            elif noise_pad > 0.:
                # Note: make sure the sigma is properly set to sqrt(noise_pad).
                gaussian_deviate.setSigma(np.sqrt(noise_pad))
                pad_image.addNoise(galsim.DeviateNoise(gaussian_deviate))
        else:
            if isinstance(noise_pad, galsim.correlatednoise._BaseCorrelatedNoise):
                cn = noise_pad.copy()
                if rng: # Let a user supplied RNG take precedence over that in user CN
                    cn.setRNG(gaussian_deviate)
            elif isinstance(noise_pad,galsim.BaseImageF) or isinstance(noise_pad,galsim.BaseImageD):
                cn = galsim.CorrelatedNoise(gaussian_deviate, noise_pad)
            elif use_cache and noise_pad in InterpolatedImage._cache_noise_pad:
                cn = InterpolatedImage._cache_noise_pad[noise_pad]
                if rng:
                    # Make sure that we are using a specified RNG by resetting that in this cached
                    # CorrelatedNoise instance, otherwise preserve the cached RNG
                    cn.setRNG(gaussian_deviate)
            elif isinstance(noise_pad, str):
                cn = galsim.CorrelatedNoise(gaussian_deviate, galsim.fits.read(noise_pad))
                if use_cache: 
                    InterpolatedImage._cache_noise_pad[noise_pad] = cn
            else:
                raise ValueError(
                    "Input noise_pad must be a float/int, a CorrelatedNoise, Image, or filename "+
                    "containing an image to use to make a CorrelatedNoise!")
            pad_image.addNoise(cn)

        # Now we have to check: was the padding determined using pad_factor?  Or by passing in an
        # image for padding?  Treat these cases differently:
        # (1) If the former, then we can simply have the C++ handle the padding process.
        # (2) If the latter, then we have to do the padding ourselves, and pass the resulting image
        # to the C++ with pad_factor explicitly set to 1.
        if specify_size is False:
            # Make the SBInterpolatedImage out of the image.
            sbinterpolatedimage = galsim.SBInterpolatedImage(
                    image, xInterp=self.x_interpolant, kInterp=self.k_interpolant,
                    dx=dx, pad_factor=pad_factor, pad_image=pad_image, gsparams=gsparams)
            self.x_size = padded_size
            self.y_size = padded_size
        else:
            # Leave the original image as-is.  Instead, we shift around the image to be used for
            # padding.  Find out how much x and y margin there should be on lower end:
            x_marg = int(np.round(0.5*deltax))
            y_marg = int(np.round(0.5*deltay))
            # Now reset the pad_image to contain the original image in an even way
            pad_image = pad_image.view()
            pad_image.setScale(dx)
            pad_image.setOrigin(image.getXMin()-x_marg, image.getYMin()-y_marg)
            # Set the central values of pad_image to be equal to the input image
            pad_image[image.bounds] = image
            sbinterpolatedimage = galsim.SBInterpolatedImage(
                    pad_image, xInterp=self.x_interpolant, kInterp=self.k_interpolant,
                    dx=dx, pad_factor=1., gsparams=gsparams)
            self.x_size = 1+pad_image.getXMax()-pad_image.getXMin()
            self.y_size = 1+pad_image.getYMax()-pad_image.getYMin()

        # GalSim cannot automatically know what stepK and maxK are appropriate for the 
        # input image.  So it is usually worth it to do a manual calculation here.
        if calculate_stepk:
            sbinterpolatedimage.calculateStepK()
        if calculate_maxk:
            sbinterpolatedimage.calculateMaxK()

        # If the user specified a flux, then set to that flux value.
        if flux != None:
            if type(flux) != flux:
                flux = float(flux)
            sbinterpolatedimage.setFlux(flux)
        # If the user specified a flux normalization for the input Image, then since
        # SBInterpolatedImage works in terms of surface brightness, have to rescale the values to
        # get proper normalization.
        elif flux is None and normalization.lower() in ['flux','f'] and dx != 1.:
            sbinterpolatedimage.scaleFlux(1./(dx**2))
        # If the input Image normalization is 'sb' then since that is the SBInterpolated default
        # assumption, no rescaling is needed.

        # Initialize the SBProfile
        GSObject.__init__(self, sbinterpolatedimage)

        # Fix the center to be in the right place.
        # Note the minus sign in front of image.scale, since we want to fix the center in the 
        # opposite sense of what the draw function does.
        if use_true_center:
            prof = self._fix_center(image, -image.scale)
            GSObject.__init__(self, prof.SBProfile)
Exemplo n.º 8
0
    def __init__(self,
                 lam_over_diam,
                 defocus=0.,
                 astig1=0.,
                 astig2=0.,
                 coma1=0.,
                 coma2=0.,
                 trefoil1=0.,
                 trefoil2=0.,
                 spher=0.,
                 circular_pupil=True,
                 obscuration=0.,
                 interpolant=None,
                 oversampling=1.5,
                 pad_factor=1.5,
                 flux=1.,
                 gsparams=None):

        # Currently we load optics, noise etc in galsim/__init__.py, but this might change (???)
        import galsim.optics

        # Choose dx for lookup table using Nyquist for optical aperture and the specified
        # oversampling factor
        dx_lookup = .5 * lam_over_diam / oversampling

        # We need alias_threshold here, so don't wait to make this a default GSParams instance
        # if the user didn't specify anything else.
        if not gsparams:
            gsparams = galsim.GSParams()

        # Use a similar prescription as SBAiry to set Airy stepK and thus reference unpadded image
        # size in physical units
        stepk_airy = min(
            gsparams.alias_threshold * .5 * np.pi**3 * (1. - obscuration) /
            lam_over_diam, np.pi / 5. / lam_over_diam)

        # Boost Airy image size by a user-specifed pad_factor to allow for larger, aberrated PSFs,
        # also make npix always *odd* so that opticalPSF lookup table array is correctly centred:
        npix = 1 + 2 * (np.ceil(pad_factor *
                                (np.pi / stepk_airy) / dx_lookup)).astype(int)

        # Make the psf image using this dx and array shape
        optimage = galsim.optics.psf_image(lam_over_diam=lam_over_diam,
                                           dx=dx_lookup,
                                           array_shape=(npix, npix),
                                           defocus=defocus,
                                           astig1=astig1,
                                           astig2=astig2,
                                           coma1=coma1,
                                           coma2=coma2,
                                           trefoil1=trefoil1,
                                           trefoil2=trefoil2,
                                           spher=spher,
                                           circular_pupil=circular_pupil,
                                           obscuration=obscuration,
                                           flux=flux)

        # If interpolant not specified on input, use a Quintic interpolant
        if interpolant is None:
            quintic = galsim.Quintic(tol=1e-4)
            self.interpolant = galsim.InterpolantXY(quintic)
        else:
            self.interpolant = galsim.utilities.convert_interpolant_to_2d(
                interpolant)

        # Initialize the SBProfile
        GSObject.__init__(
            self,
            galsim.SBInterpolatedImage(optimage,
                                       xInterp=self.interpolant,
                                       dx=dx_lookup,
                                       gsparams=gsparams))

        # The above procedure ends up with a larger image than we really need, which
        # means that the default stepK value will be smaller than we need.
        # Thus, we call the function calculateStepK() to refine the value.
        self.SBProfile.calculateStepK()
        self.SBProfile.calculateMaxK()
Exemplo n.º 9
0
    def __init__(self, image, x_interpolant = None, k_interpolant = None, normalization = 'flux',
                 dx = None, flux = None, pad_factor = 0., noise_pad = 0., rng = None,
                 pad_image = None, calculate_stepk=True, calculate_maxk=True,
                 use_cache=True, use_true_center=True, offset=None, gsparams=None):

        # first try to read the image as a file.  If it's not either a string or a valid
        # pyfits hdu or hdulist, then an exception will be raised, which we ignore and move on.
        try:
            image = galsim.fits.read(image)
        except:
            pass

        # make sure image is really an image and has a float type
        if not isinstance(image, galsim.BaseImageF) and not isinstance(image, galsim.BaseImageD):
            raise ValueError("Supplied image is not an image of floats or doubles!")

        # it must have well-defined bounds, otherwise seg fault in SBInterpolatedImage constructor
        if not image.bounds.isDefined():
            raise ValueError("Supplied image does not have bounds defined!")

        # check what normalization was specified for the image: is it an image of surface
        # brightness, or flux?
        if not normalization.lower() in ("flux", "f", "surface brightness", "sb"):
            raise ValueError(("Invalid normalization requested: '%s'. Expecting one of 'flux', "+
                              "'f', 'surface brightness', or 'sb'.") % normalization)

        # set up the interpolants if none was provided by user, or check that the user-provided ones
        # are of a valid type
        if x_interpolant is None:
            self.x_interpolant = galsim.InterpolantXY(galsim.Quintic(tol=1e-4))
        else:
            self.x_interpolant = galsim.utilities.convert_interpolant_to_2d(x_interpolant)
        if k_interpolant is None:
            self.k_interpolant = galsim.InterpolantXY(galsim.Quintic(tol=1e-4))
        else:
            self.k_interpolant = galsim.utilities.convert_interpolant_to_2d(k_interpolant)

        # Check for input dx, and check whether Image already has one set.  At the end of this
        # code block, either an exception will have been raised, or the input image will have a
        # valid scale set.
        if dx is None:
            dx = image.scale
            if dx == 0:
                raise ValueError("No information given with Image or keywords about pixel scale!")
        else:
            if type(dx) != float:
                dx = float(dx)
            if dx <= 0.0:
                raise ValueError("dx may not be <= 0.0")
            # Don't change the original image.  Make a new view if we need to set the scale.
            image = image.view()
            image.scale = dx

        # Set up the GaussianDeviate if not provided one, or check that the user-provided one is
        # of a valid type.
        if rng is None:
            if noise_pad: rng = galsim.BaseDeviate()
        elif not isinstance(rng, galsim.BaseDeviate):
            raise TypeError("rng provided to InterpolatedImage constructor is not a BaseDeviate")

        # Check that given pad_image is valid:
        if pad_image:
            if isinstance(pad_image, str):
                pad_image = galsim.fits.read(pad_image)
            if ( not isinstance(pad_image, galsim.BaseImageF) and 
                 not isinstance(pad_image, galsim.BaseImageD) ):
                raise ValueError("Supplied pad_image is not one of the allowed types!")

        # Check that the given noise_pad is valid:
        try:
            noise_pad = float(noise_pad)
        except:
            pass
        if isinstance(noise_pad, float):
            if noise_pad < 0.:
                raise ValueError("Noise variance cannot be negative!")
        # There are other options for noise_pad, the validity of which will be checked in
        # the helper function self.buildNoisePadImage()

        # This will be passed to SBInterpolatedImage, so make sure it is the right type.
        pad_factor = float(pad_factor)

        # Store the image as an attribute
        self.orig_image = image
        self.use_cache = use_cache

        # See if we need to build a pad_image
        if noise_pad and pad_image:
            # if both noise_pad and pad_image are set, then we need to build up a larger
            # pad_image and place the given pad_image in the center.
            new_pad_image = self.buildNoisePadImage(pad_factor, noise_pad, rng)

            # We will change the bounds here, so make a new view to avoid modifying the 
            # input pad_image.
            pad_image = pad_image.view()  
            pad_image.setCenter(0,0)
            new_pad_image.setCenter(0,0)
            if not new_pad_image.bounds.includes(pad_image.bounds):
                raise ValueError("pad_factor is too small to fit the provided pad_image.")
            new_pad_image[pad_image.bounds] = pad_image
            pad_image = new_pad_image
        elif noise_pad:
            # Just build the noise image
            pad_image = self.buildNoisePadImage(pad_factor, noise_pad, rng)
        elif pad_image:
            # Just make sure pad_image is the right type
            if ( isinstance(image, galsim.BaseImageF) and 
                 not isinstance(pad_image, galsim.BaseImageF) ):
                pad_image = galsim.ImageF(pad_image)
            elif ( isinstance(image, galsim.BaseImageD) and 
                   not isinstance(pad_image, galsim.BaseImageD) ):
                pad_image = galsim.ImageD(pad_image)

        # Make the SBInterpolatedImage out of the image.
        sbinterpolatedimage = galsim.SBInterpolatedImage(
                image, xInterp=self.x_interpolant, kInterp=self.k_interpolant,
                dx=dx, pad_factor=pad_factor, pad_image=pad_image, gsparams=gsparams)

        # GalSim cannot automatically know what stepK and maxK are appropriate for the 
        # input image.  So it is usually worth it to do a manual calculation here.
        if calculate_stepk:
            sbinterpolatedimage.calculateStepK()
        if calculate_maxk:
            sbinterpolatedimage.calculateMaxK()

        # If the user specified a flux, then set to that flux value.
        if flux != None:
            if type(flux) != flux:
                flux = float(flux)
            sbinterpolatedimage.setFlux(flux)
        # If the user specified a flux normalization for the input Image, then since
        # SBInterpolatedImage works in terms of surface brightness, have to rescale the values to
        # get proper normalization.
        elif flux is None and normalization.lower() in ['flux','f'] and dx != 1.:
            sbinterpolatedimage.scaleFlux(1./(dx**2))
        # If the input Image normalization is 'sb' then since that is the SBInterpolated default
        # assumption, no rescaling is needed.

        # Initialize the SBProfile
        GSObject.__init__(self, sbinterpolatedimage)

        # Apply the offset, and possibly fix the centering for even-sized images
        # Note reverse=True, since we want to fix the center in the opposite sense of what the 
        # draw function does.
        prof = self._fix_center(image, dx, offset, use_true_center, reverse=True)
        GSObject.__init__(self, prof.SBProfile)
Exemplo n.º 10
0
    raise RuntimeError(
        "Grids in bulge and disk scale lengths do not have same size!")
nBulge = 4.0
nDisk = 1.0
pixelScale = 0.03  # we are simulating ACS data
totFlux = 1000.0  # total flux for galaxy

#### note: the following parameters were not used ####
sigmaBulge = 1.0  # dispersion in Sersic n for bulge
sigmaDisk = 0.2  # dispersion in Sersic n for disk

# read in ePSF and normalize (note: already includes pixel response, don't have to do separately)
l3 = galsim.Lanczos(3, True, 1.0E-4)
l32d = galsim.InterpolantXY(l3)
PSFImage = galsim.fits.read(PSFFile)
PSF = galsim.SBInterpolatedImage(PSFImage, l32d, pixelScale, 2.)
PSF.setFlux(1.0)

# Loop over the various grids: values of bulge-to-total ratio, bulge ellipticity, disk ellipticity,
# S/N and number of noise realizations, radii
rng = galsim.UniformDeviate()
for bt in bulge2Total:
    print "Beginning bulge-to-total ratio of ", bt
    for bell in bulgeEllip:
        print "Beginning bulge ellipticity of ", bell
        for dell in diskEllip:
            print "Beginning disk ellipticity of ", dell
            for dreind in range(len(diskRe)):
                print "Beginning disk half-light radius of ", diskRe[dreind]

                # Make the bulge: use a Sersic rather than a DeVauc specifically, because we want to