def compare_image_integrators():
    import galsim.integ
    import time

    pixel_scale = 0.2
    stamp_size = 128

    gal = galsim.Chromatic(galsim.Gaussian(half_light_radius=0.5), disk_SED)
    PSF_500 = galsim.Gaussian(half_light_radius=PSF_hlr)
    PSF = galsim.ChromaticAtmosphere(PSF_500, 500.0, zenith_angle)

    final = galsim.Convolve([gal, PSF])
    image = galsim.ImageD(stamp_size, stamp_size, scale=pixel_scale)

    # truth flux
    x = np.union1d(disk_SED.wave_list, bandpass.wave_list)
    x = x[(x <= bandpass.red_limit) & (x >= bandpass.blue_limit)]
    target = np.trapz(disk_SED(x) * bandpass(x), x)
    print('target')
    print('        {:14.11f}'.format(target))

    t1 = time.time()
    print('midpoint')
    for N in [10, 30, 100, 300, 1000, 3000]:
        image = final.drawImage(bandpass,
                                image=image,
                                integrator=galsim.integ.ContinuousIntegrator(
                                    rule=galsim.integ.midpt, N=N))
        mom = silentgetmoments(image)
        outstring = '   {:4d} {:14.11f} {:14.11f} {:14.11f} {:14.11f} {:14.11f} {:14.11f} {:14.11f}'
        print(
            outstring.format(N, image.array.sum(),
                             image.array.sum() - target, *mom))
    t2 = time.time()
    print('time for midpoint = %.2f' % (t2 - t1))

    print('trapezoidal')
    for N in [10, 30, 100, 300, 1000, 3000]:
        image = final.drawImage(bandpass,
                                image=image,
                                integrator=galsim.integ.ContinuousIntegrator(
                                    rule=np.trapz, N=N))
        mom = silentgetmoments(image)
        outstring = '   {:4d} {:14.11f} {:14.11f} {:14.11f} {:14.11f} {:14.11f} {:14.11f} {:14.11f}'
        print(
            outstring.format(N, image.array.sum(),
                             image.array.sum() - target, *mom))
    t3 = time.time()
    print('time for trapezoidal = %.2f' % (t3 - t2))
Exemplo n.º 2
0
def test_crg_roundtrip_larger_target_psf():
    """Test that drawing a chromatic galaxy with a color gradient directly using an LSST-size PSF
    is equivalent to first drawing the galaxy to HST-like images, and then using ChromaticRealGalaxy
    to produce an LSST-like image.
    """
    # load some spectra
    bulge_SED = (galsim.SED(
        os.path.join(sedpath, 'CWW_E_ext.sed'),
        wave_type='ang',
        flux_type='flambda').thin(rel_err=1e-3).withFluxDensity(
            target_flux_density=0.3, wavelength=500.0))

    disk_SED = (galsim.SED(
        os.path.join(sedpath, 'CWW_Sbc_ext.sed'),
        wave_type='ang',
        flux_type='flambda').thin(rel_err=1e-3).withFluxDensity(
            target_flux_density=0.3, wavelength=500.0))

    bulge = galsim.Sersic(n=4, half_light_radius=0.6) * bulge_SED
    disk = galsim.Sersic(n=1, half_light_radius=0.4) * disk_SED
    # Decenter components a bit to make the test more complicated
    disk = disk.shift(0.05, 0.1)
    gal = (bulge + disk).shear(g1=0.3, g2=0.1)

    # Much faster to just use some achromatic HST-like PSFs.  We'll make them slightly different in
    # each band though.
    f606w_PSF = galsim.ChromaticObject(galsim.Gaussian(half_light_radius=0.05))
    f814w_PSF = galsim.ChromaticObject(galsim.Gaussian(half_light_radius=0.07))
    LSSTPSF = galsim.ChromaticAtmosphere(galsim.Kolmogorov(fwhm=0.7),
                                         600.0,
                                         zenith_angle=0.0 * galsim.degrees)

    f606w = galsim.Bandpass(os.path.join(bppath, "ACS_wfc_F606W.dat"),
                            'nm').truncate()
    f814w = galsim.Bandpass(os.path.join(bppath, "ACS_wfc_F814W.dat"), 'nm')
    LSST_i = galsim.Bandpass(os.path.join(bppath, "LSST_r.dat"), 'nm')

    truth_image = galsim.Convolve(LSSTPSF, gal).drawImage(LSST_i,
                                                          nx=24,
                                                          ny=24,
                                                          scale=0.2)
    f606w_image = galsim.Convolve(f606w_PSF, gal).drawImage(f606w,
                                                            nx=192,
                                                            ny=192,
                                                            scale=0.03)
    f814w_image = galsim.Convolve(f814w_PSF, gal).drawImage(f814w,
                                                            nx=192,
                                                            ny=192,
                                                            scale=0.03)

    crg = galsim.ChromaticRealGalaxy.makeFromImages(
        images=[f606w_image, f814w_image],
        bands=[f606w, f814w],
        PSFs=[f606w_PSF, f814w_PSF],
        xis=[galsim.UncorrelatedNoise(1e-16)] * 2,
        SEDs=[bulge_SED, disk_SED])

    test_image = galsim.Convolve(crg, LSSTPSF).drawImage(LSST_i,
                                                         nx=24,
                                                         ny=24,
                                                         scale=0.2)

    truth_mom = galsim.hsm.FindAdaptiveMom(truth_image)
    test_mom = galsim.hsm.FindAdaptiveMom(test_image)

    np.testing.assert_allclose(test_mom.moments_amp,
                               truth_mom.moments_amp,
                               rtol=1e-3,
                               atol=0)
    np.testing.assert_allclose(test_mom.moments_centroid.x,
                               truth_mom.moments_centroid.x,
                               rtol=0.,
                               atol=1e-2)
    np.testing.assert_allclose(test_mom.moments_centroid.y,
                               truth_mom.moments_centroid.y,
                               rtol=0.,
                               atol=1e-2)
    np.testing.assert_allclose(test_mom.moments_sigma,
                               truth_mom.moments_sigma,
                               rtol=1e-3,
                               atol=0)
    np.testing.assert_allclose(test_mom.observed_shape.g1,
                               truth_mom.observed_shape.g1,
                               rtol=0,
                               atol=1e-4)
    np.testing.assert_allclose(test_mom.observed_shape.g2,
                               truth_mom.observed_shape.g2,
                               rtol=0,
                               atol=1e-4)

    # Invalid arguments
    with assert_raises(ValueError):
        crg = galsim.ChromaticRealGalaxy.makeFromImages(
            images=[f606w_image],
            bands=[f606w, f814w],
            PSFs=[f606w_PSF, f814w_PSF],
            xis=[galsim.UncorrelatedNoise(1e-16)] * 2,
            SEDs=[bulge_SED, disk_SED])
    with assert_raises(ValueError):
        crg = galsim.ChromaticRealGalaxy.makeFromImages(
            images=[f606w_image, f814w_image],
            bands=[f606w],
            PSFs=[f606w_PSF, f814w_PSF],
            xis=[galsim.UncorrelatedNoise(1e-16)] * 2,
            SEDs=[bulge_SED, disk_SED])
    with assert_raises(ValueError):
        crg = galsim.ChromaticRealGalaxy.makeFromImages(
            images=[f606w_image, f814w_image],
            bands=[f606w, f814w],
            PSFs=[f606w_PSF],
            xis=[galsim.UncorrelatedNoise(1e-16)] * 2,
            SEDs=[bulge_SED, disk_SED])
    with assert_raises(ValueError):
        crg = galsim.ChromaticRealGalaxy.makeFromImages(
            images=[f606w_image, f814w_image],
            bands=[f606w, f814w],
            PSFs=[f606w_PSF, f814w_PSF],
            xis=[galsim.UncorrelatedNoise(1e-16)],
            SEDs=[bulge_SED, disk_SED])
    with assert_raises(ValueError):
        crg = galsim.ChromaticRealGalaxy.makeFromImages(
            images=[f606w_image, f814w_image],
            bands=[f606w, f814w],
            PSFs=[f606w_PSF, f814w_PSF],
            xis=[galsim.UncorrelatedNoise(1e-16)] * 2,
            SEDs=[bulge_SED, disk_SED, disk_SED])
Exemplo n.º 3
0
def main(argv):
    # Where to find and output data
    path, filename = os.path.split(__file__)
    datapath = os.path.abspath(os.path.join(path, "data/"))
    outpath = os.path.abspath(os.path.join(path, "output/"))

    # In non-script code, use getLogger(__name__) at module scope instead.
    logging.basicConfig(format="%(message)s",
                        level=logging.INFO,
                        stream=sys.stdout)
    logger = logging.getLogger("demo12")

    # initialize (pseudo-)random number generator
    random_seed = 1234567
    rng = galsim.BaseDeviate(random_seed)

    # read in SEDs
    SED_names = ['CWW_E_ext', 'CWW_Sbc_ext', 'CWW_Scd_ext', 'CWW_Im_ext']
    SEDs = {}
    for SED_name in SED_names:
        SED_filename = os.path.join(galsim.meta_data.share_dir,
                                    '{0}.sed'.format(SED_name))
        # Here we create some galsim.SED objects to hold star or galaxy spectra.  The most
        # convenient way to create realistic spectra is to read them in from a two-column ASCII
        # file, where the first column is wavelength and the second column is flux. Wavelengths in
        # the example SED files are in Angstroms, flux in flambda.  We use a set of files that are
        # distributed with GalSim in the share/ directory.
        SED = galsim.SED(SED_filename, wave_type='Ang', flux_type='flambda')
        # The normalization of SEDs affects how many photons are eventually drawn into an image.
        # One way to control this normalization is to specify the flux density in photons per nm
        # at a particular wavelength.  For example, here we normalize such that the photon density
        # is 1 photon per nm at 500 nm.
        SEDs[SED_name] = SED.withFluxDensity(target_flux_density=1.0,
                                             wavelength=500)
    logger.debug('Successfully read in SEDs')

    # read in the LSST filters
    filter_names = 'ugrizy'
    filters = {}
    for filter_name in filter_names:
        filter_filename = os.path.join(datapath,
                                       'LSST_{0}.dat'.format(filter_name))
        # Here we create some galsim.Bandpass objects to represent the filters we're observing
        # through.  These include the entire imaging system throughput including the atmosphere,
        # reflective and refractive optics, filters, and the CCD quantum efficiency.  These are
        # also conveniently read in from two-column ASCII files where the first column is
        # wavelength and the second column is dimensionless throughput. The example filter files
        # units of nanometers for the wavelength type, so we specify that using the required
        # `wave_type` argument.
        filters[filter_name] = galsim.Bandpass(filter_filename, wave_type='nm')
        # For speed, we can thin out the wavelength sampling of the filter a bit.
        # In the following line, `rel_err` specifies the relative error when integrating over just
        # the filter (however, this is not necessarily the relative error when integrating over the
        # filter times an SED).
        filters[filter_name] = filters[filter_name].thin(rel_err=1e-4)
    logger.debug('Read in filters')

    pixel_scale = 0.2  # arcseconds

    #-----------------------------------------------------------------------------------------------
    # Part A: chromatic de Vaucouleurs galaxy

    # Here we create a chromatic version of a de Vaucouleurs profile using the Chromatic class.
    # This class lets one create chromatic versions of any galsim GSObject class.  The first
    # argument is the GSObject instance to be chromaticized, and the second argument is the
    # profile's SED.

    logger.info('')
    logger.info('Starting part A: chromatic De Vaucouleurs galaxy')
    redshift = 0.8
    mono_gal = galsim.DeVaucouleurs(half_light_radius=0.5)
    SED = SEDs['CWW_E_ext'].atRedshift(redshift)
    gal = galsim.Chromatic(mono_gal, SED)

    # You can still shear, shift, and dilate the resulting chromatic object.
    gal = gal.shear(g1=0.5, g2=0.3).dilate(1.05).shift((0.0, 0.1))
    logger.debug('Created Chromatic')

    # convolve with PSF to make final profile
    PSF = galsim.Moffat(fwhm=0.6, beta=2.5)
    final = galsim.Convolve([gal, PSF])
    logger.debug('Created final profile')

    # draw profile through LSST filters
    gaussian_noise = galsim.GaussianNoise(rng, sigma=0.1)
    for filter_name, filter_ in filters.iteritems():
        img = galsim.ImageF(64, 64, scale=pixel_scale)
        final.drawImage(filter_, image=img)
        img.addNoise(gaussian_noise)
        logger.debug('Created {0}-band image'.format(filter_name))
        out_filename = os.path.join(outpath,
                                    'demo12a_{0}.fits'.format(filter_name))
        galsim.fits.write(img, out_filename)
        logger.debug('Wrote {0}-band image to disk'.format(filter_name))
        logger.info('Added flux for {0}-band image: {1}'.format(
            filter_name, img.added_flux))

    logger.info(
        'You can display the output in ds9 with a command line that looks something like:'
    )
    logger.info(
        'ds9 output/demo12a_*.fits -match scale -zoom 2 -match frame image &')

    #-----------------------------------------------------------------------------------------------
    # Part B: chromatic bulge+disk galaxy

    logger.info('')
    logger.info('Starting part B: chromatic bulge+disk galaxy')
    redshift = 0.8
    # make a bulge ...
    mono_bulge = galsim.DeVaucouleurs(half_light_radius=0.5)
    bulge_SED = SEDs['CWW_E_ext'].atRedshift(redshift)
    # The `*` operator can be used as a shortcut for creating a chromatic version of a GSObject:
    bulge = mono_bulge * bulge_SED
    bulge = bulge.shear(g1=0.12, g2=0.07)
    logger.debug('Created bulge component')
    # ... and a disk ...
    mono_disk = galsim.Exponential(half_light_radius=2.0)
    disk_SED = SEDs['CWW_Im_ext'].atRedshift(redshift)
    disk = mono_disk * disk_SED
    disk = disk.shear(g1=0.4, g2=0.2)
    logger.debug('Created disk component')
    # ... and then combine them.
    bdgal = 1.1 * (
        0.8 * bulge + 4 * disk
    )  # you can add and multiply ChromaticObjects just like GSObjects
    bdfinal = galsim.Convolve([bdgal, PSF])
    # Note that at this stage, our galaxy is chromatic but our PSF is still achromatic.  Part C)
    # below will dive into chromatic PSFs.
    logger.debug('Created bulge+disk galaxy final profile')

    # draw profile through LSST filters
    gaussian_noise = galsim.GaussianNoise(rng, sigma=0.02)
    for filter_name, filter_ in filters.iteritems():
        img = galsim.ImageF(64, 64, scale=pixel_scale)
        bdfinal.drawImage(filter_, image=img)
        img.addNoise(gaussian_noise)
        logger.debug('Created {0}-band image'.format(filter_name))
        out_filename = os.path.join(outpath,
                                    'demo12b_{0}.fits'.format(filter_name))
        galsim.fits.write(img, out_filename)
        logger.debug('Wrote {0}-band image to disk'.format(filter_name))
        logger.info('Added flux for {0}-band image: {1}'.format(
            filter_name, img.added_flux))

    logger.info(
        'You can display the output in ds9 with a command line that looks something like:'
    )
    logger.info(
        'ds9 -rgb -blue -scale limits -0.2 0.8 output/demo12b_r.fits -green -scale limits'
        +
        ' -0.25 1.0 output/demo12b_i.fits -red -scale limits -0.25 1.0 output/demo12b_z.fits'
        + ' -zoom 2 &')

    #-----------------------------------------------------------------------------------------------
    # Part C: chromatic PSF

    logger.info('')
    logger.info('Starting part C: chromatic PSF')
    redshift = 0.0
    mono_gal = galsim.Exponential(half_light_radius=0.5)
    SED = SEDs['CWW_Im_ext'].atRedshift(redshift)
    # Here's another way to set the normalization of the SED.  If we want 50 counts to be drawn
    # when observing an object with this SED through the LSST g-band filter, for instance, then we
    # can do:
    SED = SED.withFlux(50.0, filters['g'])
    # The flux drawn through other bands, which sample different parts of the SED and have different
    # throughputs, will, of course, be different.
    gal = mono_gal * SED
    gal = gal.shear(g1=0.5, g2=0.3)
    logger.debug('Created `Chromatic` galaxy')

    # For a ground-based PSF, two chromatic effects are introduced by the atmosphere:
    # (i) differential chromatic refraction (DCR), and (ii) wavelength-dependent seeing.
    #
    # DCR shifts the position of the PSF as a function of wavelength.  Blue light is shifted
    # toward the zenith slightly more than red light.
    #
    # Kolmogorov turbulence in the atmosphere leads to a seeing size (e.g., FWHM) that scales with
    # wavelength to the (-0.2) power.
    #
    # The ChromaticAtmosphere function will attach both of these effects to a fiducial PSF at
    # some fiducial wavelength.

    # First we define a monochromatic PSF to be the fiducial PSF.
    PSF_500 = galsim.Moffat(beta=2.5, fwhm=0.5)
    # Then we use ChromaticAtmosphere to manipulate this fiducial PSF as a function of wavelength.
    # ChromaticAtmosphere also needs to know the wavelength of the fiducial PSF, and the location
    # and orientation of the object with respect to the zenith.  This final piece of information
    # can be specified in several ways (see the ChromaticAtmosphere docstring for all of them).
    # Here are a couple ways: let's pretend our object is located near M101 on the sky, we observe
    # it 1 hour before it transits and we're observing from Mauna Kea.
    ra = galsim.HMS_Angle("14:03:13")  # hours : minutes : seconds
    dec = galsim.DMS_Angle("54:20:57")  # degrees : minutes : seconds
    m101 = galsim.CelestialCoord(ra, dec)
    latitude = 19.8207 * galsim.degrees  # latitude of Mauna Kea
    HA = -1.0 * galsim.hours  # Hour angle = one hour before transit

    # Then we can compute the zenith angle and parallactic angle (which is is the position angle
    # of the zenith measured from North through East) of this object:
    za, pa = galsim.dcr.zenith_parallactic_angles(m101,
                                                  HA=HA,
                                                  latitude=latitude)
    # And then finally, create the chromatic PSF
    PSF = galsim.ChromaticAtmosphere(PSF_500,
                                     500.0,
                                     zenith_angle=za,
                                     parallactic_angle=pa)
    # We could have also just passed `m101`, `latitude` and `HA` to ChromaticAtmosphere directly:
    PSF = galsim.ChromaticAtmosphere(PSF_500,
                                     500.0,
                                     obj_coord=m101,
                                     latitude=latitude,
                                     HA=HA)
    # and proceed like normal.

    # convolve with galaxy to create final profile
    final = galsim.Convolve([gal, PSF])
    logger.debug('Created chromatic PSF finale profile')

    # Draw profile through LSST filters
    gaussian_noise = galsim.GaussianNoise(rng, sigma=0.03)
    for filter_name, filter_ in filters.iteritems():
        img = galsim.ImageF(64, 64, scale=pixel_scale)
        final.drawImage(filter_, image=img)
        img.addNoise(gaussian_noise)
        logger.debug('Created {0}-band image'.format(filter_name))
        out_filename = os.path.join(outpath,
                                    'demo12c_{0}.fits'.format(filter_name))
        galsim.fits.write(img, out_filename)
        logger.debug('Wrote {0}-band image to disk'.format(filter_name))
        logger.info('Added flux for {0}-band image: {1}'.format(
            filter_name, img.added_flux))

    logger.info(
        'You can display the output in ds9 with a command line that looks something like:'
    )
    logger.info(
        'ds9 output/demo12c_*.fits -match scale -zoom 2 -match frame image -blink &'
    )
sed1 = galsim.SED(spec="wave",wave_type='nm',flux_type='fphotons')
sed1 = sed1.withFlux(gal1_flux_thru_r,filters['r'])

sed2 = galsim.SED(spec="300-wave",wave_type = 'nm',flux_type = 'fphotons')
sed2 = sed1.withFlux(gal2_flux_thru_r,filters['r'])

gal1 = galsim.Gaussian(flux=1.,sigma=gal1_sigma)
psf1 = galsim.Moffat(beta=2.5,fwhm=0.5)
ra = galsim.HMS_Angle("14:03:13")
dec = galsim.DMS_Angle("54:20:57")
m101 = galsim.CelestialCoord(ra,dec)
latitude = 19.8207*galsim.degrees
HA=-1.0*galsim.hours
za,pa = galsim.dcr.zenith_parallactic_angles(m101,HA=HA,latitude=latitude)
chrom_psf1 = galsim.ChromaticAtmosphere(psf1,500.,obj_coord=m101,latitude=latitude,HA=HA)


gal2 = galsim.Gaussian(flux=1.,sigma=gal2_sigma)
psf2 = galsim.Gaussian(flux=1.,sigma = psf2_sigma)
ra = galsim.HMS_Angle("14:13:13")
dec = galsim.DMS_Angle("54:50:57")
rand_thing_next_to_m101 = galsim.CelestialCoord(ra,dec)
latitude_seoul = 37.5665*galsim.degrees #seoul
za,pa = galsim.dcr.zenith_parallactic_angles(rand_thing_next_to_m101,HA=HA,latitude=latitude)
chrom_psf2 = galsim.ChromaticAtmosphere(psf2,500.,obj_coord=rand_thing_next_to_m101,latitude=latitude_seoul,HA=HA)

chrom_gal1 = gal1*sed1
chrom_gal2 = gal2*sed2

chrom_total1 = galsim.Convolve([chrom_gal1,chrom_psf1])
Exemplo n.º 5
0
def test_dcr():
    """Test the dcr surface op
    """
    # This tests that implementing DCR with the surface op is equivalent to using
    # ChromaticAtmosphere.
    # We use fairly extreme choices for the parameters to make the comparison easier, so
    # we can still get good discrimination of any errors with only 10^6 photons.
    zenith_angle = 45 * galsim.degrees  # Larger angle has larger DCR.
    parallactic_angle = 129 * galsim.degrees  # Something random, not near 0 or 180
    pixel_scale = 0.03  # Small pixel scale means shifts are many pixels, rather than a fraction.
    alpha = -1.2  # The normal alpha is -0.2, so this is exaggerates the effect.

    bandpass = galsim.Bandpass('LSST_r.dat', 'nm')
    base_wavelength = bandpass.effective_wavelength
    base_wavelength += 500  # This exaggerates the effects fairly substantially.

    sed = galsim.SED('CWW_E_ext.sed', wave_type='ang', flux_type='flambda')

    flux = 1.e6
    base_PSF = galsim.Kolmogorov(fwhm=0.3)

    # Use ChromaticAtmosphere
    im1 = galsim.ImageD(50, 50, scale=pixel_scale)
    star = galsim.DeltaFunction() * sed
    star = star.withFlux(flux, bandpass=bandpass)
    chrom_PSF = galsim.ChromaticAtmosphere(base_PSF,
                                           base_wavelength=base_wavelength,
                                           zenith_angle=zenith_angle,
                                           parallactic_angle=parallactic_angle,
                                           alpha=alpha)
    chrom = galsim.Convolve(star, chrom_PSF)
    chrom.drawImage(bandpass, image=im1)

    # Use PhotonDCR
    im2 = galsim.ImageD(50, 50, scale=pixel_scale)
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           zenith_angle=zenith_angle,
                           parallactic_angle=parallactic_angle,
                           alpha=alpha)
    achrom = base_PSF.withFlux(flux)
    rng = galsim.BaseDeviate(31415)
    wave_sampler = galsim.WavelengthSampler(sed, bandpass, rng)
    surface_ops = [wave_sampler, dcr]
    achrom.drawImage(image=im2,
                     method='phot',
                     rng=rng,
                     surface_ops=surface_ops)

    im1 /= flux  # Divide by flux, so comparison is on a relative basis.
    im2 /= flux
    printval(im2, im1, show=False)
    np.testing.assert_almost_equal(
        im2.array,
        im1.array,
        decimal=4,
        err_msg="PhotonDCR didn't match ChromaticAtmosphere")

    # Repeat with thinned bandpass and SED to check that thin still works well.
    im3 = galsim.ImageD(50, 50, scale=pixel_scale)
    thin = 0.1  # Even higher also works.  But this is probably enough.
    thin_bandpass = bandpass.thin(thin)
    thin_sed = sed.thin(thin)
    print('len bp = %d => %d' %
          (len(bandpass.wave_list), len(thin_bandpass.wave_list)))
    print('len sed = %d => %d' % (len(sed.wave_list), len(thin_sed.wave_list)))
    wave_sampler = galsim.WavelengthSampler(thin_sed, thin_bandpass, rng)
    achrom.drawImage(image=im3,
                     method='phot',
                     rng=rng,
                     surface_ops=surface_ops)

    im3 /= flux
    printval(im3, im1, show=False)
    np.testing.assert_almost_equal(
        im3.array,
        im1.array,
        decimal=4,
        err_msg="thinning factor %f led to 1.e-4 level inaccuracy" % thin)

    # Check scale_unit
    im4 = galsim.ImageD(50, 50, scale=pixel_scale / 60)
    dcr = galsim.PhotonDCR(base_wavelength=base_wavelength,
                           zenith_angle=zenith_angle,
                           parallactic_angle=parallactic_angle,
                           scale_unit='arcmin',
                           alpha=alpha)
    surface_ops = [wave_sampler, dcr]
    achrom.dilate(1. / 60).drawImage(image=im4,
                                     method='phot',
                                     rng=rng,
                                     surface_ops=surface_ops)
    im4 /= flux
    printval(im4, im1, show=False)
    np.testing.assert_almost_equal(
        im4.array,
        im1.array,
        decimal=4,
        err_msg="PhotonDCR with scale_unit=arcmin, didn't match")

    # Check some other valid options
    # alpha = 0 means don't do any size scaling.
    # obj_coord, HA and latitude are another option for setting the angles
    # pressure, temp, and water pressure are settable.
    # Also use a non-trivial WCS.
    wcs = galsim.FitsWCS('des_data/DECam_00154912_12_header.fits')
    image = galsim.Image(50, 50, wcs=wcs)
    bandpass = galsim.Bandpass('LSST_r.dat', wave_type='nm').thin(0.1)
    base_wavelength = bandpass.effective_wavelength
    lsst_lat = galsim.Angle.from_dms('-30:14:23.76')
    lsst_long = galsim.Angle.from_dms('-70:44:34.67')
    local_sidereal_time = 3.14 * galsim.hours  # Not pi. This is the time for this observation.

    im5 = galsim.ImageD(50, 50, wcs=wcs)
    obj_coord = wcs.toWorld(im5.true_center)
    base_PSF = galsim.Kolmogorov(fwhm=0.9)
    achrom = base_PSF.withFlux(flux)
    dcr = galsim.PhotonDCR(
        base_wavelength=bandpass.effective_wavelength,
        obj_coord=obj_coord,
        HA=local_sidereal_time - obj_coord.ra,
        latitude=lsst_lat,
        pressure=72,  # default is 69.328
        temperature=290,  # default is 293.15
        H2O_pressure=0.9)  # default is 1.067
    #alpha=0)            # default is 0, so don't need to set it.
    surface_ops = [wave_sampler, dcr]
    achrom.drawImage(image=im5,
                     method='phot',
                     rng=rng,
                     surface_ops=surface_ops)

    im6 = galsim.ImageD(50, 50, wcs=wcs)
    star = galsim.DeltaFunction() * sed
    star = star.withFlux(flux, bandpass=bandpass)
    chrom_PSF = galsim.ChromaticAtmosphere(
        base_PSF,
        base_wavelength=bandpass.effective_wavelength,
        obj_coord=obj_coord,
        HA=local_sidereal_time - obj_coord.ra,
        latitude=lsst_lat,
        pressure=72,
        temperature=290,
        H2O_pressure=0.9,
        alpha=0)
    chrom = galsim.Convolve(star, chrom_PSF)
    chrom.drawImage(bandpass, image=im6)

    im5 /= flux  # Divide by flux, so comparison is on a relative basis.
    im6 /= flux
    printval(im5, im6, show=False)
    np.testing.assert_almost_equal(
        im5.array,
        im6.array,
        decimal=3,
        err_msg="PhotonDCR with alpha=0 didn't match")

    # Also check invalid parameters
    zenith_coord = galsim.CelestialCoord(13.54 * galsim.hours, lsst_lat)
    assert_raises(
        TypeError,
        galsim.PhotonDCR,
        zenith_angle=zenith_angle,
        parallactic_angle=parallactic_angle)  # base_wavelength is required
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  base_wavelength=500,
                  parallactic_angle=parallactic_angle
                  )  # zenith_angle (somehow) is required
    assert_raises(
        TypeError,
        galsim.PhotonDCR,
        500,
        zenith_angle=34.4,
        parallactic_angle=parallactic_angle)  # zenith_angle must be Angle
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  zenith_angle=zenith_angle,
                  parallactic_angle=34.5)  # parallactic_angle must be Angle
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  obj_coord=obj_coord,
                  latitude=lsst_lat)  # Missing HA
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  obj_coord=obj_coord,
                  HA=local_sidereal_time - obj_coord.ra)  # Missing latitude
    assert_raises(TypeError, galsim.PhotonDCR, 500,
                  obj_coord=obj_coord)  # Need either zenith_coord, or (HA,lat)
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  obj_coord=obj_coord,
                  zenith_coord=zenith_coord,
                  HA=local_sidereal_time -
                  obj_coord.ra)  # Can't have both HA and zenith_coord
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  obj_coord=obj_coord,
                  zenith_coord=zenith_coord,
                  latitude=lsst_lat)  # Can't have both lat and zenith_coord
    assert_raises(TypeError,
                  galsim.PhotonDCR,
                  500,
                  zenith_angle=zenith_angle,
                  parallactic_angle=parallactic_angle,
                  H20_pressure=1.)  # invalid (misspelled)
    assert_raises(ValueError,
                  galsim.PhotonDCR,
                  500,
                  zenith_angle=zenith_angle,
                  parallactic_angle=parallactic_angle,
                  scale_unit='inches')  # invalid scale_unit

    # Invalid to use dcr without some way of setting wavelengths.
    assert_raises(galsim.GalSimError,
                  achrom.drawImage,
                  im2,
                  method='phot',
                  surface_ops=[dcr])
Exemplo n.º 6
0
def test_CRG(args):
    """Predict an LSST or Euclid image given HST images of a galaxy with color gradients."""
    t0 = time.time()

    print("Constructing chromatic PSFs")
    in_PSF = galsim.ChromaticAiry(lam=700, diam=2.4)
    if args.lsst_psf:
        out_PSF = galsim.ChromaticAtmosphere(galsim.Kolmogorov(fwhm=0.6),
                                             500.0,
                                             zenith_angle=0 * galsim.degrees,
                                             parallactic_angle=0.0 *
                                             galsim.degrees)
    else:
        out_PSF = galsim.ChromaticAiry(lam=700, diam=1.2)  # Euclid-like

    print("Constructing filters and SEDs")
    waves = np.arange(550.0, 900.1, 10.0)
    visband = galsim.Bandpass(galsim.LookupTable(waves,
                                                 np.ones_like(waves),
                                                 interpolant='linear'),
                              wave_type='nm')
    split_points = np.linspace(550.0, 900.0, args.Nim + 1, endpoint=True)
    bands = [
        visband.truncate(blue_limit=blim, red_limit=rlim)
        for blim, rlim in zip(split_points[:-1], split_points[1:])
    ]
    outband = visband.truncate(blue_limit=args.out_blim,
                               red_limit=args.out_rlim)

    maxk = max([
        out_PSF.evaluateAtWavelength(waves[0]).maxK(),
        out_PSF.evaluateAtWavelength(waves[-1]).maxK()
    ])

    SEDs = [
        galsim.SED(galsim.LookupTable(waves, waves**i, interpolant='linear'),
                   wave_type='nm',
                   flux_type='fphotons').withFlux(1.0, visband)
        for i in range(args.NSED)
    ]

    print("Construction input noise correlation functions")
    rng = galsim.BaseDeviate(args.seed)
    in_xis = [
        galsim.getCOSMOSNoise(cosmos_scale=args.in_scale,
                              rng=rng).dilate(1 + i * 0.05).rotate(
                                  30 * i * galsim.degrees)
        for i in range(args.Nim)
    ]

    print("Constructing galaxy")
    components = [galsim.Gaussian(half_light_radius=0.3).shear(e1=0.1)]
    for i in range(1, args.Nim):
        components.append(
            galsim.Gaussian(half_light_radius=0.3 + 0.1 * np.cos(i)).shear(
                e=0.4 + np.cos(i) * 0.4,
                beta=i * galsim.radians).shift(0.4 * i, -0.4 * i))
    gal = galsim.Add([c * s for c, s in zip(components, SEDs)])
    gal = gal.shift(-gal.centroid(visband))

    in_prof = galsim.Convolve(gal, in_PSF)
    out_prof = galsim.Convolve(gal, out_PSF)

    print("Drawing input images")
    in_Nx = args.in_Nx
    in_Ny = args.in_Ny if args.in_Ny is not None else in_Nx
    in_imgs = [
        in_prof.drawImage(band, nx=in_Nx, ny=in_Ny, scale=args.in_scale)
        for band in bands
    ]
    [
        img.addNoiseSNR(xi, args.SNR, preserve_flux=True)
        for xi, img in zip(in_xis, in_imgs)
    ]

    print("Drawing true output image")
    out_img = out_prof.drawImage(outband,
                                 nx=args.out_Nx,
                                 ny=args.out_Nx,
                                 scale=args.out_scale)

    # Now "deconvolve" the chromatic HST PSF while asserting the correct SEDs.
    print("Constructing ChromaticRealGalaxy")
    crg = galsim.ChromaticRealGalaxy.makeFromImages(in_imgs,
                                                    bands,
                                                    in_PSF,
                                                    in_xis,
                                                    SEDs=SEDs,
                                                    maxk=maxk)
    # crg should be effectively the same thing as gal now.  Let's test.

    crg_prof = galsim.Convolve(crg, out_PSF)
    crg_img = crg_prof.drawImage(outband,
                                 nx=args.out_Nx,
                                 ny=args.out_Nx,
                                 scale=args.out_scale)
    print("Max comparison:", out_img.array.max(), crg_img.array.max())
    print("Sum comparison:", out_img.array.sum(), crg_img.array.sum())

    print("Took {} seconds".format(time.time() - t0))

    if args.plot:
        import matplotlib.pyplot as plt
        import matplotlib.gridspec as gridspec
        in_extent = [
            -in_Nx * args.in_scale / 2, in_Nx * args.in_scale / 2,
            -in_Ny * args.in_scale / 2, in_Ny * args.in_scale / 2
        ]
        out_extent = [
            -args.out_Nx * args.out_scale / 2,
            args.out_Nx * args.out_scale / 2,
            -args.out_Nx * args.out_scale / 2, args.out_Nx * args.out_scale / 2
        ]

        fig = plt.figure(figsize=(10, 5))
        outer_grid = gridspec.GridSpec(2, 1)

        # Input images
        inner_grid = gridspec.GridSpecFromSubplotSpec(1, args.Nim,
                                                      outer_grid[0])
        for i, img in enumerate(in_imgs):
            ax = plt.Subplot(fig, inner_grid[i])
            im = ax.imshow(img.array, extent=in_extent, cmap='viridis')
            ax.set_title("band[{}] input".format(i))
            # ax.set_xticks([])
            # ax.set_yticks([])
            fig.add_subplot(ax)
            plt.colorbar(im)

        inner_grid = gridspec.GridSpecFromSubplotSpec(1, 3, outer_grid[1])
        # Output image, truth, and residual
        ax = plt.Subplot(fig, inner_grid[0])
        ax.set_title("True output")
        im = ax.imshow(out_img.array, extent=out_extent, cmap='viridis')
        # ax.set_xticks([])
        # ax.set_yticks([])
        fig.add_subplot(ax)
        plt.colorbar(im)

        ax = plt.Subplot(fig, inner_grid[1])
        ax.set_title("Reconstructed output")
        # ax.set_xticks([])
        # ax.set_yticks([])
        im = ax.imshow(crg_img.array, extent=out_extent, cmap='viridis')
        fig.add_subplot(ax)
        plt.colorbar(im)

        ax = plt.Subplot(fig, inner_grid[2])
        ax.set_title("Residual")
        ax.set_xticks([])
        ax.set_yticks([])
        resid = crg_img.array - out_img.array
        vmin, vmax = np.percentile(resid, [5.0, 95.0])
        v = np.max([np.abs(vmin), np.abs(vmax)])
        im = ax.imshow(resid,
                       extent=out_extent,
                       cmap='seismic',
                       vmin=-v,
                       vmax=v)
        fig.add_subplot(ax)
        plt.colorbar(im)

        plt.tight_layout()
        plt.show()