Exemple #1
0
def test_realspace_distorted_convolve():
    """
    The same as above, but both the Moffat and the Box are sheared, rotated and shifted
    to stress test the code that deals with this for real-space convolutions that wouldn't
    be tested otherwise.
    """
    import time
    t1 = time.time()
    fwhm_backwards_compatible = 1.0927449310213702
    psf = galsim.SBMoffat(beta=1.5,
                          half_light_radius=1,
                          trunc=4 * fwhm_backwards_compatible,
                          flux=1)
    #psf = galsim.SBMoffat(beta=1.5, fwhm=fwhm_backwards_compatible,
    #trunc=4*fwhm_backwards_compatible, flux=1)
    psf.applyShear(galsim.Shear(g1=0.11, g2=0.17)._shear)
    psf.applyRotation(13 * galsim.degrees)
    pixel = galsim.SBBox(xw=0.2, yw=0.2, flux=1.)
    pixel.applyShear(galsim.Shear(g1=0.2, g2=0.0)._shear)
    pixel.applyRotation(80 * galsim.degrees)
    pixel.applyShift(0.13, 0.27)
    conv = galsim.SBConvolve([psf, pixel], real_space=True)

    # Note: Using an image created from Maple "exact" calculations.
    saved_img = galsim.fits.read(
        os.path.join(imgdir, "moffat_pixel_distorted.fits"))
    img = galsim.ImageF(saved_img.bounds, scale=0.2)
    conv.draw(img.view())
    printval(img, saved_img)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "distorted Moffat convolved with distorted Box disagrees with expected result"
    )

    # Repeat with the GSObject version of this:
    psf = galsim.Moffat(beta=1.5,
                        half_light_radius=1,
                        trunc=4 * fwhm_backwards_compatible,
                        flux=1)
    #psf = galsim.Moffat(beta=1.5, fwhm=fwhm_backwards_compatible,
    #trunc=4*fwhm_backwards_compatible, flux=1)
    psf.applyShear(g1=0.11, g2=0.17)
    psf.applyRotation(13 * galsim.degrees)
    pixel = galsim.Pixel(xw=0.2, yw=0.2, flux=1.)
    pixel.applyShear(g1=0.2, g2=0.0)
    pixel.applyRotation(80 * galsim.degrees)
    pixel.applyShift(0.13, 0.27)
    # NB: real-space is chosen automatically
    conv = galsim.Convolve([psf, pixel])
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve([psf,pixel]) (distorted) disagrees with expected result"
    )

    # Check with default_params
    conv = galsim.Convolve([psf, pixel], gsparams=default_params)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve([psf,pixel]) (distorted) with default_params disagrees with "
        "expected result")
    conv = galsim.Convolve([psf, pixel], gsparams=galsim.GSParams())
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve([psf,pixel]) (distorted) with GSParams() disagrees with "
        "expected result")

    # Other ways to do the convolution:
    conv = galsim.Convolve(psf, pixel)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve(psf,pixel) (distorted) disagrees with expected result")

    # The real-space convolution algorithm is not (trivially) independent of the order of
    # the two things being convolved.  So check the opposite order.
    conv = galsim.Convolve([pixel, psf])
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve([pixel,psf]) (distorted) disagrees with expected result"
    )

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Exemple #2
0
def test_exponential():
    """Test the generation of a specific exp profile against a known result.
    """
    re = 1.0
    # Note the factor below should really be 1.6783469900166605, but the value of 1.67839 is
    # retained here as it was used by SBParse to generate the original known result (this changed
    # in commit b77eb05ab42ecd31bc8ca03f1c0ae4ee0bc0a78b.
    # The value of this test for regression purposes is not harmed by retaining the old scaling, it
    # just means that the half light radius chosen for the test is not really 1, but 0.999974...
    r0 = re / 1.67839
    savedImg = galsim.fits.read(os.path.join(imgdir, "exp_1.fits"))
    dx = 0.2
    myImg = galsim.ImageF(savedImg.bounds, scale=dx)
    myImg.setCenter(0, 0)

    expon = galsim.Exponential(flux=1., scale_radius=r0)
    expon.drawImage(myImg, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg="Using GSObject Exponential disagrees with expected result")

    # Check with default_params
    expon = galsim.Exponential(flux=1.,
                               scale_radius=r0,
                               gsparams=default_params)
    expon.drawImage(myImg, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject Exponential with default_params disagrees with expected result"
    )
    expon = galsim.Exponential(flux=1.,
                               scale_radius=r0,
                               gsparams=galsim.GSParams())
    expon.drawImage(myImg, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject Exponential with GSParams() disagrees with expected result"
    )

    # Use non-unity values.
    expon = galsim.Exponential(flux=1.7, scale_radius=0.91)
    gsp = galsim.GSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)
    expon2 = galsim.Exponential(flux=1.7, scale_radius=0.91, gsparams=gsp)
    assert expon2 != expon
    assert expon2 == expon.withGSParams(gsp)

    check_basic(expon, "Exponential")

    # Test photon shooting.
    do_shoot(expon, myImg, "Exponential")

    # Test kvalues
    do_kvalue(expon, myImg, "Exponential")

    # Check picklability
    do_pickle(expon, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(expon)

    # Should raise an exception if both scale_radius and half_light_radius are provided.
    assert_raises(TypeError,
                  galsim.Exponential,
                  scale_radius=3,
                  half_light_radius=1)
    # Or neither.
    assert_raises(TypeError, galsim.Exponential)
Exemple #3
0
def test_ne():
    # Use some very forgiving settings to speed up this test.  We're not actually going to draw
    # any images (other than internally the PSF), so should be okay.
    gsp1 = galsim.GSParams(maxk_threshold=5.e-2,
                           folding_threshold=5e-2,
                           kvalue_accuracy=1e-3,
                           xvalue_accuracy=1e-3)
    gsp2 = galsim.GSParams(maxk_threshold=5.1e-2,
                           folding_threshold=5e-2,
                           kvalue_accuracy=1e-3,
                           xvalue_accuracy=1e-3)
    pupil_plane_im = galsim.fits.read(os.path.join(imgdir, pp_file))

    # Params include: lam_over_diam, (lam/diam), aberrations by name, aberrations by list, nstruts,
    # strut_thick, strut_angle, obscuration, oversampling, pad_factor, flux, gsparams,
    # circular_pupil, interpolant, pupil_plane_im, pupil_angle, scale_unit
    objs = [
        galsim.OpticalPSF(lam_over_diam=1.0, gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0, gsparams=gsp2),
        galsim.OpticalPSF(lam=1.0, diam=1.0, gsparams=gsp1),
        galsim.OpticalPSF(lam=1.0,
                          diam=1.0,
                          scale_unit=galsim.arcmin,
                          gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0, defocus=0.1, gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0,
                          aberrations=[0, 0, 0, 0, 0.2],
                          gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0, nstruts=2, gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0,
                          nstruts=2,
                          strut_thick=0.3,
                          gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0,
                          nstruts=2,
                          strut_angle=10. * galsim.degrees,
                          gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0, obscuration=0.5, gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0, oversampling=2.0, gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0, pad_factor=2.0, gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0, flux=2.0, gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0,
                          circular_pupil=False,
                          gsparams=gsp1),
        galsim.OpticalPSF(lam_over_diam=1.0,
                          interpolant='Linear',
                          gsparams=gsp1)
    ]
    if __name__ == do_slow_tests:
        objs += [
            galsim.OpticalPSF(lam_over_diam=1.0,
                              pupil_plane_im=pupil_plane_im,
                              gsparams=gsp1,
                              suppress_warning=True),
            galsim.OpticalPSF(lam_over_diam=1.0,
                              pupil_plane_im=pupil_plane_im,
                              gsparams=gsp1,
                              pupil_angle=10 * galsim.degrees,
                              suppress_warning=True)
        ]
    all_obj_diff(objs)
Exemple #4
0
def test_tophat():
    """Test the generation of a specific tophat profile against a known result.
    """
    savedImg = galsim.fits.read(os.path.join(imgdir, "tophat_101.fits"))
    myImg = galsim.ImageF(savedImg.bounds, scale=0.2)
    myImg.setCenter(0,0)
    test_flux = 1.8

    # There are numerical issues with using radius = 1, since many points are right on the edge
    # of the circle.  e.g. (+-1,0), (0,+-1), (+-0.6,+-0.8), (+-0.8,+-0.6).  And in practice, some
    # of these end up getting drawn and not others, which means it's not a good choice for a unit
    # test since it wouldn't be any less correct for a different subset of these points to be
    # drawn. Using r = 1.01 solves this problem and makes the result symmetric.
    tophat = galsim.TopHat(radius=1.01, flux=1)
    tophat.drawImage(myImg, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject TopHat disagrees with expected result")
    np.testing.assert_array_equal(
            tophat.radius, 1.01,
            err_msg="TopHat radius returned wrong value")

    # Check with default_params
    tophat = galsim.TopHat(radius=1.01, flux=1, gsparams=default_params)
    tophat.drawImage(myImg, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject TopHat with default_params disagrees with expected result")
    tophat = galsim.TopHat(radius=1.01, flux=1, gsparams=galsim.GSParams())
    tophat.drawImage(myImg, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject TopHat with GSParams() disagrees with expected result")

    # Use non-unity values.
    tophat = galsim.TopHat(flux=1.7, radius=2.3)
    gsp = galsim.GSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)
    tophat2 = galsim.TopHat(flux=1.7, radius=2.3, gsparams=gsp)
    assert tophat2 != tophat
    assert tophat2 == tophat.withGSParams(gsp)

    # Test photon shooting.
    do_shoot(tophat,myImg,"TopHat")

    # Test shoot and kvalue
    scale = 0.2939
    im = galsim.ImageF(16,16, scale=scale)
    # The choices of radius here are fairly specific.  If the edge of the circle comes too close
    # to the center of one of the pixels, then the test will fail, since the Fourier draw method
    # will blur the edge a bit and give some flux to that pixel.
    for radius in [ 1.2, 0.93, 2.11 ]:
        tophat = galsim.TopHat(radius=radius, flux=test_flux)
        check_basic(tophat, "TopHat with radius = %f"%radius)
        do_shoot(tophat,im,"TopHat with radius = %f"%radius)
        do_kvalue(tophat,im,"TopHat with radius = %f"%radius)

        # This is also a profile that may be convolved using real space convolution, so test that.
        conv = galsim.Convolve(tophat, galsim.Pixel(scale=scale), real_space=True)
        check_basic(conv, "TopHat convolved with pixel in real space",
                    approx_maxsb=True, scale=0.2)
        do_kvalue(conv,im, "TopHat convolved with pixel in real space")

        cen = galsim.PositionD(0, 0)
        np.testing.assert_equal(tophat.centroid, cen)
        np.testing.assert_almost_equal(tophat.kValue(cen), (1+0j) * test_flux)
        np.testing.assert_almost_equal(tophat.flux, test_flux)
        np.testing.assert_almost_equal(tophat.xValue(cen), tophat.max_sb)
        np.testing.assert_almost_equal(tophat.xValue(radius-0.001, 0.), tophat.max_sb)
        np.testing.assert_almost_equal(tophat.xValue(0., radius-0.001), tophat.max_sb)
        np.testing.assert_almost_equal(tophat.xValue(radius+0.001, 0.), 0.)
        np.testing.assert_almost_equal(tophat.xValue(0., radius+0.001), 0.)

    # Check picklability
    do_pickle(tophat, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(tophat)
    do_pickle(galsim.TopHat(1))

    # Check sheared tophat the same way
    tophat = galsim.TopHat(radius=1.2, flux=test_flux)
    # Again, the test is very sensitive to the choice of shear here.  Most values fail because
    # some pixel center gets too close to the resulting ellipse for the fourier draw to match
    # the real-space draw at the required accuracy.
    tophat = tophat.shear(galsim.Shear(g1=0.15, g2=-0.33))
    check_basic(tophat, "Sheared TopHat")
    do_shoot(tophat,im, "Sheared TopHat")
    do_kvalue(tophat,im, "Sheared TopHat")
    cen = galsim.PositionD(0, 0)
    np.testing.assert_equal(tophat.centroid, cen)
    np.testing.assert_almost_equal(tophat.kValue(cen), (1+0j) * test_flux)
    np.testing.assert_almost_equal(tophat.flux, test_flux)
    np.testing.assert_almost_equal(tophat.xValue(cen), tophat.max_sb)

    # Check picklability
    do_pickle(tophat, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(tophat)

    # Check real-space convolution of the sheared tophat.
    conv = galsim.Convolve(tophat, galsim.Pixel(scale=scale), real_space=True)
    check_basic(conv, "Sheared TopHat convolved with pixel in real space",
                approx_maxsb=True, scale=0.2)
    do_kvalue(conv,im, "Sheared TopHat convolved with pixel in real space")
Exemple #5
0
def main(argv):

    logging.basicConfig(format="%(message)s",
                        level=logging.INFO,
                        stream=sys.stdout)
    logger = logging.getLogger("demo7")

    ### Make output directory if not already present.
    if not os.path.isdir('output'):
        os.mkdir('output')

    file_name = os.path.join('output', 'cube_phot.fits.gz')

    scaleimg_y = []
    scaleimg_x_DFT = []
    scaleimg_x_Photon = []
    ranges = np.linspace(2.e-6, 2.e-1, 5)
    for num in ranges:

        ### Define some parameters we'll use below.
        random_seed = 553728
        sky_level = 1.e4  # ADU / arcsec^2
        pixel_scale = .28  # arcsec*
        nx = 64
        ny = 64

        gal_flux_min = 1.e1  # Range for galaxy flux
        gal_flux_max = 1.e5
        gal_hlr_min = 0.3  # arcsec
        gal_hlr_max = 1.3  # arcsec
        gal_e_min = 0.  # Range for ellipticity
        gal_e_max = 0.8

        psf_fwhm = 0.65  # arcsec

        # We encapsulate these parameters with an object called GSParams.  The default values
        # are intended to be accurate enough for normal precision shear tests, without sacrificing
        # too much speed.Any PSF or galaxy object can be given a gsparams argument on construction that can
        # have different values to make the calculation more or less accurate (typically trading
        # off for speed or memory).

        gsparams = galsim.GSParams(
            folding_threshold=
            1.e-2,  # maximum fractional flux that may be folded around edge of FFT
            maxk_threshold=
            num,  # k-values less than this may be excluded off edge of FFT
            xvalue_accuracy=
            1.e-4,  # approximations in real space aim to be this accurate
            kvalue_accuracy=
            1.e-4,  # approximations in fourier space aim to be this accurate
            shoot_accuracy=
            1.e-4,  # approximations in photon shooting aim to be this accurate
            minimum_fft_size=64)  # minimum size of ffts

        logger.info('Starting psf')

        # Make the PSF profiles:
        ### psf 1
        psf1 = galsim.Gaussian(fwhm=psf_fwhm, gsparams=gsparams)

        ### psf 2
        psf2 = galsim.Moffat(fwhm=psf_fwhm, beta=2.4, gsparams=gsparams)

        ### psf 3
        psf3_inner = galsim.Gaussian(fwhm=psf_fwhm,
                                     flux=0.8,
                                     gsparams=gsparams)
        psf3_outer = galsim.Gaussian(fwhm=2 * psf_fwhm,
                                     flux=0.2,
                                     gsparams=gsparams)
        psf3 = psf3_inner + psf3_outer
        atmos = galsim.Gaussian(fwhm=psf_fwhm, gsparams=gsparams)

        ### defining the telescope

        # The OpticalPSF and set of Zernike values chosen below correspond to a reasonably well aligned,
        # smallish ~0.3m / 12 inch diameter telescope with a central obscuration of ~0.12m or 5 inches
        # diameter, being used in optical wavebands.

        aberrations = [0.0] * 12  # Set the initial size.
        aberrations[4] = 0.06  # Noll index 4 = Defocus
        aberrations[5:7] = [0.12, -0.08]  # Noll index 5,6 = Astigmatism
        aberrations[7:9] = [0.07, 0.04]  # Noll index 7,8 = Coma
        aberrations[11] = -0.13  # Noll index 11 = Spherical

        optics = galsim.OpticalPSF(lam_over_diam=0.6 * psf_fwhm,
                                   obscuration=0.4,
                                   aberrations=aberrations,
                                   gsparams=gsparams)

        ### psf 4
        psf4 = galsim.Convolve(
            [atmos, optics])  # Convolve inherits the gsparams from the first
        # item in the list.  (Or you can supply a gsparams
        # argument explicitly if you want to override this.)
        atmos = galsim.Kolmogorov(fwhm=psf_fwhm, gsparams=gsparams)
        optics = galsim.Airy(lam_over_diam=0.3 * psf_fwhm, gsparams=gsparams)

        ### psf 5
        psf5 = galsim.Convolve([atmos, optics])

        ### define where to keep the psfs info
        psfs = [psf1, psf2, psf3, psf4, psf5]
        psf_names = [
            "Gaussian", "Moffat", "Double Gaussian", "OpticalPSF",
            "Kolmogorov * Airy"
        ]
        psf_times = [0, 0, 0, 0, 0]
        psf_fft_times = [0, 0, 0, 0, 0]
        psf_phot_times = [0, 0, 0, 0, 0]

        # Make the galaxy profiles:

        ### gal 1
        gal1 = galsim.Gaussian(half_light_radius=1, gsparams=gsparams)

        ### gal 2
        gal2 = galsim.Exponential(half_light_radius=1, gsparams=gsparams)

        ### gal 3
        gal3 = galsim.DeVaucouleurs(half_light_radius=1, gsparams=gsparams)

        ### gal 4
        gal4 = galsim.Sersic(half_light_radius=1, n=2.5, gsparams=gsparams)
        bulge = galsim.Sersic(half_light_radius=0.7,
                              n=3.2,
                              trunc=8.5,
                              gsparams=gsparams)
        disk = galsim.Sersic(half_light_radius=1.2, n=1.5, gsparams=gsparams)

        ### gal 5
        gal5 = 0.4 * bulge + 0.6 * disk  # Net half-light radius is only approximate for this one.

        ### define where to keep the galaxys info
        gals = [gal1, gal2, gal3, gal4, gal5]
        gal_names = [
            "Gaussian", "Exponential", "Devaucouleurs", "n=2.5 Sersic",
            "Bulge + Disk"
        ]
        gal_times = [0, 0, 0, 0, 0]
        gal_fft_times = [0, 0, 0, 0, 0]
        gal_phot_times = [0, 0, 0, 0, 0]

        ### initial time conditions
        # Other times to keep track of:
        setup_times = 0
        fft_times = 0
        phot_times = 0
        noise_times = 0

        # Loop over combinations of psf, gal, and make 4 random choices for flux, size, shape.
        all_images = []
        k = 0

        n = []
        x_DFT = []
        x_Photon = []
        y = []
        all_fluxes = np.linspace(gal_flux_min, gal_flux_max, 100)

        ### will loop through the numbers (amount) of psfs
        for ipsf in range(len(psfs)):

            ### calls on the 5 psfs and their names
            psf = psfs[ipsf]
            psf_name = psf_names[ipsf]

            ### outputs the psf number and the psf information needed to create an object
            logger.info('psf %d: %s', ipsf + 1, psf)

            logger.debug('repr = %r', psf)

            ### will loop through the numbers (amount) of galaxies
            for igal in range(len(gals)):

                ### calls on the 5 galaxies and their names
                gal = gals[igal]
                gal_name = gal_names[igal]

                ### outputs the psf number and the psf information needed to create an object
                logger.info('   galaxy %d: %s', igal + 1, gal)
                logger.debug('   repr = %r', gal)

                ### will loop though 0,1,2,3 flux, size, and shape to create 4 images for each
                ### combination of galaxy and psf
                for i in range(4):
                    logger.debug('      Start work on image %d', i)
                    all_fluxes_i = all_fluxes[i]
                    image, t1, t2, t3, t4, t5, t6, k, flux, hlr, gal_shape, y_i, psfs, gals, file_name = func(
                        file_name, random_seed, pixel_scale, nx, ny, sky_level,
                        gal_flux_min, gal_flux_max, gal_hlr_min, gal_hlr_max,
                        gal_e_min, gal_e_max, psf_fwhm, gsparams, psf1, psf2,
                        psf3_inner, psf3_outer, psf3, atmos, aberrations, psf4,
                        optics, psf5, psfs, psf_names, psf_times,
                        psf_fft_times, psf_phot_times, gal1, gal2, gal3, gal4,
                        bulge, disk, gal5, gals, gal_names, gal_times,
                        gal_fft_times, gal_phot_times, setup_times, fft_times,
                        phot_times, noise_times, k, all_fluxes_i, psf,
                        psf_name, gal, gal_name)

                    ### Store that into the list of all images
                    all_images += [image]
                    y = np.append(y, y_i)

                    ### add an itteration though the loop for the psf and galaxy combination images
                    k = k + 1

                    ### express the flux,hlr, and ellip of each image combination,4 for every loop
                    logger.info(
                        '      %d: flux = %.2e, hlr = %.2f, ellip = (%.2f,%.2f)',
                        k, flux, hlr, gal_shape.getE1(), gal_shape.getE2())

                    logger.debug('      Times: %f, %f, %f, %f, %f', t2 - t1,
                                 t3 - t2, t4 - t3, t5 - t4, t6 - t5)

                    psf_times[ipsf] += t6 - t1
                    psf_fft_times[ipsf] += t3 - t2
                    psf_phot_times[ipsf] += t5 - t4
                    gal_times[igal] += t6 - t1
                    gal_fft_times[igal] += t3 - t2
                    gal_phot_times[igal] += t5 - t4
                    setup_times += t2 - t1
                    fft_times += t3 - t2
                    phot_times += t5 - t4
                    noise_times += t4 - t3 + t6 - t5
                    x_DFT = np.append(x_DFT, gal_fft_times[igal])
                    x_Photon = np.append(x_Photon, gal_phot_times[igal])

#### flux and time of each galaxy profile with each PSF
        scaleimg_y = np.append(scaleimg_y, y)
        scaleimg_x_DFT = np.append(scaleimg_x_DFT, x_DFT)
        scaleimg_x_Photon = np.append(scaleimg_x_Photon, x_Photon)

    #### [FOR FIGURES 1-5] the DFT and Photon-Shooting time for the first psf and 5 galaxy profile all at flux 10

    x1_DFT_1 = (scaleimg_x_DFT[0], scaleimg_x_DFT[100], scaleimg_x_DFT[200],
                scaleimg_x_DFT[300], scaleimg_x_DFT[400])
    x1_DFT_2 = (scaleimg_x_DFT[4], scaleimg_x_DFT[104], scaleimg_x_DFT[204],
                scaleimg_x_DFT[304], scaleimg_x_DFT[404])
    x1_DFT_3 = (scaleimg_x_DFT[8], scaleimg_x_DFT[108], scaleimg_x_DFT[208],
                scaleimg_x_DFT[308], scaleimg_x_DFT[408])
    x1_DFT_4 = (scaleimg_x_DFT[12], scaleimg_x_DFT[112], scaleimg_x_DFT[212],
                scaleimg_x_DFT[312], scaleimg_x_DFT[412])
    x1_DFT_5 = (scaleimg_x_DFT[16], scaleimg_x_DFT[116], scaleimg_x_DFT[216],
                scaleimg_x_DFT[316], scaleimg_x_DFT[416])

    x1_Photon_1 = (scaleimg_x_Photon[0], scaleimg_x_Photon[100],
                   scaleimg_x_Photon[200], scaleimg_x_Photon[300],
                   scaleimg_x_Photon[400])
    x1_Photon_2 = (scaleimg_x_Photon[4], scaleimg_x_Photon[104],
                   scaleimg_x_Photon[204], scaleimg_x_Photon[304],
                   scaleimg_x_Photon[404])
    x1_Photon_3 = (scaleimg_x_Photon[8], scaleimg_x_Photon[108],
                   scaleimg_x_Photon[208], scaleimg_x_Photon[308],
                   scaleimg_x_Photon[408])
    x1_Photon_4 = (scaleimg_x_Photon[12], scaleimg_x_Photon[112],
                   scaleimg_x_Photon[212], scaleimg_x_Photon[312],
                   scaleimg_x_Photon[412])
    x1_Photon_5 = (scaleimg_x_Photon[16], scaleimg_x_Photon[116],
                   scaleimg_x_Photon[216], scaleimg_x_Photon[316],
                   scaleimg_x_Photon[416])

    #### [FOR FIGURES 6-10] for the first PSF and 5 galaxy profile for all flux at 1020
    x2_DFT_1 = (scaleimg_x_DFT[1], scaleimg_x_DFT[101], scaleimg_x_DFT[201],
                scaleimg_x_DFT[301], scaleimg_x_DFT[401])
    x2_DFT_2 = (scaleimg_x_DFT[5], scaleimg_x_DFT[105], scaleimg_x_DFT[205],
                scaleimg_x_DFT[305], scaleimg_x_DFT[405])
    x2_DFT_3 = (scaleimg_x_DFT[9], scaleimg_x_DFT[109], scaleimg_x_DFT[209],
                scaleimg_x_DFT[309], scaleimg_x_DFT[409])
    x2_DFT_4 = (scaleimg_x_DFT[13], scaleimg_x_DFT[113], scaleimg_x_DFT[213],
                scaleimg_x_DFT[313], scaleimg_x_DFT[413])
    x2_DFT_5 = (scaleimg_x_DFT[17], scaleimg_x_DFT[117], scaleimg_x_DFT[217],
                scaleimg_x_DFT[317], scaleimg_x_DFT[417])

    x2_Photon_1 = (scaleimg_x_Photon[1], scaleimg_x_Photon[101],
                   scaleimg_x_Photon[201], scaleimg_x_Photon[301],
                   scaleimg_x_Photon[401])
    x2_Photon_2 = (scaleimg_x_Photon[5], scaleimg_x_Photon[105],
                   scaleimg_x_Photon[205], scaleimg_x_Photon[305],
                   scaleimg_x_Photon[405])
    x2_Photon_3 = (scaleimg_x_Photon[9], scaleimg_x_Photon[109],
                   scaleimg_x_Photon[209], scaleimg_x_Photon[309],
                   scaleimg_x_Photon[409])
    x2_Photon_4 = (scaleimg_x_Photon[13], scaleimg_x_Photon[113],
                   scaleimg_x_Photon[213], scaleimg_x_Photon[313],
                   scaleimg_x_Photon[413])
    x2_Photon_5 = (scaleimg_x_Photon[17], scaleimg_x_Photon[117],
                   scaleimg_x_Photon[217], scaleimg_x_Photon[317],
                   scaleimg_x_Photon[417])

    #### [FOR FIGURES 1-5] the DFT and Photon-Shooting time for the first psf and 5 galaxy profile all at flux 10
    ###subtraction of points

    xnew_1 = []
    xnew_2 = []
    xnew_3 = []
    xnew_4 = []
    xnew_5 = []
    for a, b, c, d, e, f, g, h, i, j in zip(x1_DFT_1, x1_Photon_1, x1_DFT_2,
                                            x1_Photon_2, x1_DFT_3, x1_Photon_3,
                                            x1_DFT_4, x1_Photon_4, x1_DFT_5,
                                            x1_Photon_5):
        x1 = a - b
        x2 = c - d
        x3 = e - f
        x4 = g - h
        x5 = i - j
        xnew_1 = np.append(xnew_1, x1)
        xnew_2 = np.append(xnew_2, x2)
        xnew_3 = np.append(xnew_3, x3)
        xnew_4 = np.append(xnew_4, x4)
        xnew_5 = np.append(xnew_5, x5)

#### [FOR FIGURES 6-10] for the first PSF and 5 galaxy profile for all flux at 1020
    xnew_6 = []
    xnew_7 = []
    xnew_8 = []
    xnew_9 = []
    xnew_10 = []
    for a, b, c, d, e, f, g, h, i, j in zip(x2_DFT_1, x2_Photon_1, x2_DFT_2,
                                            x2_Photon_2, x2_DFT_3, x2_Photon_3,
                                            x2_DFT_4, x2_Photon_4, x2_DFT_5,
                                            x2_Photon_5):
        x1 = a - b
        x2 = c - d
        x3 = e - f
        x4 = g - h
        x5 = i - j
        xnew_6 = np.append(xnew_6, x1)
        xnew_7 = np.append(xnew_7, x2)
        xnew_8 = np.append(xnew_8, x3)
        xnew_9 = np.append(xnew_9, x4)
        xnew_10 = np.append(xnew_10, x5)

    y = [0, 0, 0, 0, 0]

    #fig1
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x1_DFT_1, 'b-', label='l1')
    l2, = ax1.plot(ranges, x1_Photon_1, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Gaussian Galaxy Profile at flux=10')
    l4, = ax2.plot(ranges, xnew_1, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_1.png')

    #fig2
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x1_DFT_2, 'b-', label='l1')
    l2, = ax1.plot(ranges, x1_Photon_2, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Exponential Galaxy Profile at flux=10')
    l4, = ax2.plot(ranges, xnew_2, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_2.png')

    #fig3
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x1_DFT_3, 'b-', label='l1')
    l2, = ax1.plot(ranges, x1_Photon_3, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Devaucouleurs Galaxy Profile at flux=10')
    l4, = ax2.plot(ranges, xnew_3, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_3.png')

    #fig4
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x1_DFT_4, 'b-', label='l1')
    l2, = ax1.plot(ranges, x1_Photon_4, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with n=2.5 Sersic Galaxy Profile at flux=10')
    l4, = ax2.plot(ranges, xnew_4, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_4.png')

    #fig5
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x1_DFT_5, 'b-', label='l1')
    l2, = ax1.plot(ranges, x1_Photon_5, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Bulge + Disk Galaxy Profile at flux=10')
    l4, = ax2.plot(ranges, xnew_5, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_5.png')

    #fig6
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x2_DFT_1, 'b-', label='l1')
    l2, = ax1.plot(ranges, x2_Photon_1, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Bulge + Disk Galaxy Profile at flux=1020')
    l4, = ax2.plot(ranges, xnew_6, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_6.png')

    #fig7
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x2_DFT_2, 'b-', label='l1')
    l2, = ax1.plot(ranges, x2_Photon_2, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Bulge + Disk Galaxy Profile at flux=1020')
    l4, = ax2.plot(ranges, xnew_7, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_7.png')

    #fig8
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x2_DFT_3, 'b-', label='l1')
    l2, = ax1.plot(ranges, x2_Photon_3, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Bulge + Disk Galaxy Profile at flux=1020')
    l4, = ax2.plot(ranges, xnew_8, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_8.png')

    #fig9
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x2_DFT_4, 'b-', label='l1')
    l2, = ax1.plot(ranges, x2_Photon_4, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Bulge + Disk Galaxy Profile at flux=1020')
    l4, = ax2.plot(ranges, xnew_9, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_9.png')

    #fig10
    f, (ax1, ax2) = plt.subplots(2, sharex=True, sharey=True)
    l1, = ax1.plot(ranges, x2_DFT_5, 'b-', label='l1')
    l2, = ax1.plot(ranges, x2_Photon_5, 'g-', label='l2')
    l3, = ax1.plot(ranges, y, 'r--', label='l3')
    plt.legend([l1, l2, l3], ['DFT', 'Photon', 'Y=0'], loc='upper right')
    ax1.set_title('Gaussian PSF with Bulge + Disk Galaxy Profile at flux=1020')
    l4, = ax2.plot(ranges, xnew_10, 'y-', label='l4')
    l5, = ax2.plot(ranges, y, 'r--', label='l5')
    plt.legend([l4, l5], ['DFT - Photon', 'Y=0'], loc='upper right')
    plt.xlabel('pixel scale')
    plt.ylabel('time')
    plt.legend(loc='best')
    f.subplots_adjust(hspace=0)
    plt.setp([a.get_xticklabels() for a in f.axes[:-1]], visible=False)
    plt.savefig('maxk_10.png')

    plt.show()

    ### breakdown of psf and galaxy types as well as overal timing statistics
    logger.info('')
    logger.info('Some timing statistics:')
    logger.info('   Total time for setup steps = %f', setup_times)
    logger.info('   Total time for regular fft drawing = %f', fft_times)
    logger.info('   Total time for photon shooting = %f', phot_times)
    logger.info('   Total time for adding noise = %f', noise_times)
    logger.info('')
    logger.info('Breakdown by PSF type:')
    for ipsf in range(len(psfs)):
        logger.info('   %s: Total time = %f  (fft: %f, phot: %f)',
                    psf_names[ipsf], psf_times[ipsf], psf_fft_times[ipsf],
                    psf_phot_times[ipsf])
    logger.info('')
    logger.info('Breakdown by Galaxy type:')
    for igal in range(len(gals)):
        logger.info('   %s: Total time = %f  (fft: %f, phot: %f)',
                    gal_names[igal], gal_times[igal], gal_fft_times[igal],
                    gal_phot_times[igal])
    logger.info('')

    ### compress into a gzip file and save a a cube
    galsim.fits.writeCube(all_images, file_name, compression='gzip')
    logger.info('Wrote fft image to fits data cube %r', file_name)
Exemple #6
0
            self.draw_s()
        )  # Here, it's called for each catalog, and supercedes the galaxy values.
        out.update(self.draw_psf())  # Idem, one random PSF for each catalog
        out.update(self.draw_constants())

        return out


sp = EuclidLike_statshear(name="figstamps", snc_type=0, shear=0.0)

stampsize = 32

psfcat = momentsml.tools.io.readpickle(
    os.path.join(config.workdir, "psfcat.pkl"))

gsparams = galsim.GSParams(maximum_fft_size=20320)

# Simulating images
momentsml.sim.run.multi(simdir=config.simdir,
                        simparams=sp,
                        drawcatkwargs={
                            "n": 24,
                            "nc": 4,
                            "stampsize": stampsize
                        },
                        drawimgkwargs={
                            "gsparams": gsparams,
                            "sersiccut": 5.0
                        },
                        psfcat=psfcat,
                        psfselect="random",
Exemple #7
0
def test_sersic():
    """Test the generation of a specific Sersic profile against a known result.
    """
    # Test Sersic
    savedImg = galsim.fits.read(os.path.join(imgdir, "sersic_3_1.fits"))
    dx = 0.2
    myImg = galsim.ImageF(savedImg.bounds, scale=dx)
    myImg.setCenter(0,0)

    sersic = galsim.Sersic(n=3, flux=1, half_light_radius=1)
    sersic.drawImage(myImg,scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Sersic disagrees with expected result")

    # Check with default_params
    sersic = galsim.Sersic(n=3, flux=1, half_light_radius=1, gsparams=default_params)
    sersic.drawImage(myImg,scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Sersic with default_params disagrees with expected result")
    sersic = galsim.Sersic(n=3, flux=1, half_light_radius=1, gsparams=galsim.GSParams())
    sersic.drawImage(myImg,scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Sersic with GSParams() disagrees with expected result")

    # Use non-unity values.
    sersic = galsim.Sersic(n=3, flux=1.7, half_light_radius=2.3)
    gsp = galsim.GSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)
    sersic2 = galsim.Sersic(n=3, flux=1.7, half_light_radius=2.3, gsparams=gsp)
    assert sersic2 != sersic
    assert sersic2 == sersic.withGSParams(gsp)
    check_basic(sersic, "Sersic")

    # Test photon shooting.
    # Convolve with a small gaussian to smooth out the central peak.
    sersic2 = galsim.Convolve(sersic, galsim.Gaussian(sigma=0.3))
    do_shoot(sersic2,myImg,"Sersic")

    # Test kvalues
    do_kvalue(sersic,myImg,"Sersic")

    # Check picklability
    do_pickle(sersic, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(sersic)

    # Now repeat everything using a truncation.  (Above had no truncation.)

    # Test Truncated Sersic
    # Don't use an integer truncation, since we don't want the truncation line to pass directly
    # through the center of a pixel where numerical rounding differences may decide whether the
    # value is zero or not.
    # This regression test compares to an image built using the code base at 82259f0
    savedImg = galsim.fits.read(os.path.join(imgdir, "sersic_3_1_10.fits"))
    myImg = galsim.ImageF(savedImg.bounds, scale=dx)
    myImg.setCenter(0,0)

    sersic = galsim.Sersic(n=3, flux=1, half_light_radius=1, trunc=9.99)
    sersic.drawImage(myImg,scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using truncated GSObject Sersic disagrees with expected result")

    # Use non-unity values.
    test_flux = 1.8
    sersic = galsim.Sersic(n=3, flux=test_flux, half_light_radius=2.3, trunc=5.9)
    cen = galsim.PositionD(0, 0)
    np.testing.assert_equal(sersic.centroid, cen)
    np.testing.assert_almost_equal(sersic.kValue(cen), (1+0j) * test_flux)
    np.testing.assert_almost_equal(sersic.flux, test_flux)
    np.testing.assert_almost_equal(sersic.xValue(cen), sersic.max_sb)

    check_basic(sersic, "Truncated Sersic")

    # Test photon shooting.
    # Convolve with a small gaussian to smooth out the central peak.
    sersic2 = galsim.Convolve(sersic, galsim.Gaussian(sigma=0.3))
    do_shoot(sersic2,myImg,"Truncated Sersic")

    # Test kvalues
    do_kvalue(sersic,myImg, "Truncated Sersic")

    # Check picklability
    do_pickle(sersic, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(sersic)

    # Check for normalization consistencies with kValue checks. xValues tested in test_sersic_radii.

    # For half-light radius specified truncated Sersic, with flux_untruncated flag set
    sersic = galsim.Sersic(n=3, flux=test_flux, half_light_radius=1, trunc=10,
                           flux_untruncated=True)
    do_kvalue(sersic,myImg, "Truncated Sersic w/ flux_untruncated, half-light radius specified")

    # For scale radius specified Sersic
    sersic = galsim.Sersic(n=3, flux=test_flux, scale_radius=0.05)
    do_kvalue(sersic,myImg, "Sersic w/ scale radius specified")

    # For scale radius specified truncated Sersic
    sersic = galsim.Sersic(n=3, flux=test_flux, scale_radius=0.05, trunc=10)
    do_kvalue(sersic,myImg, "Truncated Sersic w/ scale radius specified")

    # For scale radius specified truncated Sersic, with flux_untruncated flag set
    sersic = galsim.Sersic(n=3, flux=test_flux, scale_radius=0.05, trunc=10, flux_untruncated=True)
    do_kvalue(sersic,myImg, "Truncated Sersic w/ flux_untruncated, scale radius specified")

    # Test severely truncated Sersic
    sersic = galsim.Sersic(n=4, flux=test_flux, half_light_radius=1, trunc=1.45)
    do_kvalue(sersic,myImg, "Severely truncated n=4 Sersic")

    # Should raise an exception if both scale_radius and half_light_radius are provided.
    assert_raises(TypeError, galsim.Sersic, n=1.2, scale_radius=3, half_light_radius=1)
    assert_raises(TypeError, galsim.Sersic, n=1.2)
    assert_raises(TypeError, galsim.DeVaucouleurs, scale_radius=3, half_light_radius=1)
    assert_raises(TypeError, galsim.DeVaucouleurs)

    # Allowed range is [0.3, 6.2]
    assert_raises(ValueError, galsim.Sersic, n=0.2, scale_radius=3)
    assert_raises(ValueError, galsim.Sersic, n=6.3, scale_radius=3)

    # trunc must be > sqrt(2) * hlr
    assert_raises(ValueError, galsim.Sersic, n=3, half_light_radius=1, trunc=1.4)
    assert_raises(ValueError, galsim.DeVaucouleurs, half_light_radius=1, trunc=1.4)

    # Other errors
    assert_raises(TypeError, galsim.Sersic, scale_radius=3)
    assert_raises(ValueError, galsim.Sersic, n=3, scale_radius=3, trunc=-1)
    assert_raises(ValueError, galsim.DeVaucouleurs, scale_radius=3, trunc=-1)
Exemple #8
0
def test_gaussian():
    """Test the generation of a specific Gaussian profile against a known result.
    """
    savedImg = galsim.fits.read(os.path.join(imgdir, "gauss_1.fits"))
    savedImg.setCenter(0,0)
    dx = 0.2
    myImg = galsim.ImageF(savedImg.bounds, scale=dx)
    myImg.setCenter(0,0)

    gauss = galsim.Gaussian(flux=1, sigma=1)
    # Reference images were made with old centering, which is equivalent to use_true_center=False.
    myImg = gauss.drawImage(myImg, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Gaussian disagrees with expected result")
    np.testing.assert_almost_equal(
            myImg.array.sum(dtype=float) *dx**2, myImg.added_flux, 5,
            err_msg="Gaussian profile GSObject::draw returned wrong added_flux")

    # Check a non-square image
    print(myImg.bounds)
    recImg = galsim.ImageF(45,66)
    recImg.setCenter(0,0)
    recImg = gauss.drawImage(recImg, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            recImg[savedImg.bounds].array, savedImg.array, 5,
            err_msg="Drawing Gaussian on non-square image disagrees with expected result")
    np.testing.assert_almost_equal(
            recImg.array.sum(dtype=float) *dx**2, recImg.added_flux, 5,
            err_msg="Gaussian profile GSObject::draw on non-square image returned wrong added_flux")

    # Check with default_params
    gauss = galsim.Gaussian(flux=1, sigma=1, gsparams=default_params)
    gauss.drawImage(myImg,scale=0.2, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Gaussian with default_params disagrees with expected result")
    gauss = galsim.Gaussian(flux=1, sigma=1, gsparams=galsim.GSParams())
    gauss.drawImage(myImg,scale=0.2, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Gaussian with GSParams() disagrees with expected result")

    # Use non-unity values.
    gauss = galsim.Gaussian(flux=1.7, sigma=2.3)
    gsp = galsim.GSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)
    gauss2 = galsim.Gaussian(flux=1.7, sigma=2.3, gsparams=gsp)
    assert gauss2 != gauss
    assert gauss2 == gauss.withGSParams(gsp)
    check_basic(gauss, "Gaussian")

    # Test photon shooting.
    do_shoot(gauss,myImg,"Gaussian")

    # Test kvalues
    do_kvalue(gauss,myImg,"Gaussian")

    # Check picklability
    do_pickle(galsim.GSParams())  # Check GSParams explicitly here too.
    do_pickle(galsim.GSParams(
        minimum_fft_size = 12,
        maximum_fft_size = 40,
        folding_threshold = 1.e-1,
        maxk_threshold = 2.e-1,
        kvalue_accuracy = 3.e-1,
        xvalue_accuracy = 4.e-1,
        shoot_accuracy = 5.e-1,
        realspace_relerr = 6.e-1,
        realspace_abserr = 7.e-1,
        integration_relerr = 8.e-1,
        integration_abserr = 9.e-1))
    do_pickle(gauss, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(gauss)

    # Should raise an exception if >=2 radii are provided.
    assert_raises(TypeError, galsim.Gaussian, sigma=3, half_light_radius=1, fwhm=2)
    assert_raises(TypeError, galsim.Gaussian, half_light_radius=1, fwhm=2)
    assert_raises(TypeError, galsim.Gaussian, sigma=3, fwhm=2)
    assert_raises(TypeError, galsim.Gaussian, sigma=3, half_light_radius=1)
    # Or none.
    assert_raises(TypeError, galsim.Gaussian)

    # Finally, test the noise property for things that don't have any noise set.
    assert gauss.noise is None
    # And accessing the attribute from the class should indicate that it is a lazyproperty
    assert 'lazy_property' in str(galsim.GSObject._noise)

    # And check that trying to use GSObject directly is an error.
    assert_raises(NotImplementedError, galsim.GSObject)
Exemple #9
0
from scipy import optimize
import galsim

import galsim.wfirst as wfirst

filters = wfirst.getBandpasses(AB_zeropoint=True)

N = 1
k = 64
base_size = 1.5 * k + 3  ## odd, so peak flux is in one pixel
pixel_scale = 0.11 / N
flux_dict = {}
new_params = galsim.hsm.HSMParams(max_amoment=60000000,
                                  max_mom2_iter=1000000000,
                                  max_moment_nsig2=25)
big_fft_params = galsim.GSParams(maximum_fft_size=int(512 * k))
e = (0., 0.)

index_dict = {}
i = 0
bandpass = ['Y106', 'J129', 'F184', 'H158']
mags = [18.3]
for lam in bandpass:
    for mag in mags:
        index_dict[i] = (lam, mag)
        i += 1


def flux_function(index):
    lam, mag = index_dict[index]
    f = filters[lam]
Exemple #10
0
def test_autoconvolve():
    """Test that auto-convolution works the same as convolution with itself.
    """
    import time
    t1 = time.time()

    mySBP = galsim.SBMoffat(beta=3.8, fwhm=1.3, flux=5)
    myConv = galsim.SBConvolve([mySBP, mySBP])
    myImg1 = galsim.ImageF(80, 80, scale=0.4)
    myConv.draw(myImg1.view())
    myAutoConv = galsim.SBAutoConvolve(mySBP)
    myImg2 = galsim.ImageF(80, 80, scale=0.4)
    myAutoConv.draw(myImg2.view())
    printval(myImg1, myImg2)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Moffat convolved with self disagrees with SBAutoConvolve result")

    # Repeat with the GSObject version of this:
    psf = galsim.Moffat(beta=3.8, fwhm=1.3, flux=5)
    conv = galsim.Convolve([psf, psf])
    conv.draw(myImg1)
    conv2 = galsim.AutoConvolve(psf)
    conv2.draw(myImg2)
    printval(myImg1, myImg2)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg="Moffat convolved with self disagrees with AutoConvolve result"
    )

    # Check with default_params
    conv = galsim.AutoConvolve(psf, gsparams=default_params)
    conv.draw(myImg1)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Using AutoConvolve with default_params disagrees with expected result"
    )
    conv = galsim.AutoConvolve(psf, gsparams=galsim.GSParams())
    conv.draw(myImg1)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Using AutoConvolve with GSParams() disagrees with expected result")

    # For a symmetric profile, AutoCorrelate is the same thing:
    conv2 = galsim.AutoCorrelate(psf)
    conv2.draw(myImg2)
    printval(myImg1, myImg2)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg="Moffat convolved with self disagrees with AutoCorrelate result"
    )

    # And check AutoCorrelate with gsparams:
    conv2 = galsim.AutoCorrelate(psf, gsparams=default_params)
    conv2.draw(myImg1)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Using AutoCorrelate with default_params disagrees with expected result"
    )
    conv2 = galsim.AutoCorrelate(psf, gsparams=galsim.GSParams())
    conv2.draw(myImg1)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Using AutoCorrelate with GSParams() disagrees with expected result")

    # Test photon shooting.
    do_shoot(conv2, myImg2, "AutoConvolve(Moffat)")

    # Also check AutoConvolve with an asymmetric profile.
    # (AutoCorrelate with this profile is done below...)
    obj1 = galsim.Gaussian(sigma=3., flux=4)
    obj1.applyShift(-0.2, -0.4)
    obj2 = galsim.Gaussian(sigma=6., flux=1.3)
    obj2.applyShift(0.3, 0.3)
    add = galsim.Add(obj1, obj2)
    conv = galsim.Convolve([add, add])
    conv.draw(myImg1)
    corr = galsim.AutoConvolve(add)
    corr.draw(myImg2)
    printval(myImg1, myImg2)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Asymmetric sum of Gaussians convolved with self disagrees with " +
        "AutoConvolve result")

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
def make_a_galaxy(ud, this_im_wcs, psf, affine):
    """
    Method to make a single galaxy object and return stamp for 
    injecting into larger GalSim image
    """
    # Choose a random RA, Dec around the sky_center.
    # Note that for this to come out close to a square shape, we need to account for the
    # cos(dec) part of the metric: ds^2 = dr^2 + r^2 d(dec)^2 + r^2 cos^2(dec) d(ra)^2
    # So need to calculate dec first.
    center_dec = this_im_wcs.center.dec
    center_ra = this_im_wcs.center.ra
    dec = center_dec + (ud() - 0.3) * image_ysize_arcsec * galsim.arcsec
    ra = center_ra + (
        ud() - 0.3) * image_xsize_arcsec / numpy.cos(dec) * galsim.arcsec

    world_pos = galsim.CelestialCoord(ra, dec)

    # We will need the image position as well, so use the wcs to get that
    image_pos = this_im_wcs.posToImage(world_pos)

    # We also need this in the tangent plane, which we call "world coordinates" here,
    # since the PowerSpectrum class is really defined on that plane, not in (ra,dec).
    # This is still an x/y corrdinate
    uv_pos = affine.toWorld(image_pos)

    # Draw the redshift from a power law distribution: N(f) ~ f^-2
    # TAKEN FROM DEMO9.PY
    redshift_dist = galsim.DistDeviate(ud,
                                       function=lambda x: x**-2,
                                       x_min=0.3,
                                       x_max=1.0)
    gal_z = redshift_dist()
    try:
        # Get the reduced shears and magnification at this point
        nfw_shear, mu = nfw_lensing(nfw, uv_pos, gal_z)
        g1 = nfw_shear.g1
        g2 = nfw_shear.g2

        binom = galsim.BinomialDeviate(ud, N=1, p=0.5)
        real = binom()

        if real:
            # For real galaxies, we will want to whiten the noise in the image (below).
            gal = cosmos_cat.makeGalaxy(gal_type='real',
                                        rng=ud,
                                        noise_pad_size=20)
        else:
            gal = cosmos_cat.makeGalaxy(gal_type='parametric', rng=ud)

        # Apply a random rotation
        theta = ud() * 2.0 * numpy.pi * galsim.radians
        gal = gal.rotate(theta)

        # Rescale the flux to match the observed A2218 flux. The flux of gal can't be edited directly,
        # so we resort to the following kludge.
        # This automatically scales up the noise variance by flux_scaling**2.

        gal_flux_dist = galsim.DistDeviate(
            ud,
            function=
            '/Users/jemcclea/Research/GalSim/examples/output/empirical_psfs/v3/gal_flux300_prob.txt'
        )
        gal_flux = gal_flux_dist()

        flux_scaling = gal_flux / gal.flux * (exp_time / 300.)
        gal *= flux_scaling

        # Apply the cosmological (reduced) shear and magnification at this position using a single
        # GSObject method.
        try:
            gal = gal.lens(g1, g2, mu)
        except:
            print("could not lens galaxy, setting default values...")
            g1 = 0.0
            g2 = 0.0
            mu = 1.0

        # Generate PSF at location of galaxy
        # Convolve galaxy image with the PSF.
        this_psf = psf.getPSF(image_pos)
        #final_psf=galsim.Convolve(this_psf,optics)
        gsp = galsim.GSParams(maximum_fft_size=16384)
        final = galsim.Convolve([this_psf, gal], gsparams=gsp)

        # Account for the fractional part of the position
        # cf. demo9.py for an explanation of this nominal position stuff.
        x_nominal = image_pos.x + 0.5
        y_nominal = image_pos.y + 0.5
        ix_nominal = int(math.floor(x_nominal + 0.5))
        iy_nominal = int(math.floor(y_nominal + 0.5))
        dx = x_nominal - ix_nominal
        dy = y_nominal - iy_nominal
        offset = galsim.PositionD(dx, dy)
        position = [ix_nominal, iy_nominal, ra.deg, dec.deg]
    except:
        pdb.set_trace()
    # We use method='no_pixel' here because the SDSS PSF image that we are using includes the
    # pixel response already.
    stamp = final.drawImage(wcs=this_im_wcs.local(image_pos),
                            offset=offset,
                            method='no_pixel')

    # If desired, one can also draw the PSF and output its moments too, as:
    #  psf_stamp = psf.drawImage(scale=0.206, offset=offset, method='no_pixel')

    # Recenter the stamp at the desired position:
    stamp.setCenter(ix_nominal, iy_nominal)

    new_variance = 0.0

    if real:
        if True:
            # We use the symmetrizing option here.
            new_variance = stamp.symmetrizeNoise(final.noise, 8)
        else:
            # Here is how you would do it if you wanted to fully whiten the image.
            new_variance = stamp.whitenNoise(final.noise)
    print("noise variance is %f" % new_variance)
    galaxy_truth = truth()
    galaxy_truth.ra = ra.deg
    galaxy_truth.dec = dec.deg
    galaxy_truth.x = ix_nominal
    galaxy_truth.y = iy_nominal
    galaxy_truth.g1 = g1
    galaxy_truth.g2 = g2
    galaxy_truth.mu = mu
    galaxy_truth.z = gal_z
    galaxy_truth.flux = stamp.added_flux
    galaxy_truth.variance = new_variance

    return stamp, galaxy_truth
Exemple #12
0
def test_add():
    """Test the addition of two rescaled Gaussian profiles against a known double Gaussian result.
    """
    import time
    t1 = time.time()
    mySBP = galsim.SBGaussian(flux=0.75, sigma=1)
    mySBP2 = galsim.SBGaussian(flux=0.25, sigma=3)
    myAdd = galsim.SBAdd([mySBP, mySBP2])
    savedImg = galsim.fits.read(os.path.join(imgdir, "double_gaussian.fits"))
    myImg = galsim.ImageF(savedImg.bounds, scale=0.2)
    myAdd.draw(myImg.view())
    printval(myImg, savedImg)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Addition of two rescaled Gaussian profiles disagrees with expected result"
    )

    # Repeat with the GSObject version of this:
    gauss1 = galsim.Gaussian(flux=0.75, sigma=1)
    gauss2 = galsim.Gaussian(flux=0.25, sigma=3)
    sum = galsim.Add(gauss1, gauss2)
    sum.draw(myImg,
             dx=0.2,
             normalization="surface brightness",
             use_true_center=False)
    printval(myImg, savedImg)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject Add(gauss1,gauss2) disagrees with expected result")

    # Check with default_params
    sum = galsim.Add(gauss1, gauss2, gsparams=default_params)
    sum.draw(myImg,
             dx=0.2,
             normalization="surface brightness",
             use_true_center=False)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject Add(gauss1,gauss2) with default_params disagrees with "
        "expected result")
    sum = galsim.Add(gauss1, gauss2, gsparams=galsim.GSParams())
    sum.draw(myImg,
             dx=0.2,
             normalization="surface brightness",
             use_true_center=False)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject Add(gauss1,gauss2) with GSParams() disagrees with "
        "expected result")

    # Other ways to do the sum:
    sum = gauss1 + gauss2
    sum.draw(myImg,
             dx=0.2,
             normalization="surface brightness",
             use_true_center=False)
    printval(myImg, savedImg)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg="Using GSObject gauss1 + gauss2 disagrees with expected result"
    )
    sum = gauss1.copy()
    sum += gauss2
    sum.draw(myImg,
             dx=0.2,
             normalization="surface brightness",
             use_true_center=False)
    printval(myImg, savedImg)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject sum = gauss1; sum += gauss2 disagrees with expected result"
    )
    sum = galsim.Add([gauss1, gauss2])
    sum.draw(myImg,
             dx=0.2,
             normalization="surface brightness",
             use_true_center=False)
    printval(myImg, savedImg)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject Add([gauss1,gauss2]) disagrees with expected result")
    gauss1 = galsim.Gaussian(flux=1, sigma=1)
    gauss2 = galsim.Gaussian(flux=1, sigma=3)
    sum = 0.75 * gauss1 + 0.25 * gauss2
    sum.draw(myImg,
             dx=0.2,
             normalization="surface brightness",
             use_true_center=False)
    printval(myImg, savedImg)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject 0.75 * gauss1 + 0.25 * gauss2 disagrees with expected result"
    )
    sum = 0.75 * gauss1
    sum += 0.25 * gauss2
    sum.draw(myImg,
             dx=0.2,
             normalization="surface brightness",
             use_true_center=False)
    printval(myImg, savedImg)
    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        5,
        err_msg=
        "Using GSObject sum += 0.25 * gauss2 disagrees with expected result")

    # Test photon shooting.
    do_shoot(sum, myImg, "sum of 2 Gaussians")

    # Test kvalues
    do_kvalue(sum, "sum of 2 Gaussians")

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Exemple #13
0
def test_realspace_shearconvolve():
    """Test the real-space convolution of a sheared Gaussian and a Box SBProfile against a 
       known result.
    """
    import time
    t1 = time.time()
    psf = galsim.SBGaussian(flux=1, sigma=1)
    e1 = 0.04
    e2 = 0.0
    myShear = galsim.Shear(e1=e1, e2=e2)
    psf.applyShear(myShear._shear)
    pix = galsim.SBBox(xw=0.2, yw=0.2, flux=1.)
    conv = galsim.SBConvolve([psf, pix], real_space=True)
    saved_img = galsim.fits.read(
        os.path.join(imgdir, "gauss_smallshear_convolve_box.fits"))
    img = galsim.ImageF(saved_img.bounds, scale=0.2)
    conv.draw(img.view())
    printval(img, saved_img)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Sheared Gaussian convolved with Box SBProfile disagrees with expected result"
    )

    # Repeat with the GSObject version of this:
    psf = galsim.Gaussian(flux=1, sigma=1)
    psf.applyShear(e1=e1, e2=e2)
    pixel = galsim.Pixel(xw=0.2, yw=0.2, flux=1.)
    conv = galsim.Convolve([psf, pixel], real_space=True)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) disagrees with expected result")

    # Check with default_params
    conv = galsim.Convolve([psf, pixel],
                           real_space=True,
                           gsparams=default_params)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) with default_params disagrees with "
        "expected result")
    conv = galsim.Convolve([psf, pixel],
                           real_space=True,
                           gsparams=galsim.GSParams())
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) with GSParams() disagrees with "
        "expected result")

    # Other ways to do the convolution:
    conv = galsim.Convolve(psf, pixel, real_space=True)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve(psf,pixel) disagrees with expected result")

    # The real-space convolution algorithm is not (trivially) independent of the order of
    # the two things being convolved.  So check the opposite order.
    conv = galsim.Convolve([pixel, psf], real_space=True)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([pixel,psf]) disagrees with expected result")

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Exemple #14
0
def test_convolve():
    """Test the convolution of a Moffat and a Box SBProfile against a known result.
    """
    import time
    t1 = time.time()
    # Code was formerly:
    # mySBP = galsim.SBMoffat(beta=1.5, truncationFWHM=4, flux=1, half_light_radius=1)
    #
    # ...but this is no longer quite so simple since we changed the handling of trunc to be in
    # physical units.  However, the same profile can be constructed using
    # fwhm=1.0927449310213702,
    # as calculated by interval bisection in devutils/external/calculate_moffat_radii.py
    fwhm_backwards_compatible = 1.0927449310213702
    mySBP = galsim.SBMoffat(beta=1.5,
                            fwhm=fwhm_backwards_compatible,
                            trunc=4 * fwhm_backwards_compatible,
                            flux=1)
    mySBP2 = galsim.SBBox(xw=0.2, yw=0.2, flux=1.)
    myConv = galsim.SBConvolve([mySBP, mySBP2])
    # Using an exact Maple calculation for the comparison.  Only accurate to 4 decimal places.
    savedImg = galsim.fits.read(os.path.join(imgdir, "moffat_pixel.fits"))
    myImg = galsim.ImageF(savedImg.bounds, scale=0.2)
    myConv.draw(myImg.view())
    printval(myImg, savedImg)

    np.testing.assert_array_almost_equal(
        myImg.array,
        savedImg.array,
        4,
        err_msg=
        "Moffat convolved with Box SBProfile disagrees with expected result")

    # Repeat with the GSObject version of this:
    psf = galsim.Moffat(beta=1.5,
                        fwhm=fwhm_backwards_compatible,
                        trunc=4 * fwhm_backwards_compatible,
                        flux=1)
    pixel = galsim.Pixel(xw=0.2, yw=0.2, flux=1.)
    # Note: Since both of these have hard edges, GalSim wants to do this with real_space=True.
    # Here we are intentionally tesing the Fourier convolution, so we want to suppress the
    # warning that GalSim emits.
    import warnings
    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        # We'll do the real space convolution below
        conv = galsim.Convolve([psf, pixel], real_space=False)
        conv.draw(myImg,
                  dx=0.2,
                  normalization="surface brightness",
                  use_true_center=False)
        np.testing.assert_array_almost_equal(
            myImg.array,
            savedImg.array,
            4,
            err_msg=
            "Using GSObject Convolve([psf,pixel]) disagrees with expected result"
        )

        # Other ways to do the convolution:
        conv = galsim.Convolve(psf, pixel, real_space=False)
        conv.draw(myImg,
                  dx=0.2,
                  normalization="surface brightness",
                  use_true_center=False)
        np.testing.assert_array_almost_equal(
            myImg.array,
            savedImg.array,
            4,
            err_msg=
            "Using GSObject Convolve(psf,pixel) disagrees with expected result"
        )

        # Check with default_params
        conv = galsim.Convolve([psf, pixel],
                               real_space=False,
                               gsparams=default_params)
        conv.draw(myImg,
                  dx=0.2,
                  normalization="surface brightness",
                  use_true_center=False)
        np.testing.assert_array_almost_equal(
            myImg.array,
            savedImg.array,
            4,
            err_msg=
            "Using GSObject Convolve([psf,pixel]) with default_params disagrees with"
            "expected result")
        conv = galsim.Convolve([psf, pixel],
                               real_space=False,
                               gsparams=galsim.GSParams())
        conv.draw(myImg,
                  dx=0.2,
                  normalization="surface brightness",
                  use_true_center=False)
        np.testing.assert_array_almost_equal(
            myImg.array,
            savedImg.array,
            4,
            err_msg=
            "Using GSObject Convolve([psf,pixel]) with GSParams() disagrees with"
            "expected result")

    # Test photon shooting.
    do_shoot(conv, myImg, "Moffat * Pixel")

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Exemple #15
0
def test_psf_config():
    """Test building the two PSF types using the config layer.
    """
    data_dir = 'des_data'
    psfex_file = "DECam_00154912_12_psfcat.psf"
    fitpsf_file = "DECam_00154912_12_fitpsf.fits"
    wcs_file = "DECam_00154912_12_header.fits"

    image_pos = galsim.PositionD(123.45, 543.21)

    config = {
        'input': {
            'des_shapelet': {
                'dir': data_dir,
                'file_name': fitpsf_file
            },
            'des_psfex': [
                {
                    'dir': data_dir,
                    'file_name': psfex_file
                },
                {
                    'dir': data_dir,
                    'file_name': psfex_file,
                    'image_file_name': wcs_file
                },
            ]
        },
        'psf1': {
            'type': 'DES_Shapelet'
        },
        'psf2': {
            'type': 'DES_PSFEx',
            'num': 0
        },
        'psf3': {
            'type': 'DES_PSFEx',
            'num': 1
        },
        'psf4': {
            'type': 'DES_Shapelet',
            'image_pos': galsim.PositionD(567, 789),
            'flux': 179,
            'gsparams': {
                'folding_threshold': 1.e-4
            }
        },
        'psf5': {
            'type': 'DES_PSFEx',
            'image_pos': galsim.PositionD(789, 567),
            'flux': 388,
            'gsparams': {
                'folding_threshold': 1.e-4
            }
        },
        'bad1': {
            'type': 'DES_Shapelet',
            'image_pos': galsim.PositionD(5670, 789)
        },

        # This would normally be set by the config processing.  Set it manually here.
        'image_pos': image_pos,
    }

    galsim.config.ProcessInput(config)

    psf1a = galsim.config.BuildGSObject(config, 'psf1')[0]
    fitpsf = galsim.des.DES_Shapelet(fitpsf_file, dir=data_dir)
    psf1b = fitpsf.getPSF(image_pos)
    gsobject_compare(psf1a, psf1b)

    psf2a = galsim.config.BuildGSObject(config, 'psf2')[0]
    psfex0 = galsim.des.DES_PSFEx(psfex_file, dir=data_dir)
    psf2b = psfex0.getPSF(image_pos)
    gsobject_compare(psf2a, psf2b)

    psf3a = galsim.config.BuildGSObject(config, 'psf3')[0]
    psfex1 = galsim.des.DES_PSFEx(psfex_file, wcs_file, dir=data_dir)
    psf3b = psfex1.getPSF(image_pos)
    gsobject_compare(psf3a, psf3b)

    gsparams = galsim.GSParams(folding_threshold=1.e-4)
    psf4a = galsim.config.BuildGSObject(config, 'psf4')[0]
    psf4b = fitpsf.getPSF(galsim.PositionD(567, 789),
                          gsparams=gsparams).withFlux(179)
    gsobject_compare(psf4a, psf4b)

    # Insert a wcs for thes last one.
    config['wcs'] = galsim.FitsWCS(os.path.join(data_dir, wcs_file))
    config = galsim.config.CleanConfig(config)
    galsim.config.ProcessInput(config)
    psfex2 = galsim.des.DES_PSFEx(psfex_file, dir=data_dir, wcs=config['wcs'])
    psf5a = galsim.config.BuildGSObject(config, 'psf5')[0]
    psf5b = psfex2.getPSF(galsim.PositionD(789, 567),
                          gsparams=gsparams).withFlux(388)
    gsobject_compare(psf5a, psf5b)

    del config['image_pos']
    galsim.config.RemoveCurrent(config)
    with assert_raises(galsim.GalSimConfigError):
        galsim.config.BuildGSObject(config, 'psf1')[0]
    with assert_raises(galsim.GalSimConfigError):
        galsim.config.BuildGSObject(config, 'psf2')[0]
    with assert_raises(galsim.config.gsobject.SkipThisObject):
        galsim.config.BuildGSObject(config, 'bad1')[0]
Exemple #16
0
def test_gsparams():
    """Test withGSParams with some non-default gsparams
    """
    obj1 = galsim.Exponential(half_light_radius=1.7)
    obj2 = galsim.Pixel(scale=0.2)
    gsp = galsim.GSParams(folding_threshold=1.e-4,
                          maxk_threshold=1.e-4,
                          maximum_fft_size=1.e4)
    gsp2 = galsim.GSParams(folding_threshold=1.e-2, maxk_threshold=1.e-2)

    # Convolve
    conv = galsim.Convolve(obj1, obj2)
    conv1 = conv.withGSParams(gsp)
    assert conv.gsparams == galsim.GSParams()
    assert conv1.gsparams == gsp
    assert conv1.obj_list[0].gsparams == gsp
    assert conv1.obj_list[1].gsparams == gsp

    conv2 = galsim.Convolve(obj1.withGSParams(gsp), obj2.withGSParams(gsp))
    conv3 = galsim.Convolve(
        galsim.Exponential(half_light_radius=1.7, gsparams=gsp),
        galsim.Pixel(scale=0.2))
    conv4 = galsim.Convolve(obj1, obj2, gsparams=gsp)
    assert conv != conv1
    assert conv1 == conv2
    assert conv1 == conv3
    assert conv1 == conv4
    print('stepk = ', conv.stepk, conv1.stepk)
    assert conv1.stepk < conv.stepk
    print('maxk = ', conv.maxk, conv1.maxk)
    assert conv1.maxk > conv.maxk

    conv5 = galsim.Convolve(obj1, obj2, gsparams=gsp, propagate_gsparams=False)
    assert conv5 != conv4
    assert conv5.gsparams == gsp
    assert conv5.obj_list[0].gsparams == galsim.GSParams()
    assert conv5.obj_list[1].gsparams == galsim.GSParams()

    conv6 = conv5.withGSParams(gsp2)
    assert conv6 != conv5
    assert conv6.gsparams == gsp2
    assert conv6.obj_list[0].gsparams == galsim.GSParams()
    assert conv6.obj_list[1].gsparams == galsim.GSParams()

    # AutoConvolve
    conv = galsim.AutoConvolve(obj1)
    conv1 = conv.withGSParams(gsp)
    assert conv.gsparams == galsim.GSParams()
    assert conv1.gsparams == gsp
    assert conv1.orig_obj.gsparams == gsp

    conv2 = galsim.AutoConvolve(obj1.withGSParams(gsp))
    conv3 = galsim.AutoConvolve(obj1, gsparams=gsp)
    assert conv != conv1
    assert conv1 == conv2
    assert conv1 == conv3
    print('stepk = ', conv.stepk, conv1.stepk)
    assert conv1.stepk < conv.stepk
    print('maxk = ', conv.maxk, conv1.maxk)
    assert conv1.maxk > conv.maxk

    conv4 = galsim.AutoConvolve(obj1, gsparams=gsp, propagate_gsparams=False)
    assert conv4 != conv3
    assert conv4.gsparams == gsp
    assert conv4.orig_obj.gsparams == galsim.GSParams()

    conv5 = conv4.withGSParams(gsp2)
    assert conv5 != conv4
    assert conv5.gsparams == gsp2
    assert conv5.orig_obj.gsparams == galsim.GSParams()

    # AutoCorrelate
    conv = galsim.AutoCorrelate(obj1)
    conv1 = conv.withGSParams(gsp)
    assert conv.gsparams == galsim.GSParams()
    assert conv1.gsparams == gsp
    assert conv1.orig_obj.gsparams == gsp

    conv2 = galsim.AutoCorrelate(obj1.withGSParams(gsp))
    conv3 = galsim.AutoCorrelate(obj1, gsparams=gsp)
    assert conv != conv1
    assert conv1 == conv2
    assert conv1 == conv3
    print('stepk = ', conv.stepk, conv1.stepk)
    assert conv1.stepk < conv.stepk
    print('maxk = ', conv.maxk, conv1.maxk)
    assert conv1.maxk > conv.maxk

    conv4 = galsim.AutoCorrelate(obj1, gsparams=gsp, propagate_gsparams=False)
    assert conv4 != conv3
    assert conv4.gsparams == gsp
    assert conv4.orig_obj.gsparams == galsim.GSParams()

    conv5 = conv4.withGSParams(gsp2)
    assert conv5 != conv4
    assert conv5.gsparams == gsp2
    assert conv5.orig_obj.gsparams == galsim.GSParams()

    # Deconvolve
    conv = galsim.Convolve(obj1, galsim.Deconvolve(obj2))
    conv1 = conv.withGSParams(gsp)
    assert conv.gsparams == galsim.GSParams()
    assert conv1.gsparams == gsp
    assert conv1.obj_list[0].gsparams == gsp
    assert conv1.obj_list[1].gsparams == gsp
    assert conv1.obj_list[1].orig_obj.gsparams == gsp

    conv2 = galsim.Convolve(obj1, galsim.Deconvolve(obj2.withGSParams(gsp)))
    conv3 = galsim.Convolve(obj1.withGSParams(gsp), galsim.Deconvolve(obj2))
    conv4 = galsim.Convolve(obj1, galsim.Deconvolve(obj2, gsparams=gsp))
    assert conv != conv1
    assert conv1 == conv2
    assert conv1 == conv3
    assert conv1 == conv4
    print('stepk = ', conv.stepk, conv1.stepk)
    assert conv1.stepk < conv.stepk
    print('maxk = ', conv.maxk, conv1.maxk)
    assert conv1.maxk > conv.maxk

    conv5 = galsim.Convolve(
        obj1, galsim.Deconvolve(obj2, gsparams=gsp, propagate_gsparams=False))
    assert conv5 != conv4
    assert conv5.gsparams == gsp
    assert conv5.obj_list[0].gsparams == gsp
    assert conv5.obj_list[1].gsparams == gsp
    assert conv5.obj_list[1].orig_obj.gsparams == galsim.GSParams()

    conv6 = conv5.withGSParams(gsp2)
    assert conv6 != conv5
    assert conv6.gsparams == gsp2
    assert conv6.obj_list[0].gsparams == gsp2
    assert conv6.obj_list[1].gsparams == gsp2
    assert conv6.obj_list[1].orig_obj.gsparams == galsim.GSParams()

    # FourierSqrt
    conv = galsim.Convolve(obj1, galsim.FourierSqrt(obj2))
    conv1 = conv.withGSParams(gsp)
    assert conv.gsparams == galsim.GSParams()
    assert conv1.gsparams == gsp
    assert conv1.obj_list[0].gsparams == gsp
    assert conv1.obj_list[1].gsparams == gsp
    assert conv1.obj_list[1].orig_obj.gsparams == gsp

    conv2 = galsim.Convolve(obj1, galsim.FourierSqrt(obj2.withGSParams(gsp)))
    conv3 = galsim.Convolve(obj1.withGSParams(gsp), galsim.FourierSqrt(obj2))
    conv4 = galsim.Convolve(obj1, galsim.FourierSqrt(obj2, gsparams=gsp))
    assert conv != conv1
    assert conv1 == conv2
    assert conv1 == conv3
    assert conv1 == conv4
    print('stepk = ', conv.stepk, conv1.stepk)
    assert conv1.stepk < conv.stepk
    print('maxk = ', conv.maxk, conv1.maxk)
    assert conv1.maxk > conv.maxk

    conv5 = galsim.Convolve(
        obj1, galsim.FourierSqrt(obj2, gsparams=gsp, propagate_gsparams=False))
    assert conv5 != conv4
    assert conv5.gsparams == gsp
    assert conv5.obj_list[0].gsparams == gsp
    assert conv5.obj_list[1].gsparams == gsp
    assert conv5.obj_list[1].orig_obj.gsparams == galsim.GSParams()

    conv6 = conv5.withGSParams(gsp2)
    assert conv6 != conv5
    assert conv6.gsparams == gsp2
    assert conv6.obj_list[0].gsparams == gsp2
    assert conv6.obj_list[1].gsparams == gsp2
    assert conv6.obj_list[1].orig_obj.gsparams == galsim.GSParams()
Exemple #17
0
def main(argv):
    """
    Make a fits image cube where each frame has two images of the same galaxy drawn
    with regular FFT convolution and with photon shooting.

    We do this for 5 different PSFs and 5 different galaxies, each with 4 different (random)
    fluxes, sizes, and shapes.
    """
    logging.basicConfig(format="%(message)s",
                        level=logging.INFO,
                        stream=sys.stdout)
    logger = logging.getLogger("demo7")

    # To turn off logging:
    #logger.propagate = False

    # To turn on the debugging messages:
    #logger.setLevel(logging.DEBUG)

    # Define some parameters we'll use below.

    # Make output directory if not already present.
    if not os.path.isdir('output'):
        os.mkdir('output')

    file_name = os.path.join('output', 'cube_phot.fits.gz')

    random_seed = 553728
    sky_level = 1.e4  # ADU / arcsec^2
    pixel_scale = 0.28  # arcsec
    nx = 64
    ny = 64

    gal_flux_min = 1.e4  # Range for galaxy flux
    gal_flux_max = 1.e5
    gal_hlr_min = 0.3  # arcsec
    gal_hlr_max = 1.3  # arcsec
    gal_e_min = 0.  # Range for ellipticity
    gal_e_max = 0.8

    psf_fwhm = 0.65  # arcsec

    # This script is set up as a comparison between using FFTs for doing the convolutions and
    # shooting photons.  The two methods have trade-offs in speed and accuracy which vary
    # with the kind of profile being drawn and the S/N of the object, among other factors.
    # In addition, for each method, there are a number of parameters GalSim uses that control
    # aspects of the calculation that further affect the speed and accuracy.
    #
    # We encapsulate these parameters with an object called GSParams.  The default values
    # are intended to be accurate enough for normal precision shear tests, without sacrificing
    # too much speed.
    #
    # Any PSF or galaxy object can be given a gsparams argument on construction that can
    # have different values to make the calculation more or less accurate (typically trading
    # off for speed or memory).
    #
    # In this script, we adjust some of the values slightly, just to show you how it works.
    # You could play around with these values and see what effect they have on the drawn images.
    # Usually, it requires a pretty drastic change in these parameters for you to be able to
    # notice the difference by eye.  But subtle effects that may impact the shapes of galaxies
    # can happen well before then.

    # Type help(galsim.GSParams) for the complete list of parameters and more detailed
    # documentation, including the default values for each parameter.
    gsparams = galsim.GSParams(
        folding_threshold=
        1.e-2,  # maximum fractional flux that may be folded around edge of FFT
        maxk_threshold=
        2.e-3,  # k-values less than this may be excluded off edge of FFT
        xvalue_accuracy=
        1.e-4,  # approximations in real space aim to be this accurate
        kvalue_accuracy=
        1.e-4,  # approximations in fourier space aim to be this accurate
        shoot_accuracy=
        1.e-4,  # approximations in photon shooting aim to be this accurate
        minimum_fft_size=64)  # minimum size of ffts

    logger.info('Starting demo script 7')

    # Make the PSF profiles:
    psf1 = galsim.Gaussian(fwhm=psf_fwhm, gsparams=gsparams)
    psf2 = galsim.Moffat(fwhm=psf_fwhm, beta=2.4, gsparams=gsparams)
    psf3_inner = galsim.Gaussian(fwhm=psf_fwhm, flux=0.8, gsparams=gsparams)
    psf3_outer = galsim.Gaussian(fwhm=2 * psf_fwhm,
                                 flux=0.2,
                                 gsparams=gsparams)
    psf3 = psf3_inner + psf3_outer
    atmos = galsim.Gaussian(fwhm=psf_fwhm, gsparams=gsparams)
    # The OpticalPSF and set of Zernike values chosen below correspond to a reasonably well aligned,
    # smallish ~0.3m / 12 inch diameter telescope with a central obscuration of ~0.12m or 5 inches
    # diameter, being used in optical wavebands.
    # In the Noll convention, the value of the Zernike coefficient also gives the RMS optical path
    # difference across a circular pupil.  An RMS difference of ~0.5 or larger indicates that parts
    # of the wavefront are in fully destructive interference, and so we might expect aberrations to
    # become strong when Zernike aberrations summed in quadrature approach 0.5 wave.
    # The aberrations chosen in this case correspond to operating close to a 0.25 wave RMS optical
    # path difference.  Unlike in demo3, we specify the aberrations by making a list that we pass
    # in using the 'aberrations' kwarg.  The order of aberrations starting from index 4 is defocus,
    # astig1, astig2, coma1, coma2, trefoil1, trefoil2, spher as in the Noll convention.
    # We ignore the first 4 values so that the index number corresponds to the Zernike index
    # in the Noll convention. This will be particularly convenient once we start allowing
    # coefficients beyond spherical (index 11).  c.f. The Wikipedia page about the Noll indices:
    #
    #     http://en.wikipedia.org/wiki/Zernike_polynomials#Zernike_polynomials

    aberrations = [0.0] * 12  # Set the initial size.
    aberrations[4] = 0.06  # Noll index 4 = Defocus
    aberrations[5:7] = [0.12, -0.08]  # Noll index 5,6 = Astigmatism
    aberrations[7:9] = [0.07, 0.04]  # Noll index 7,8 = Coma
    aberrations[11] = -0.13  # Noll index 11 = Spherical
    # You could also define these all at once if that is more convenient:
    #aberrations = [0.0, 0.0, 0.0, 0.0, 0.06, 0.12, -0.08, 0.07, 0.04, 0.0, 0.0, -0.13]

    optics = galsim.OpticalPSF(lam_over_diam=0.6 * psf_fwhm,
                               obscuration=0.4,
                               aberrations=aberrations,
                               gsparams=gsparams)
    psf4 = galsim.Convolve([atmos, optics
                            ])  # Convolve inherits the gsparams from the first
    # item in the list.  (Or you can supply a gsparams
    # argument explicitly if you want to override this.)
    atmos = galsim.Kolmogorov(fwhm=psf_fwhm, gsparams=gsparams)
    optics = galsim.Airy(lam_over_diam=0.3 * psf_fwhm, gsparams=gsparams)
    psf5 = galsim.Convolve([atmos, optics])
    psfs = [psf1, psf2, psf3, psf4, psf5]
    psf_names = [
        "Gaussian", "Moffat", "Double Gaussian", "OpticalPSF",
        "Kolmogorov * Airy"
    ]
    psf_times = [0, 0, 0, 0, 0]
    psf_fft_times = [0, 0, 0, 0, 0]
    psf_phot_times = [0, 0, 0, 0, 0]

    # Make the galaxy profiles:
    gal1 = galsim.Gaussian(half_light_radius=1, gsparams=gsparams)
    gal2 = galsim.Exponential(half_light_radius=1, gsparams=gsparams)
    gal3 = galsim.DeVaucouleurs(half_light_radius=1, gsparams=gsparams)
    gal4 = galsim.Sersic(half_light_radius=1, n=2.5, gsparams=gsparams)
    # A Sersic profile may be truncated if desired.
    # The units for this are expected to be arcsec (or specifically -- whatever units
    # you are using for all the size values as defined by the pixel_scale).
    bulge = galsim.Sersic(half_light_radius=0.7,
                          n=3.2,
                          trunc=8.5,
                          gsparams=gsparams)
    disk = galsim.Sersic(half_light_radius=1.2, n=1.5, gsparams=gsparams)
    gal5 = 0.4 * bulge + 0.6 * disk  # Net half-light radius is only approximate for this one.
    gals = [gal1, gal2, gal3, gal4, gal5]
    gal_names = [
        "Gaussian", "Exponential", "Devaucouleurs", "n=2.5 Sersic",
        "Bulge + Disk"
    ]
    gal_times = [0, 0, 0, 0, 0]
    gal_fft_times = [0, 0, 0, 0, 0]
    gal_phot_times = [0, 0, 0, 0, 0]

    # Other times to keep track of:
    setup_times = 0
    fft_times = 0
    phot_times = 0
    noise_times = 0

    # Loop over combinations of psf, gal, and make 4 random choices for flux, size, shape.
    all_images = []
    k = 0
    for ipsf in range(len(psfs)):
        psf = psfs[ipsf]
        psf_name = psf_names[ipsf]
        logger.info('psf %d: %s', ipsf + 1, psf)
        # Note that this implicitly calls str(psf).  We've made an effort to give all GalSim
        # objects an informative but relatively succinct str representation.  Some details may
        # be missing, but it should look essentially like how you would create the object.
        logger.debug('repr = %r', psf)
        # The repr() version are a bit more pedantic in form and should be completely informative,
        # to the point where two objects that are not identical should never have equal repr
        # strings. As such the repr strings may in some cases be somewhat unwieldy.  For instance,
        # since we set non-default gsparams in these, the repr includes that information, but
        # it is omitted from the str for brevity.
        for igal in range(len(gals)):
            gal = gals[igal]
            gal_name = gal_names[igal]
            logger.info('   galaxy %d: %s', igal + 1, gal)
            logger.debug('   repr = %r', gal)
            for i in range(4):
                logger.debug('      Start work on image %d', i)
                t1 = time.time()

                # Initialize the random number generator we will be using.
                rng = galsim.UniformDeviate(random_seed + k + 1)

                # Generate random variates:
                flux = rng() * (gal_flux_max - gal_flux_min) + gal_flux_min

                # Use a new variable name, since we'll want to keep the original unmodified.
                this_gal = gal.withFlux(flux)

                hlr = rng() * (gal_hlr_max - gal_hlr_min) + gal_hlr_min
                this_gal = this_gal.dilate(hlr)

                beta_ellip = rng() * 2 * math.pi * galsim.radians
                ellip = rng() * (gal_e_max - gal_e_min) + gal_e_min
                gal_shape = galsim.Shear(e=ellip, beta=beta_ellip)
                this_gal = this_gal.shear(gal_shape)

                # Build the final object by convolving the galaxy and PSF.
                final = galsim.Convolve([this_gal, psf])

                # Create the large, double width output image
                # Rather than provide a scale= argument to the drawImage commands, we can also
                # set the pixel scale in the image constructor.
                # Note: You can also change it after the construction with im.scale=pixel_scale
                image = galsim.ImageF(2 * nx + 2, ny, scale=pixel_scale)

                # Assign the following two Image "views", fft_image and phot_image.
                # Using the syntax below, these are views into the larger image.
                # Changes/additions to the sub-images referenced by the views are automatically
                # reflected in the original image.
                fft_image = image[galsim.BoundsI(1, nx, 1, ny)]
                phot_image = image[galsim.BoundsI(nx + 3, 2 * nx + 2, 1, ny)]

                logger.debug(
                    '      Read in training sample galaxy and PSF from file')
                t2 = time.time()

                # Draw the profile
                # This default rendering method (method='auto') usually defaults to FFT, since
                # that is normally the most efficient method.  However, we can also set method
                # to 'fft' explicitly to force it to always use FFTs for the convolution
                # by the pixel response.  (In this case, it doesn't have any effect, since
                # the 'auto' method would have always chosen 'fft' anyway, so this is just
                # for illustrative purposes.)
                final.drawImage(fft_image, method='fft')

                logger.debug(
                    '      Drew fft image.  Total drawn flux = %f.  .flux = %f',
                    fft_image.array.sum(), final.getFlux())
                t3 = time.time()

                # Add Poisson noise
                sky_level_pixel = sky_level * pixel_scale**2
                fft_image.addNoise(
                    galsim.PoissonNoise(rng, sky_level=sky_level_pixel))

                t4 = time.time()

                # The next two lines are just to get the output from this demo script
                # to match the output from the parsing of demo7.yaml.
                rng = galsim.UniformDeviate(random_seed + k + 1)
                rng()
                rng()
                rng()
                rng()

                # Repeat for photon shooting image.
                # The max_extra_noise parameter indicates how much extra noise per pixel we are
                # willing to tolerate.  The sky noise will be adding a variance of sky_level_pixel,
                # so we allow up to 1% of that extra.
                final.drawImage(phot_image,
                                method='phot',
                                max_extra_noise=sky_level_pixel / 100,
                                rng=rng)
                t5 = time.time()

                # For photon shooting, galaxy already has Poisson noise, so we want to make
                # sure not to add that noise again!  Thus, we just add sky noise, which
                # is Poisson with the mean = sky_level_pixel
                pd = galsim.PoissonDeviate(rng, mean=sky_level_pixel)
                # DeviateNoise just adds the action of the given deviate to every pixel.
                phot_image.addNoise(galsim.DeviateNoise(pd))
                # For PoissonDeviate, the mean is not zero, so for a background-subtracted
                # image, we need to subtract the mean back off when we are done.
                phot_image -= sky_level_pixel

                logger.debug(
                    '      Added Poisson noise.  Image fluxes are now %f and %f',
                    fft_image.array.sum(), phot_image.array.sum())
                t6 = time.time()

                # Store that into the list of all images
                all_images += [image]

                k = k + 1
                logger.info(
                    '      %d: flux = %.2e, hlr = %.2f, ellip = (%.2f,%.2f)',
                    k, flux, hlr, gal_shape.getE1(), gal_shape.getE2())
                logger.debug('      Times: %f, %f, %f, %f, %f', t2 - t1,
                             t3 - t2, t4 - t3, t5 - t4, t6 - t5)

                psf_times[ipsf] += t6 - t1
                psf_fft_times[ipsf] += t3 - t2
                psf_phot_times[ipsf] += t5 - t4
                gal_times[igal] += t6 - t1
                gal_fft_times[igal] += t3 - t2
                gal_phot_times[igal] += t5 - t4
                setup_times += t2 - t1
                fft_times += t3 - t2
                phot_times += t5 - t4
                noise_times += t4 - t3 + t6 - t5

    logger.info('Done making images of galaxies')
    logger.info('')
    logger.info('Some timing statistics:')
    logger.info('   Total time for setup steps = %f', setup_times)
    logger.info('   Total time for regular fft drawing = %f', fft_times)
    logger.info('   Total time for photon shooting = %f', phot_times)
    logger.info('   Total time for adding noise = %f', noise_times)
    logger.info('')
    logger.info('Breakdown by PSF type:')
    for ipsf in range(len(psfs)):
        logger.info('   %s: Total time = %f  (fft: %f, phot: %f)',
                    psf_names[ipsf], psf_times[ipsf], psf_fft_times[ipsf],
                    psf_phot_times[ipsf])
    logger.info('')
    logger.info('Breakdown by Galaxy type:')
    for igal in range(len(gals)):
        logger.info('   %s: Total time = %f  (fft: %f, phot: %f)',
                    gal_names[igal], gal_times[igal], gal_fft_times[igal],
                    gal_phot_times[igal])
    logger.info('')

    # Now write the image to disk.
    # With any write command, you can optionally compress the file using several compression
    # schemes:
    #   'gzip' uses gzip on the full output file.
    #   'bzip2' uses bzip2 on the full output file.
    #   'rice' uses rice compression on the image, leaving the fits headers readable.
    #   'gzip_tile' uses gzip in tiles on the output image, leaving the fits headers readable.
    #   'hcompress' uses hcompress on the image, but it is only valid for 2-d data, so it
    #               doesn't work for writeCube.
    #   'plio' uses plio on the image, but it is only valid for positive integer data.
    # Furthermore, the first three have standard filename extensions associated with them,
    # so if you don't specify a compression, but the filename ends with '.gz', '.bz2' or '.fz',
    # the corresponding compression will be selected automatically.
    # In other words, the `compression='gzip'` specification is actually optional here:
    galsim.fits.writeCube(all_images, file_name, compression='gzip')
    logger.info('Wrote fft image to fits data cube %r', file_name)
Exemple #18
0
def test_convolve():
    """Test the convolution of a Moffat and a Box profile against a known result.
    """
    dx = 0.2
    # Using an exact Maple calculation for the comparison.  Only accurate to 4 decimal places.
    savedImg = galsim.fits.read(os.path.join(imgdir, "moffat_pixel.fits"))
    myImg = galsim.ImageF(savedImg.bounds, scale=dx)
    myImg.setCenter(0, 0)

    # Code was formerly:
    # psf = galsim.Moffat(beta=1.5, truncationFWHM=4, flux=1, half_light_radius=1)
    #
    # ...but this is no longer quite so simple since we changed the handling of trunc to be in
    # physical units.  However, the same profile can be constructed using
    # fwhm=1.0927449310213702,
    # as calculated by interval bisection in devutils/external/calculate_moffat_radii.py
    fwhm_backwards_compatible = 1.0927449310213702
    psf = galsim.Moffat(beta=1.5,
                        fwhm=fwhm_backwards_compatible,
                        trunc=4 * fwhm_backwards_compatible,
                        flux=1)
    pixel = galsim.Pixel(scale=dx, flux=1.)
    # Note: Since both of these have hard edges, GalSim wants to do this with real_space=True.
    # Here we are intentionally tesing the Fourier convolution, so we want to suppress the
    # warning that GalSim emits.
    with assert_warns(galsim.GalSimWarning):
        # We'll do the real space convolution below
        conv = galsim.Convolve([psf, pixel], real_space=False)
        conv.drawImage(myImg, scale=dx, method="sb", use_true_center=False)
        np.testing.assert_array_almost_equal(
            myImg.array,
            savedImg.array,
            4,
            err_msg="Moffat convolved with Pixel disagrees with expected result"
        )
        assert psf.gsparams is galsim.GSParams.default
        assert pixel.gsparams is galsim.GSParams.default
        assert conv.gsparams is galsim.GSParams.default

        # Other ways to do the convolution:
        conv = galsim.Convolve(psf, pixel, real_space=False)
        conv.drawImage(myImg, scale=dx, method="sb", use_true_center=False)
        np.testing.assert_array_almost_equal(
            myImg.array,
            savedImg.array,
            4,
            err_msg=
            "Using GSObject Convolve(psf,pixel) disagrees with expected result"
        )
        assert conv.gsparams is galsim.GSParams.default

        # Check with default_params
        conv = galsim.Convolve([psf, pixel],
                               real_space=False,
                               gsparams=default_params)
        conv.drawImage(myImg, scale=dx, method="sb", use_true_center=False)
        np.testing.assert_array_almost_equal(
            myImg.array,
            savedImg.array,
            4,
            err_msg=
            "Using GSObject Convolve([psf,pixel]) with default_params disagrees with"
            "expected result")
        # In this case, it's not the same object, but it should be ==
        assert conv.gsparams is not galsim.GSParams.default
        assert conv.gsparams == galsim.GSParams.default
        assert conv.gsparams is default_params
        # Also the components shouldn't have changed.
        assert conv.obj_list[0] is psf
        assert conv.obj_list[1] is pixel

        conv = galsim.Convolve([psf, pixel],
                               real_space=False,
                               gsparams=galsim.GSParams())
        conv.drawImage(myImg, scale=dx, method="sb", use_true_center=False)
        np.testing.assert_array_almost_equal(
            myImg.array,
            savedImg.array,
            4,
            err_msg=
            "Using GSObject Convolve([psf,pixel]) with GSParams() disagrees with"
            "expected result")
        assert conv.gsparams is not galsim.GSParams.default
        assert conv.gsparams == galsim.GSParams.default

    cen = galsim.PositionD(0, 0)
    np.testing.assert_equal(conv.centroid, cen)
    np.testing.assert_almost_equal(conv.flux, psf.flux * pixel.flux)
    # Not almost_equal.  Convolutions don't give a very good estimate.
    # They are almost always too high, which is actually ok for how we use max_sb for phot shooting.
    np.testing.assert_array_less(conv.xValue(cen), conv.max_sb)

    check_basic(conv, "Moffat * Pixel")

    # Test photon shooting.
    with assert_warns(galsim.GalSimWarning):
        do_shoot(conv, myImg, "Moffat * Pixel")

    # Convolution of just one argument should be equivalent to that argument.
    single = galsim.Convolve(psf)
    gsobject_compare(single, psf)
    check_basic(single, "`convolution' of single Moffat")
    do_pickle(single)
    do_shoot(single, myImg, "single Convolution")

    single = galsim.Convolve([psf])
    gsobject_compare(single, psf)
    check_basic(single, "`convolution' of single Moffat")
    do_pickle(single)

    single = galsim.Convolution(psf)
    gsobject_compare(single, psf)
    check_basic(single, "`convolution' of single Moffat")
    do_pickle(single)

    single = galsim.Convolution([psf])
    gsobject_compare(single, psf)
    check_basic(single, "`convolution' of single Moffat")
    do_pickle(single)

    # Should raise an exception for invalid arguments
    assert_raises(TypeError, galsim.Convolve)
    assert_raises(TypeError, galsim.Convolve, myImg)
    assert_raises(TypeError, galsim.Convolve, [myImg])
    assert_raises(TypeError, galsim.Convolve, [psf, myImg])
    assert_raises(TypeError, galsim.Convolve, [psf, psf, myImg])
    assert_raises(TypeError, galsim.Convolve, [psf, psf], realspace=False)
    assert_raises(TypeError, galsim.Convolution)
    assert_raises(TypeError, galsim.Convolution, myImg)
    assert_raises(TypeError, galsim.Convolution, [myImg])
    assert_raises(TypeError, galsim.Convolution, [psf, myImg])
    assert_raises(TypeError, galsim.Convolution, [psf, psf, myImg])
    assert_raises(TypeError, galsim.Convolution, [psf, psf], realspace=False)

    with assert_warns(galsim.GalSimWarning):
        triple = galsim.Convolve(psf, psf, pixel)
    assert_raises(galsim.GalSimError, triple.xValue, galsim.PositionD(0, 0))
    assert_raises(galsim.GalSimError, triple.drawReal, myImg)

    deconv = galsim.Convolve(psf, galsim.Deconvolve(pixel))
    assert_raises(galsim.GalSimError, deconv.xValue, galsim.PositionD(0, 0))
    assert_raises(galsim.GalSimError, deconv.drawReal, myImg)
    assert_raises(galsim.GalSimError, deconv.drawPhot, myImg, n_photons=10)
Exemple #19
0
def test_knots_defaults():
    """
    Create a random walk galaxy and test that the getters work for
    default inputs
    """

    # try constructing with mostly defaults
    npoints=100
    hlr = 8.0
    rng = galsim.BaseDeviate(1234)
    rw=galsim.RandomKnots(npoints, half_light_radius=hlr, rng=rng)

    assert rw.npoints==npoints,"expected npoints==%d, got %d" % (npoints, rw.npoints)
    assert rw.input_half_light_radius==hlr,\
        "expected hlr==%g, got %g" % (hlr, rw.input_half_light_radius)

    nobj=len(rw.points)
    assert nobj == npoints,"expected %d objects, got %d" % (npoints, nobj)

    pts=rw.points
    assert pts.shape == (npoints,2),"expected (%d,2) shape for points, got %s" % (npoints, pts.shape)
    np.testing.assert_almost_equal(rw.centroid.x, np.mean(pts[:,0]))
    np.testing.assert_almost_equal(rw.centroid.y, np.mean(pts[:,1]))

    gsp = galsim.GSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)
    rng2 = galsim.BaseDeviate(1234)
    rw2 = galsim.RandomKnots(npoints, half_light_radius=hlr, rng=rng2, gsparams=gsp)
    assert rw2 != rw
    assert rw2 == rw.withGSParams(gsp)
    assert rw2 == rw.withGSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)

    # Check that they produce identical images.
    psf = galsim.Gaussian(sigma=0.8)
    conv1 = galsim.Convolve(rw.withGSParams(gsp), psf)
    conv2 = galsim.Convolve(rw2, psf)
    im1 = conv1.drawImage()
    im2 = conv2.drawImage()
    assert im1 == im2

    # Check that image is not sensitive to use of rng by other objects.
    rng3 = galsim.BaseDeviate(1234)
    rw3=galsim.RandomKnots(npoints, half_light_radius=hlr, rng=rng3)
    rng3.discard(523)
    conv1 = galsim.Convolve(rw, psf)
    conv3 = galsim.Convolve(rw3, psf)
    im1 = conv1.drawImage()
    im3 = conv2.drawImage()
    assert im1 == im3

    # Run some basic tests of correctness
    check_basic(conv1, "RandomKnots")
    im = galsim.ImageD(64,64, scale=0.5)
    do_shoot(conv1, im, "RandomKnots")
    do_kvalue(conv1, im, "RandomKnots")
    do_pickle(rw)
    do_pickle(conv1)
    do_pickle(conv1, lambda x: x.drawImage(scale=1))

    # Check negative flux
    rw3 = rw.withFlux(-2.3)
    assert rw3 == galsim.RandomKnots(npoints, half_light_radius=hlr, rng=galsim.BaseDeviate(1234),
                                     flux=-2.3)
    conv = galsim.Convolve(rw3, psf)
    check_basic(conv, "RandomKnots with negative flux")
Exemple #20
0
def test_realspace_convolve():
    """Test the real-space convolution of a Moffat and a Box profile against a known result.
    """
    dx = 0.2
    # Note: Using an image created from Maple "exact" calculations.
    saved_img = galsim.fits.read(os.path.join(imgdir, "moffat_pixel.fits"))
    img = galsim.ImageF(saved_img.bounds, scale=dx)
    img.setCenter(0, 0)

    # Code was formerly:
    # psf = galsim.Moffat(beta=1.5, truncationFWHM=4, flux=1, half_light_radius=1)
    #
    # ...but this is no longer quite so simple since we changed the handling of trunc to be in
    # physical units.  However, the same profile can be constructed using
    # fwhm=1.0927449310213702,
    # as calculated by interval bisection in devutils/external/calculate_moffat_radii.py
    fwhm_backwards_compatible = 1.0927449310213702
    psf = galsim.Moffat(beta=1.5,
                        half_light_radius=1,
                        trunc=4 * fwhm_backwards_compatible,
                        flux=1)
    #psf = galsim.Moffat(beta=1.5, fwhm=fwhm_backwards_compatible,
    #trunc=4*fwhm_backwards_compatible, flux=1)
    pixel = galsim.Pixel(scale=dx, flux=1.)
    conv = galsim.Convolve([psf, pixel], real_space=True)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) disagrees with expected result")

    # Check with default_params
    conv = galsim.Convolve([psf, pixel],
                           real_space=True,
                           gsparams=default_params)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) with default_params disagrees with "
        "expected result")
    conv = galsim.Convolve([psf, pixel],
                           real_space=True,
                           gsparams=galsim.GSParams())
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) with GSParams() disagrees with "
        "expected result")

    # Other ways to do the convolution:
    conv = galsim.Convolve(psf, pixel, real_space=True)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve(psf,pixel) disagrees with expected result")

    # The real-space convolution algorithm is not (trivially) independent of the order of
    # the two things being convolved.  So check the opposite order.
    conv = galsim.Convolve([pixel, psf], real_space=True)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([pixel,psf]) disagrees with expected result")

    check_basic(conv, "Truncated Moffat*Box", approx_maxsb=True)

    # Test kvalues
    do_kvalue(conv, img, "Truncated Moffat*Box")

    # Check picklability
    do_pickle(conv, lambda x: x.drawImage(method='sb'))
    do_pickle(conv)

    # Check some warnings that should be raised
    # More than 2 with only hard edges gives a warning either way. (Different warnings though.)
    assert_warns(galsim.GalSimWarning, galsim.Convolve, [psf, psf, pixel])
    assert_warns(galsim.GalSimWarning,
                 galsim.Convolve, [psf, psf, pixel],
                 real_space=False)
    assert_warns(galsim.GalSimWarning,
                 galsim.Convolve, [psf, psf, pixel],
                 real_space=True)
    # 2 with hard edges gives a warning if we ask it not to use real_space
    assert_warns(galsim.GalSimWarning,
                 galsim.Convolve, [psf, pixel],
                 real_space=False)
    # >2 of any kind give a warning if we ask it to use real_space
    g = galsim.Gaussian(sigma=2)
    assert_warns(galsim.GalSimWarning,
                 galsim.Convolve, [g, g, g],
                 real_space=True)
    # non-analytic profiles cannot do real_space
    d = galsim.Deconvolve(galsim.Gaussian(sigma=2))
    assert_warns(galsim.GalSimWarning,
                 galsim.Convolve, [g, d],
                 real_space=True)
    assert_raises(TypeError, galsim.Convolve, [g, d], real_space='true')

    # Repeat some of the above for AutoConvolve and AutoCorrelate
    conv = galsim.AutoConvolve(psf, real_space=True)
    check_basic(conv, "AutoConvolve Truncated Moffat", approx_maxsb=True)
    do_kvalue(conv, img, "AutoConvolve Truncated Moffat")
    do_pickle(conv)

    conv = galsim.AutoCorrelate(psf, real_space=True)
    check_basic(conv, "AutoCorrelate Truncated Moffat", approx_maxsb=True)
    do_kvalue(conv, img, "AutoCorrelate Truncated Moffat")
    do_pickle(conv)

    assert_warns(galsim.GalSimWarning,
                 galsim.AutoConvolve,
                 psf,
                 real_space=False)
    assert_warns(galsim.GalSimWarning, galsim.AutoConvolve, d, real_space=True)
    assert_warns(galsim.GalSimWarning,
                 galsim.AutoCorrelate,
                 psf,
                 real_space=False)
    assert_warns(galsim.GalSimWarning,
                 galsim.AutoCorrelate,
                 d,
                 real_space=True)
    assert_raises(TypeError, galsim.AutoConvolve, d, real_space='true')
    assert_raises(TypeError, galsim.AutoCorrelate, d, real_space='true')
Exemple #21
0
def run_tests(random_seed, outfile, config=None, gsparams=None, wmult=None, logger=None,
              fail_value=-666.):
    """Run a full set of tests, writing pickled tuple output to outfile.
    """
    import sys
    import cPickle
    import numpy as np
    import galsim
    import galaxy_sample
    # Load up the comparison_utilities module from the parent directory
    sys.path.append('..')
    import comparison_utilities
    
    if config is None:
        use_config = False
        if gsparams is None:
            import warnings
            warnings.warn("No gsparams provided to run_tests?")
        if wmult is None:
            raise ValueError("wmult must be set if config=None.")
    else:
        use_config = True
        if gsparams is not None:
            import warnings
            warnings.warn(
                "gsparams is provided as a kwarg but the config['image']['gsparams'] will take "+
                "precedence.")
        if wmult is not None:
            import warnings
            warnings.warn(
                "wmult is provided as a kwarg but the config['image']['wmult'] will take "+
                "precedence.")
    # Get galaxy sample
    n_cosmos, hlr_cosmos, gabs_cosmos = galaxy_sample.get()
    # Only take the first NOBS objects
    n_cosmos = n_cosmos[0: NOBS]
    hlr_cosmos = hlr_cosmos[0: NOBS]
    gabs_cosmos = gabs_cosmos[0: NOBS]
    ntest = len(SERSIC_N_TEST)
    # Setup a UniformDeviate
    ud = galsim.UniformDeviate(random_seed)
    # Open the output file and write a header:
    fout = open(outfile, 'wb')
    fout.write(
        '#  g1obs_draw g2obs_draw sigma_draw delta_g1obs delta_g2obs delta_sigma '+
        'err_g1obs err_g2obs err_sigma\n')
    # Start looping through the sample objects and collect the results
    for i, hlr, gabs in zip(range(NOBS), hlr_cosmos, gabs_cosmos):
        print "Testing galaxy #"+str(i+1)+"/"+str(NOBS)+\
              " with (hlr, |g|) = "+str(hlr)+", "+str(gabs)
        random_theta = 2. * np.pi * ud()
        g1 = gabs * np.cos(2. * random_theta)
        g2 = gabs * np.sin(2. * random_theta)
        for j, sersic_n in zip(range(ntest), SERSIC_N_TEST):
            print "Exploring Sersic n = "+str(sersic_n)
            if use_config:
                # Increment the random seed so that each test gets a unique one
                config['image']['random_seed'] = random_seed + i * NOBS * ntest + j * ntest + 1
                config['gal'] = {
                    "type" : "Sersic" , "n" : sersic_n , "half_light_radius" : hlr ,
                    "ellip" : {
                        "type" : "G1G2" , "g1" : g1 , "g2" : g2
                    }
                }
                config['psf'] = {"type" : "Airy" , "lam_over_diam" : PSF_LAM_OVER_DIAM }
                try:
                    results = comparison_utilities.compare_dft_vs_photon_config(
                        config, abs_tol_ellip=TOL_ELLIP, abs_tol_size=TOL_SIZE, logger=logger)
                    test_ran = True
                except RuntimeError as err:
                    test_ran = False
                    pass
                # Uncomment lines below to ouput a check image
                #import copy
                #checkimage = galsim.config.BuildImage(copy.deepcopy(config))[0] #im = first element
                #checkimage.write('junk_'+str(i + 1)+'_'+str(j + 1)+'.fits')
            else:
                test_gsparams = galsim.GSParams(maximum_fft_size=MAX_FFT_SIZE)
                galaxy = galsim.Sersic(sersic_n, half_light_radius=hlr, gsparams=test_gsparams)
                galaxy.applyShear(g1=g1, g2=g2)
                psf = galsim.Airy(lam_over_diam=PSF_LAM_OVER_DIAM, gsparams=test_gsparams)
                try:
                    results = comparison_utilities.compare_dft_vs_photon_object(
                        galaxy, psf_object=psf, rng=ud, pixel_scale=PIXEL_SCALE, size=IMAGE_SIZE,
                        abs_tol_ellip=TOL_ELLIP, abs_tol_size=TOL_SIZE,
                        n_photons_per_trial=NPHOTONS, wmult=wmult)
                    test_ran = True
                except RuntimeError, err:
                    test_ran = False
                    pass

            if not test_ran:
                import warnings
                warnings.warn(
                        'RuntimeError encountered for galaxy '+str(i + 1)+'/'+str(NOBS)+' with '+
                        'Sersic n = '+str(sersic_n)+': '+str(err))
                fout.write(
                    '%e %e %e %e %e %e %e %e %e %e %e %e %e\n' % (
                    fail_value, fail_value, fail_value, fail_value, fail_value, fail_value,
                    fail_value, fail_value, fail_value, fail_value, fail_value, fail_value,
                    fail_value)
                )
                fout.flush()
            else:
                fout.write(
                    '%e %e %e %e %e %e %e %e %e %e %e %e %e\n' % (
                    results.g1obs_draw, results.g2obs_draw, results.sigma_draw,
                    results.delta_g1obs, results.delta_g2obs, results.delta_sigma,
                    results.err_g1obs, results.err_g2obs, results.err_sigma, sersic_n, hlr, g1, g2
                    )
                )
                fout.flush()
Exemple #22
0
def test_realspace_distorted_convolve():
    """
    The same as above, but both the Moffat and the Box are sheared, rotated and shifted
    to stress test the code that deals with this for real-space convolutions that wouldn't
    be tested otherwise.
    """
    dx = 0.2
    saved_img = galsim.fits.read(
        os.path.join(imgdir, "moffat_pixel_distorted.fits"))
    img = galsim.ImageF(saved_img.bounds, scale=dx)
    img.setCenter(0, 0)

    fwhm_backwards_compatible = 1.0927449310213702
    psf = galsim.Moffat(beta=1.5,
                        half_light_radius=1,
                        trunc=4 * fwhm_backwards_compatible,
                        flux=1)
    #psf = galsim.Moffat(beta=1.5, fwhm=fwhm_backwards_compatible,
    #trunc=4*fwhm_backwards_compatible, flux=1)
    psf = psf.shear(g1=0.11, g2=0.17).rotate(13 * galsim.degrees)
    pixel = galsim.Pixel(scale=dx, flux=1.)
    pixel = pixel.shear(g1=0.2,
                        g2=0.0).rotate(80 * galsim.degrees).shift(0.13, 0.27)
    # NB: real-space is chosen automatically
    conv = galsim.Convolve([psf, pixel])
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve([psf,pixel]) (distorted) disagrees with expected result"
    )

    # Check with default_params
    conv = galsim.Convolve([psf, pixel], gsparams=default_params)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve([psf,pixel]) (distorted) with default_params disagrees with "
        "expected result")
    conv = galsim.Convolve([psf, pixel], gsparams=galsim.GSParams())
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve([psf,pixel]) (distorted) with GSParams() disagrees with "
        "expected result")

    # Other ways to do the convolution:
    conv = galsim.Convolve(psf, pixel)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve(psf,pixel) (distorted) disagrees with expected result")

    # The real-space convolution algorithm is not (trivially) independent of the order of
    # the two things being convolved.  So check the opposite order.
    conv = galsim.Convolve([pixel, psf])
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using Convolve([pixel,psf]) (distorted) disagrees with expected result"
    )
Exemple #23
0
def test_box():
    """Test the generation of a specific box profile against a known result.
    """
    savedImg = galsim.fits.read(os.path.join(imgdir, "box_1.fits"))
    myImg = galsim.ImageF(savedImg.bounds, scale=0.2)
    myImg.setCenter(0,0)
    test_flux = 1.8

    pixel = galsim.Pixel(scale=1, flux=1)
    pixel.drawImage(myImg, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Pixel disagrees with expected result")
    np.testing.assert_array_equal(
            pixel.scale, 1,
            err_msg="Pixel scale returned wrong value")

    # Check with default_params
    pixel = galsim.Pixel(scale=1, flux=1, gsparams=default_params)
    pixel.drawImage(myImg, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Pixel with default_params disagrees with expected result")
    pixel = galsim.Pixel(scale=1, flux=1, gsparams=galsim.GSParams())
    pixel.drawImage(myImg, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
            myImg.array, savedImg.array, 5,
            err_msg="Using GSObject Pixel with GSParams() disagrees with expected result")

    # Use non-unity values.
    pixel = galsim.Pixel(flux=1.7, scale=2.3)
    gsp = galsim.GSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)
    pixel2 = galsim.Pixel(flux=1.7, scale=2.3, gsparams=gsp)
    assert pixel2 != pixel
    assert pixel2 == pixel.withGSParams(gsp)

    # Test photon shooting.
    do_shoot(pixel,myImg,"Pixel")

    # Check picklability
    do_pickle(pixel, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(pixel)
    do_pickle(galsim.Pixel(1))

    # Check that non-square Box profiles work correctly
    scale = 0.2939  # Use a strange scale here to make sure that the centers of the pixels
                    # never fall on the box edge, otherwise it gets a bit weird to know what
                    # the correct SB value is for that pixel.
    im = galsim.ImageF(16,16, scale=scale)
    gsp = galsim.GSParams(maximum_fft_size = 30000)
    for (width,height) in [ (3,2), (1.7, 2.7), (2.2222, 3.1415) ]:
        box = galsim.Box(width=width, height=height, flux=test_flux, gsparams=gsp)
        check_basic(box, "Box with width,height = %f,%f"%(width,height))
        do_shoot(box,im,"Box with width,height = %f,%f"%(width,height))
        if __name__ == '__main__':
            # These are slow because they require a pretty huge fft.
            # So only do them if running as main.
            do_kvalue(box,im,"Box with width,height = %f,%f"%(width,height))
        cen = galsim.PositionD(0, 0)
        np.testing.assert_equal(box.centroid, cen)
        np.testing.assert_almost_equal(box.kValue(cen), (1+0j) * test_flux)
        np.testing.assert_almost_equal(box.flux, test_flux)
        np.testing.assert_almost_equal(box.xValue(cen), box.max_sb)
        np.testing.assert_almost_equal(box.xValue(width/2.-0.001, height/2.-0.001), box.max_sb)
        np.testing.assert_almost_equal(box.xValue(width/2.-0.001, height/2.+0.001), 0.)
        np.testing.assert_almost_equal(box.xValue(width/2.+0.001, height/2.-0.001), 0.)
        np.testing.assert_almost_equal(box.xValue(width/2.+0.001, height/2.+0.001), 0.)
        np.testing.assert_array_equal(
                box.width, width,
                err_msg="Box width returned wrong value")
        np.testing.assert_array_equal(
                box.height, height,
                err_msg="Box height returned wrong value")

        gsp2 = galsim.GSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)
        box2 = galsim.Box(width=width, height=height, flux=test_flux, gsparams=gsp2)
        assert box2 != box
        assert box2 == box.withGSParams(gsp2)

    # Check picklability
    do_pickle(box, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(box)
    do_pickle(galsim.Box(1,1))

    # Check sheared boxes the same way
    box = galsim.Box(width=3, height=2, flux=test_flux, gsparams=gsp)
    box = box.shear(galsim.Shear(g1=0.2, g2=-0.3))
    check_basic(box, "Sheared Box", approx_maxsb=True)
    do_shoot(box,im, "Sheared Box")
    if __name__ == '__main__':
        do_kvalue(box,im, "Sheared Box")
        do_pickle(box, lambda x: x.drawImage(method='no_pixel'))
        do_pickle(box)
    cen = galsim.PositionD(0, 0)
    np.testing.assert_equal(box.centroid, cen)
    np.testing.assert_almost_equal(box.kValue(cen), (1+0j) * test_flux)
    np.testing.assert_almost_equal(box.flux, test_flux)
    np.testing.assert_almost_equal(box.xValue(cen), box.max_sb)

    # This is also a profile that may be convolved using real space convolution, so test that.
    if __name__ == '__main__':
        conv = galsim.Convolve(box, galsim.Pixel(scale=scale), real_space=True)
        check_basic(conv, "Sheared Box convolved with pixel in real space",
                    approx_maxsb=True, scale=0.2)
        do_kvalue(conv,im, "Sheared Box convolved with pixel in real space")
        do_pickle(conv, lambda x: x.xValue(0.123,-0.456))
        do_pickle(conv)
Exemple #24
0
def test_realspace_shearconvolve():
    """Test the real-space convolution of a sheared Gaussian and a Box profile against a
       known result.
    """
    e1 = 0.04
    e2 = 0.0
    myShear = galsim.Shear(e1=e1, e2=e2)
    dx = 0.2
    saved_img = galsim.fits.read(
        os.path.join(imgdir, "gauss_smallshear_convolve_box.fits"))
    img = galsim.ImageF(saved_img.bounds, scale=dx)
    img.setCenter(0, 0)

    psf = galsim.Gaussian(flux=1, sigma=1)
    psf = psf.shear(e1=e1, e2=e2)
    pixel = galsim.Pixel(scale=dx, flux=1.)
    conv = galsim.Convolve([psf, pixel], real_space=True)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) disagrees with expected result")

    # Check with default_params
    conv = galsim.Convolve([psf, pixel],
                           real_space=True,
                           gsparams=default_params)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) with default_params disagrees with "
        "expected result")
    conv = galsim.Convolve([psf, pixel],
                           real_space=True,
                           gsparams=galsim.GSParams())
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) with GSParams() disagrees with "
        "expected result")

    # Other ways to do the convolution:
    conv = galsim.Convolve(psf, pixel, real_space=True)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve(psf,pixel) disagrees with expected result")

    # The real-space convolution algorithm is not (trivially) independent of the order of
    # the two things being convolved.  So check the opposite order.
    conv = galsim.Convolve([pixel, psf], real_space=True)
    conv.drawImage(img, scale=dx, method="sb", use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([pixel,psf]) disagrees with expected result")
Exemple #25
0
def _BuildCOSMOSGalaxy(config, base, ignore, gsparams, logger):
    """@brief Build a COSMOS galaxy using the cosmos_catalog input item.
    """
    cosmos_cat = galsim.config.GetInputObj('cosmos_catalog', config, base,
                                           'COSMOSGalaxy')

    ignore = ignore + ['num']

    # Special: if galaxies are selected based on index, and index is Sequence or Random, and max
    # isn't set, set it to nobjects-1.
    if 'index' in config:
        galsim.config.SetDefaultIndex(config, cosmos_cat.getNObjects())

    kwargs, safe = galsim.config.GetAllParams(
        config,
        base,
        req=galsim.COSMOSCatalog.makeGalaxy._req_params,
        opt=galsim.COSMOSCatalog.makeGalaxy._opt_params,
        single=galsim.COSMOSCatalog.makeGalaxy._single_params,
        ignore=ignore)
    if gsparams: kwargs['gsparams'] = galsim.GSParams(**gsparams)

    # Deal with defaults for gal_type, if it wasn't specified:
    # If COSMOSCatalog was constructed with 'use_real'=True, then default is 'real'.  Otherwise, the
    # default is 'parametric'.  This code is in makeGalaxy, but since config has to use
    # _makeSingleGalaxy, we have to include this here too.
    if 'gal_type' not in kwargs:
        if cosmos_cat.use_real: kwargs['gal_type'] = 'real'
        else: kwargs['gal_type'] = 'parametric'

    rng = None
    if 'index' not in kwargs:
        rng = galsim.config.GetRNG(config, base, logger, 'COSMOSGalaxy')
        kwargs['index'], n_rng_calls = cosmos_cat.selectRandomIndex(
            1, rng=rng, _n_rng_calls=True)

        # Make sure this process gives consistent results regardless of the number of processes
        # being used.
        if not isinstance(cosmos_cat,
                          galsim.COSMOSCatalog) and rng is not None:
            # Then cosmos_cat is really a proxy, which means the rng was pickled, so we need to
            # discard the same number of random calls from the one in the config dict.
            rng.discard(int(n_rng_calls))

    # Even though gal_type is optional, it will have been set in the code above.  So we can at this
    # point assume that kwargs['gal_type'] exists.
    if kwargs['gal_type'] == 'real':
        if rng is None:
            rng = galsim.config.GetRNG(config, base, logger, 'COSMOSGalaxy')
        kwargs['rng'] = rng

    # NB. Even though index is officially optional, it will always be present, either because it was
    #     set by a call to selectRandomIndex, explicitly by the user, or due to the call to
    #     SetDefaultIndex.
    index = kwargs['index']
    if index >= cosmos_cat.getNObjects():
        raise IndexError(
            "%s index has gone past the number of entries in the catalog" %
            index)

    logger.debug('obj %d: COSMOSGalaxy kwargs = %s', base.get('obj_num', 0),
                 kwargs)

    kwargs['cosmos_catalog'] = cosmos_cat

    # Use a staticmethod of COSMOSCatalog to avoid pickling the result of makeGalaxy()
    # The RealGalaxy in particular has a large serialization, so it is more efficient to
    # make it in this process, which is what happens here.
    gal = galsim.COSMOSCatalog._makeSingleGalaxy(**kwargs)

    return gal, safe
Exemple #26
0
def test_autoconvolve():
    """Test that auto-convolution works the same as convolution with itself.
    """
    dx = 0.4
    myImg1 = galsim.ImageF(80, 80, scale=dx)
    myImg1.setCenter(0, 0)
    myImg2 = galsim.ImageF(80, 80, scale=dx)
    myImg2.setCenter(0, 0)

    psf = galsim.Moffat(beta=3.8, fwhm=1.3, flux=5)
    conv = galsim.Convolve([psf, psf])
    conv.drawImage(myImg1, method='no_pixel')
    conv2 = galsim.AutoConvolve(psf)
    conv2.drawImage(myImg2, method='no_pixel')
    printval(myImg1, myImg2)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg="Moffat convolved with self disagrees with AutoConvolve result"
    )

    # Check with default_params
    conv = galsim.AutoConvolve(psf, gsparams=default_params)
    conv.drawImage(myImg1, method='no_pixel')
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Using AutoConvolve with default_params disagrees with expected result"
    )
    conv = galsim.AutoConvolve(psf, gsparams=galsim.GSParams())
    conv.drawImage(myImg1, method='no_pixel')
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Using AutoConvolve with GSParams() disagrees with expected result")

    check_basic(conv, "AutoConvolve(Moffat)")

    cen = galsim.PositionD(0, 0)
    np.testing.assert_equal(conv2.centroid, cen)
    np.testing.assert_almost_equal(conv2.flux, psf.flux**2)
    np.testing.assert_array_less(conv2.xValue(cen), conv2.max_sb)

    # Check picklability
    do_pickle(conv2, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(conv2)

    # Test photon shooting.
    do_shoot(conv2, myImg2, "AutoConvolve(Moffat)")

    # For a symmetric profile, AutoCorrelate is the same thing:
    conv2 = galsim.AutoCorrelate(psf)
    conv2.drawImage(myImg2, method='no_pixel')
    printval(myImg1, myImg2)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg="Moffat convolved with self disagrees with AutoCorrelate result"
    )

    # And check AutoCorrelate with gsparams:
    conv2 = galsim.AutoCorrelate(psf, gsparams=default_params)
    conv2.drawImage(myImg1, method='no_pixel')
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Using AutoCorrelate with default_params disagrees with expected result"
    )
    conv2 = galsim.AutoCorrelate(psf, gsparams=galsim.GSParams())
    conv2.drawImage(myImg1, method='no_pixel')
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Using AutoCorrelate with GSParams() disagrees with expected result")

    cen = galsim.PositionD(0, 0)
    np.testing.assert_equal(conv2.centroid, cen)
    np.testing.assert_almost_equal(conv2.flux, psf.flux**2)
    np.testing.assert_array_less(conv2.xValue(cen), conv2.max_sb)

    # Also check AutoConvolve with an asymmetric profile.
    # (AutoCorrelate with this profile is done below...)
    obj1 = galsim.Gaussian(sigma=3., flux=4).shift(-0.2, -0.4)
    obj2 = galsim.Gaussian(sigma=6., flux=1.3).shift(0.3, 0.3)
    add = galsim.Add(obj1, obj2)
    conv = galsim.Convolve([add, add])
    conv.drawImage(myImg1, method='no_pixel')
    autoconv = galsim.AutoConvolve(add)
    autoconv.drawImage(myImg2, method='no_pixel')
    printval(myImg1, myImg2)
    np.testing.assert_array_almost_equal(
        myImg1.array,
        myImg2.array,
        4,
        err_msg=
        "Asymmetric sum of Gaussians convolved with self disagrees with " +
        "AutoConvolve result")

    cen = 2. * add.centroid
    np.testing.assert_equal(autoconv.centroid, cen)
    np.testing.assert_almost_equal(autoconv.flux, add.flux**2)
    np.testing.assert_array_less(autoconv.xValue(cen), autoconv.max_sb)

    check_basic(autoconv, "AutoConvolve(asym)")

    # Should raise an exception for invalid arguments
    assert_raises(TypeError, galsim.AutoConvolve)
    assert_raises(TypeError, galsim.AutoConvolve, myImg1)
    assert_raises(TypeError, galsim.AutoConvolve, [psf])
    assert_raises(TypeError, galsim.AutoConvolve, psf, psf)
    assert_raises(TypeError, galsim.AutoConvolve, psf, realspace=False)
    assert_raises(TypeError, galsim.AutoConvolution)
    assert_raises(TypeError, galsim.AutoConvolution, myImg1)
    assert_raises(TypeError, galsim.AutoConvolution, [psf])
    assert_raises(TypeError, galsim.AutoConvolution, psf, psf)
    assert_raises(TypeError, galsim.AutoConvolution, psf, realspace=False)
Exemple #27
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()
    def getStampBounds(self, gsObject, flux, image_pos, keep_sb_level,
                       large_object_sb_level, Nmax=1400, pixel_scale=0.2):
        """
        Get the postage stamp bounds for drawing an object within the stamp
        to include the specified minimum surface brightness.  Use the
        folding_threshold criterion for point source objects.  For
        extended objects, use the getGoodPhotImageSize function, where
        if the initial stamp is too large (> Nmax**2 ~ 1GB of RSS
        memory for a 72 vertex/pixel sensor model), use the relaxed
        surface brightness level for large objects.

        Parameters
        ----------
        gsObject: GalSimCelestialObject
            This contains the information needed to construct a
            galsim.GSObject convolved with the desired PSF.
        flux: float
            The flux of the object in e-.
        keep_sb_level: float
            The minimum surface brightness (photons/pixel) out to which to
            extend the postage stamp, e.g., a value of
            sqrt(sky_bg_per_pixel)/3 would be 1/3 the Poisson noise
            per pixel from the sky background.
        large_object_sb_level: float
            Surface brightness level to use for large/bright objects that
            would otherwise yield stamps with more than Nmax**2 pixels.
        Nmax: int [1400]
            The largest stamp size to consider at the nominal keep_sb_level.
            1400**2*72*8/1024**3 = 1GB.
        pixel_scale: float [0.2]
            The CCD pixel scale in arcsec.

        Returns
        -------
        galsim.BoundsI: The postage stamp bounds.

        """
        if flux < 10:
            # For really faint things, don't try too hard.  Just use 32x32.
            image_size = 32
        elif gsObject.galSimType.lower() == "pointsource":
            # For bright stars, set the folding threshold for the
            # stamp size calculation.  Use a
            # Kolmogorov_and_Gaussian_PSF since it is faster to
            # evaluate than an AtmosphericPSF.
            folding_threshold = self.sky_bg_per_pixel/flux
            if folding_threshold >= self._ft_default:
                gsparams = None
            else:
                gsparams = galsim.GSParams(folding_threshold=folding_threshold)
            psf = Kolmogorov_and_Gaussian_PSF(airmass=self._airmass,
                                              rawSeeing=self._rawSeeing,
                                              band=self._band,
                                              gsparams=gsparams)
            obj = self.drawPointSource(gsObject, psf=psf)
            image_size = obj.getGoodImageSize(pixel_scale)
        else:
            # For extended objects, recreate the object to draw, but
            # convolved with the faster DoubleGaussian PSF.
            obj = self.createCenteredObject(gsObject,
                                            psf=self._double_gaussian_psf)
            obj = obj.withFlux(flux)

            # Start with GalSim's estimate of a good box size.
            image_size = obj.getGoodImageSize(pixel_scale)

            # For bright things, defined as having an average of at least 10 photons per
            # pixel on average, try to be careful about not truncating the surface brightness
            # at the edge of the box.
            if flux > 10 * image_size**2:
                image_size = getGoodPhotImageSize(obj, keep_sb_level,
                                                  pixel_scale=pixel_scale)

            # If the above size comes out really huge, scale back to what you get for
            # a somewhat brighter surface brightness limit.
            if image_size > Nmax:
                image_size = getGoodPhotImageSize(obj, large_object_sb_level,
                                                  pixel_scale=pixel_scale)
                image_size = max(image_size, Nmax)

        # Create the bounds object centered on the desired location.
        xmin = int(math.floor(image_pos.x) - image_size/2)
        xmax = int(math.ceil(image_pos.x) + image_size/2)
        ymin = int(math.floor(image_pos.y) - image_size/2)
        ymax = int(math.ceil(image_pos.y) + image_size/2)

        return galsim.BoundsI(xmin, xmax, ymin, ymax)
Exemple #29
0
def test_OpticalPSF_pupil_plane():
    """Test the ability to generate a PSF using an image of the pupil plane.
    """
    # Test case: lam/diam=0.12, obscuration=0.18, 4 struts of the default width and with rotation
    # from the vertical of -15 degrees.  There are two versions of these tests at different
    # oversampling levels.
    #
    # To (re-)generate the pupil plane images for this test, simply delete
    # tests/Optics_comparison_images/sample_pupil_rolled.fits and
    # tests/Optics_comparison_images/sample_pupil_rolled_oversample.fits.gz,
    # and then rerun this function.  Note that these images are also used in test_ne(), so there
    # may be some racing if this script is tested in parallel before the fits files are regenerated.

    # First test: should get excellent agreement between that particular OpticalPSF with specified
    # options and one from loading the pupil plane image.  Note that this won't work if you change
    # the optical PSF parameters, unless you also regenerate the test image.
    lam_over_diam = 0.12
    obscuration = 0.18
    nstruts = 4
    strut_angle = -15. * galsim.degrees
    scale = 0.055
    ref_psf = galsim.OpticalPSF(lam_over_diam,
                                obscuration=obscuration,
                                nstruts=nstruts,
                                oversampling=pp_oversampling,
                                strut_angle=strut_angle,
                                pad_factor=pp_pad_factor)
    if os.path.isfile(os.path.join(imgdir, pp_file)):
        im = galsim.fits.read(os.path.join(imgdir, pp_file))
    else:
        import warnings
        warnings.warn(
            "Could not find file {0}, so generating it from scratch.  This should only "
            "happen if you intentionally deleted the file in order to regenerate it!"
            .format(pp_file))
        im = galsim.Image(ref_psf._psf.aper.illuminated.astype(float))
        im.scale = ref_psf._psf.aper.pupil_plane_scale
        print('pupil_plane image has scale = ', pp_scale)
        im.write(os.path.join(imgdir, pp_file))
    pp_scale = im.scale
    print('pupil_plane image has scale = ', pp_scale)

    # For most of the tests, we remove this scale, since for achromatic tests, you don't really
    # need it, and it is invalid to give lam_over_diam (rather than lam, diam separately) when
    # there is a specific scale for the pupil plane image.  But see the last test below where
    # we do use lam, diam separately with the input image.
    im.scale = None
    # This implies that the lam_over_diam value
    test_psf = galsim.OpticalPSF(lam_over_diam,
                                 obscuration=obscuration,
                                 oversampling=pp_oversampling,
                                 pupil_plane_im=im,
                                 pad_factor=pp_pad_factor)
    im_ref_psf = ref_psf.drawImage(scale=scale)
    im_test_psf = galsim.ImageD(im_ref_psf.array.shape[0],
                                im_ref_psf.array.shape[1])
    im_test_psf = test_psf.drawImage(image=im_test_psf, scale=scale)

    if pp_test_type == 'image':
        np.testing.assert_array_almost_equal(
            im_test_psf.array,
            im_ref_psf.array,
            decimal=pp_decimal,
            err_msg=
            "Inconsistent OpticalPSF image for basic model after loading pupil plane."
        )
    else:
        test_moments = im_test_psf.FindAdaptiveMom()
        ref_moments = im_ref_psf.FindAdaptiveMom()
        np.testing.assert_almost_equal(
            test_moments.moments_sigma,
            ref_moments.moments_sigma,
            decimal=pp_decimal,
            err_msg=
            "Inconsistent OpticalPSF image for basic model after loading pupil plane."
        )

    if do_slow_tests:
        do_pickle(
            test_psf,
            lambda x: x.drawImage(nx=20, ny=20, scale=0.07, method='no_pixel'))
        do_pickle(test_psf)

    # It is supposed to be able to figure this out even if we *don't* tell it the pad factor. So
    # make sure that it still works even if we don't tell it that value.
    test_psf = galsim.OpticalPSF(lam_over_diam,
                                 obscuration=obscuration,
                                 pupil_plane_im=im,
                                 oversampling=pp_oversampling)
    im_test_psf = galsim.ImageD(im_ref_psf.array.shape[0],
                                im_ref_psf.array.shape[1])
    im_test_psf = test_psf.drawImage(image=im_test_psf, scale=scale)

    if pp_test_type == 'image':
        np.testing.assert_array_almost_equal(
            im_test_psf.array,
            im_ref_psf.array,
            decimal=pp_decimal,
            err_msg=
            "Inconsistent OpticalPSF image for basic model after loading pupil plane without "
            "specifying parameters.")
    else:
        test_moments = im_test_psf.FindAdaptiveMom()
        ref_moments = im_ref_psf.FindAdaptiveMom()
        np.testing.assert_almost_equal(
            test_moments.moments_sigma,
            ref_moments.moments_sigma,
            decimal=pp_decimal,
            err_msg=
            "Inconsistent OpticalPSF image for basic model after loading pupil plane without "
            "specifying parameters.")

    # Next test (less trivial): Rotate the struts by +27 degrees, and check that agreement is
    # good. This is making sure that the linear interpolation that is done when rotating does not
    # result in significant loss of accuracy.
    rot_angle = 27. * galsim.degrees
    ref_psf = galsim.OpticalPSF(lam_over_diam,
                                obscuration=obscuration,
                                nstruts=nstruts,
                                strut_angle=strut_angle + rot_angle,
                                oversampling=pp_oversampling,
                                pad_factor=pp_pad_factor)
    test_psf = galsim.OpticalPSF(lam_over_diam,
                                 obscuration=obscuration,
                                 pupil_plane_im=im,
                                 pupil_angle=rot_angle,
                                 oversampling=pp_oversampling,
                                 pad_factor=pp_pad_factor)
    im_ref_psf = ref_psf.drawImage(scale=scale)
    im_test_psf = galsim.ImageD(im_ref_psf.array.shape[0],
                                im_ref_psf.array.shape[1])
    im_test_psf = test_psf.drawImage(image=im_test_psf, scale=scale)
    # We are slightly less stringent here since it should not be exact.
    if pp_test_type == 'image':
        np.testing.assert_array_almost_equal(
            im_test_psf.array,
            im_ref_psf.array,
            decimal=pp_decimal - 1,
            err_msg=
            "Inconsistent OpticalPSF image for rotated model after loading pupil plane."
        )
    else:
        test_moments = im_test_psf.FindAdaptiveMom()
        ref_moments = im_ref_psf.FindAdaptiveMom()
        np.testing.assert_almost_equal(
            test_moments.moments_sigma,
            ref_moments.moments_sigma,
            decimal=pp_decimal - 1,
            err_msg=
            "Inconsistent OpticalPSF image for rotated model after loading pupil plane."
        )

    # Now include aberrations.  Here we are testing the ability to figure out the pupil plane extent
    # and sampling appropriately.  Those get fed into the routine for making the aberrations.
    defocus = -0.03
    coma1 = 0.03
    spher = -0.02
    ref_psf = galsim.OpticalPSF(lam_over_diam,
                                obscuration=obscuration,
                                nstruts=nstruts,
                                strut_angle=strut_angle,
                                defocus=defocus,
                                coma1=coma1,
                                spher=spher,
                                oversampling=pp_oversampling,
                                pad_factor=pp_pad_factor)
    test_psf = galsim.OpticalPSF(lam_over_diam,
                                 obscuration=obscuration,
                                 pupil_plane_im=im,
                                 defocus=defocus,
                                 coma1=coma1,
                                 spher=spher,
                                 oversampling=pp_oversampling,
                                 pad_factor=pp_pad_factor)
    im_ref_psf = ref_psf.drawImage(scale=scale)
    im_test_psf = galsim.ImageD(im_ref_psf.array.shape[0],
                                im_ref_psf.array.shape[1])
    im_test_psf = test_psf.drawImage(image=im_test_psf, scale=scale)
    if pp_test_type == 'image':
        np.testing.assert_array_almost_equal(
            im_test_psf.array,
            im_ref_psf.array,
            decimal=pp_decimal,
            err_msg=
            "Inconsistent OpticalPSF image for aberrated model after loading pupil plane."
        )
    else:
        test_moments = im_test_psf.FindAdaptiveMom()
        ref_moments = im_ref_psf.FindAdaptiveMom()
        np.testing.assert_almost_equal(
            test_moments.moments_sigma,
            ref_moments.moments_sigma,
            decimal=pp_decimal,
            err_msg=
            "Inconsistent OpticalPSF image for aberrated model after loading pupil plane."
        )

    # Test for preservation of symmetries: the result should be the same if the pupil plane is
    # rotated by integer multiples of 2pi/(nstruts).
    ref_psf = galsim.OpticalPSF(lam_over_diam,
                                obscuration=obscuration,
                                nstruts=nstruts,
                                strut_angle=strut_angle,
                                oversampling=pp_oversampling,
                                pad_factor=pp_pad_factor)
    im_ref_psf = ref_psf.drawImage(scale=scale)
    for ind in range(1, nstruts):
        rot_angle = ind * 2. * np.pi / nstruts
        test_psf = galsim.OpticalPSF(lam_over_diam,
                                     obscuration=obscuration,
                                     pupil_plane_im=im,
                                     pupil_angle=rot_angle * galsim.radians,
                                     oversampling=pp_oversampling,
                                     pad_factor=pp_pad_factor)
        im_test_psf = galsim.ImageD(im_ref_psf.array.shape[0],
                                    im_ref_psf.array.shape[1])
        im_test_psf = test_psf.drawImage(image=im_test_psf, scale=scale)
        if pp_test_type == 'image':
            np.testing.assert_array_almost_equal(
                im_test_psf.array,
                im_ref_psf.array,
                decimal=pp_decimal,
                err_msg=
                "Inconsistent OpticalPSF image after rotating pupil plane by invariant "
                "angle.")
        else:
            test_moments = im_test_psf.FindAdaptiveMom()
            ref_moments = im_test_psf.FindAdaptiveMom()
            np.testing.assert_almost_equal(
                test_moments.moments_sigma,
                ref_moments.moments_sigma,
                decimal=pp_decimal,
                err_msg=
                "Inconsistent OpticalPSF image after rotating pupil plane by invariant "
                "angle.")

    # Test that if we rotate pupil plane with no aberrations, that's equivalent to rotating the PSF
    # itself.  Use rotation angle of 90 degrees so numerical issues due to the interpolation should
    # be minimal.
    rot_angle = 90. * galsim.degrees
    psf_1 = galsim.OpticalPSF(lam_over_diam,
                              obscuration=obscuration,
                              pupil_plane_im=im,
                              oversampling=pp_oversampling,
                              pad_factor=pp_pad_factor)
    rot_psf_1 = psf_1.rotate(rot_angle)
    psf_2 = galsim.OpticalPSF(lam_over_diam,
                              obscuration=obscuration,
                              pupil_plane_im=im,
                              pupil_angle=rot_angle,
                              oversampling=pp_oversampling,
                              pad_factor=pp_pad_factor)
    im_1 = psf_1.drawImage(scale=scale)
    im_2 = galsim.ImageD(im_1.array.shape[0], im_1.array.shape[1])
    im_2 = psf_2.drawImage(image=im_2, scale=scale)
    if pp_test_type == 'image':
        np.testing.assert_array_almost_equal(
            im_1.array,
            im_2.array,
            decimal=pp_decimal,
            err_msg=
            "Inconsistent OpticalPSF image after rotating pupil plane vs. rotating PSF."
        )
    else:
        test_moments = im_1.FindAdaptiveMom()
        ref_moments = im_2.FindAdaptiveMom()
        np.testing.assert_almost_equal(
            test_moments.moments_sigma,
            ref_moments.moments_sigma,
            decimal=pp_decimal,
            err_msg=
            "Inconsistent OpticalPSF image after rotating pupil plane vs. rotating PSF."
        )

    # Supply the pupil plane at higher resolution, and make sure that the routine figures out the
    # sampling and gets the right image scale etc.
    gsp = galsim.GSParams(maximum_fft_size=8192)
    rescale_fac = 0.77
    ref_psf = galsim.OpticalPSF(lam_over_diam,
                                obscuration=obscuration,
                                nstruts=nstruts,
                                strut_angle=strut_angle,
                                oversampling=pp_oversampling,
                                pad_factor=pp_pad_factor / rescale_fac,
                                gsparams=gsp)
    # Make higher resolution pupil plane image via interpolation
    int_im = galsim.InterpolatedImage(galsim.Image(im,
                                                   scale=1.0,
                                                   dtype=np.float32),
                                      calculate_maxk=False,
                                      calculate_stepk=False,
                                      x_interpolant='linear')
    new_im = int_im.drawImage(scale=rescale_fac, method='no_pixel')
    new_im.scale = None  # Let OpticalPSF figure out the scale automatically.
    test_psf = galsim.OpticalPSF(lam_over_diam,
                                 obscuration=obscuration,
                                 pupil_plane_im=new_im,
                                 oversampling=pp_oversampling,
                                 gsparams=gsp)
    im_ref_psf = ref_psf.drawImage(scale=scale)
    im_test_psf = galsim.ImageD(im_ref_psf.array.shape[0],
                                im_ref_psf.array.shape[1])
    im_test_psf = test_psf.drawImage(image=im_test_psf, scale=scale)
    test_moments = im_test_psf.FindAdaptiveMom()
    ref_moments = im_ref_psf.FindAdaptiveMom()
    if pp_test_type == 'image':
        np.testing.assert_almost_equal(
            test_moments.moments_sigma / ref_moments.moments_sigma - 1.,
            0,
            decimal=2,
            err_msg=
            "Inconsistent OpticalPSF image for basic model after loading high-res pupil plane."
        )
    else:
        np.testing.assert_almost_equal(
            test_moments.moments_sigma / ref_moments.moments_sigma - 1.,
            0,
            decimal=1,
            err_msg=
            "Inconsistent OpticalPSF image for basic model after loading high-res pupil plane."
        )

    # Now supply the pupil plane at the original resolution, but remove some of the padding.  We
    # want it to properly recognize that it needs more padding, and include it.
    remove_pad = -23
    sub_im = im[im.bounds.withBorder(remove_pad)]
    test_psf = galsim.OpticalPSF(lam_over_diam,
                                 obscuration=obscuration,
                                 pupil_plane_im=sub_im,
                                 oversampling=pp_oversampling,
                                 pad_factor=pp_pad_factor)
    im_test_psf = galsim.ImageD(im_ref_psf.array.shape[0],
                                im_ref_psf.array.shape[1])
    im_test_psf = test_psf.drawImage(image=im_test_psf, scale=scale)
    test_moments = im_test_psf.FindAdaptiveMom()
    ref_moments = im_ref_psf.FindAdaptiveMom()
    np.testing.assert_almost_equal(
        test_moments.moments_sigma / ref_moments.moments_sigma - 1.,
        0,
        decimal=pp_decimal - 3,
        err_msg=
        "Inconsistent OpticalPSF image for basic model after loading less padded pupil plane."
    )

    # Now supply the pupil plane at the original resolution, with extra padding.
    new_pad = 76
    big_im = galsim.Image(im.bounds.withBorder(new_pad))
    big_im[im.bounds] = im
    test_psf = galsim.OpticalPSF(lam_over_diam,
                                 obscuration=obscuration,
                                 pupil_plane_im=big_im,
                                 oversampling=pp_oversampling,
                                 pad_factor=pp_pad_factor,
                                 gsparams=gsp)
    im_test_psf = galsim.ImageD(im_ref_psf.array.shape[0],
                                im_ref_psf.array.shape[1])
    im_test_psf = test_psf.drawImage(image=im_test_psf, scale=scale)
    test_moments = im_test_psf.FindAdaptiveMom()
    ref_moments = im_ref_psf.FindAdaptiveMom()
    np.testing.assert_almost_equal(
        test_moments.moments_sigma,
        ref_moments.moments_sigma,
        decimal=pp_decimal - 2,
        err_msg="Inconsistent OpticalPSF image size for basic model "
        "after loading more padded pupil plane.")

    # Check for same answer if we use image, array, or filename for reading in array.
    test_psf = galsim.OpticalPSF(lam_over_diam,
                                 obscuration=obscuration,
                                 pupil_plane_im=im,
                                 oversampling=pp_oversampling,
                                 pad_factor=pp_pad_factor)
    im_test_psf = test_psf.drawImage(scale=scale)
    test_psf_2 = galsim.OpticalPSF(lam_over_diam,
                                   obscuration=obscuration,
                                   pupil_plane_im=im.array,
                                   oversampling=pp_oversampling,
                                   pad_factor=pp_pad_factor)
    im_test_psf_2 = test_psf_2.drawImage(scale=scale)
    np.testing.assert_almost_equal(
        im_test_psf.array,
        im_test_psf_2.array,
        decimal=pp_decimal,
        err_msg="Inconsistent OpticalPSF image from Image vs. array.")

    # The following had used lam_over_diam, but that is now invalid because the fits file
    # has a specific pixel scale.  So we need to provide lam and diam separately so that the
    # units are consistent.
    diam = 500.e-9 / lam_over_diam * galsim.radians / galsim.arcsec
    test_psf_3 = galsim.OpticalPSF(lam=500,
                                   diam=diam,
                                   obscuration=obscuration,
                                   oversampling=pp_oversampling,
                                   pupil_plane_im=os.path.join(
                                       imgdir, pp_file),
                                   pad_factor=pp_pad_factor)
    im_test_psf_3 = test_psf_3.drawImage(scale=scale)
    np.testing.assert_almost_equal(
        im_test_psf.array,
        im_test_psf_3.array,
        decimal=pp_decimal,
        err_msg="Inconsistent OpticalPSF image from Image vs. file read-in.")
Exemple #30
0
def test_realspace_convolve():
    """Test the real-space convolution of a Moffat and a Box SBProfile against a known result.
    """
    import time
    t1 = time.time()
    # Code was formerly:
    # mySBP = galsim.SBMoffat(beta=1.5, truncationFWHM=4, flux=1, half_light_radius=1)
    #
    # ...but this is no longer quite so simple since we changed the handling of trunc to be in
    # physical units.  However, the same profile can be constructed using
    # fwhm=1.0927449310213702,
    # as calculated by interval bisection in devutils/external/calculate_moffat_radii.py
    fwhm_backwards_compatible = 1.0927449310213702
    #psf = galsim.SBMoffat(beta=1.5, fwhm=fwhm_backwards_compatible,
    #trunc=4*fwhm_backwards_compatible, flux=1)
    psf = galsim.SBMoffat(beta=1.5,
                          half_light_radius=1,
                          trunc=4 * fwhm_backwards_compatible,
                          flux=1)
    pixel = galsim.SBBox(xw=0.2, yw=0.2, flux=1.)
    conv = galsim.SBConvolve([psf, pixel], real_space=True)
    # Note: Using an image created from Maple "exact" calculations.
    saved_img = galsim.fits.read(os.path.join(imgdir, "moffat_pixel.fits"))
    img = galsim.ImageF(saved_img.bounds, scale=0.2)
    conv.draw(img.view())
    printval(img, saved_img)
    arg = abs(saved_img.array - img.array).argmax()
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Moffat convolved with Box SBProfile disagrees with expected result")

    # Repeat with the GSObject version of this:
    psf = galsim.Moffat(beta=1.5,
                        half_light_radius=1,
                        trunc=4 * fwhm_backwards_compatible,
                        flux=1)
    #psf = galsim.Moffat(beta=1.5, fwhm=fwhm_backwards_compatible,
    #trunc=4*fwhm_backwards_compatible, flux=1)
    pixel = galsim.Pixel(xw=0.2, yw=0.2, flux=1.)
    conv = galsim.Convolve([psf, pixel], real_space=True)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) disagrees with expected result")

    # Check with default_params
    conv = galsim.Convolve([psf, pixel],
                           real_space=True,
                           gsparams=default_params)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) with default_params disagrees with "
        "expected result")
    conv = galsim.Convolve([psf, pixel],
                           real_space=True,
                           gsparams=galsim.GSParams())
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([psf,pixel]) with GSParams() disagrees with "
        "expected result")

    # Other ways to do the convolution:
    conv = galsim.Convolve(psf, pixel, real_space=True)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve(psf,pixel) disagrees with expected result")

    # The real-space convolution algorithm is not (trivially) independent of the order of
    # the two things being convolved.  So check the opposite order.
    conv = galsim.Convolve([pixel, psf], real_space=True)
    conv.draw(img,
              dx=0.2,
              normalization="surface brightness",
              use_true_center=False)
    np.testing.assert_array_almost_equal(
        img.array,
        saved_img.array,
        5,
        err_msg=
        "Using GSObject Convolve([pixel,psf]) disagrees with expected result")

    # Test kvalues
    do_kvalue(conv, "Truncated Moffat convolved with Box")

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)