Beispiel #1
0
def test_area_norm():
    """Check that area_norm works as expected"""
    f606w_cat = galsim.RealGalaxyCatalog('AEGIS_F606w_catalog.fits', dir=image_dir)
    f814w_cat = galsim.RealGalaxyCatalog('AEGIS_F814w_catalog.fits', dir=image_dir)

    psf = galsim.Gaussian(fwhm=0.6)

    rng = galsim.BaseDeviate(5772)
    crg1 = galsim.ChromaticRealGalaxy([f606w_cat, f814w_cat], random=True, rng=rng.duplicate())
    crg2 = galsim.ChromaticRealGalaxy([f606w_cat, f814w_cat], random=True, rng=rng.duplicate(),
                                      area_norm=galsim.real.HST_area)
    assert crg1 != crg2
    LSST_i = galsim.Bandpass(os.path.join(bppath, "LSST_r.dat"), 'nm')
    obj1 = galsim.Convolve(crg1, psf)
    obj2 = galsim.Convolve(crg2, psf)
    im1 = obj1.drawImage(LSST_i, exptime=1, area=1)
    im2 = obj2.drawImage(LSST_i, exptime=1, area=galsim.real.HST_area)
    printval(im1, im2)
    np.testing.assert_array_almost_equal(im1.array, im2.array)
    np.testing.assert_almost_equal(
            obj1.noise.getVariance(),
            obj2.noise.getVariance() * galsim.real.HST_area**2)

    # area_norm is equivalant to an overall scaling
    crg3 = galsim.ChromaticRealGalaxy([f606w_cat, f814w_cat], random=True, rng=rng.duplicate())
    crg3 /= galsim.real.HST_area
    obj3 = galsim.Convolve(crg3, psf)
    im3 = obj3.drawImage(LSST_i, exptime=1, area=galsim.real.HST_area)
    np.testing.assert_array_almost_equal(im3.array, im2.array)
    np.testing.assert_almost_equal(obj3.noise.getVariance(), obj2.noise.getVariance())

    rg1 = galsim.RealGalaxy(f606w_cat, index=1)
    rg2 = galsim.RealGalaxy(f606w_cat, index=1, area_norm=galsim.real.HST_area)
    assert rg1 != rg2
    obj1 = galsim.Convolve(rg1, psf)
    obj2 = galsim.Convolve(rg2, psf)
    im1 = obj1.drawImage()
    im2 = obj2.drawImage(exptime=1, area=galsim.real.HST_area)
    printval(im1, im2)
    np.testing.assert_array_almost_equal(im1.array, im2.array)
    np.testing.assert_almost_equal(
            obj1.noise.getVariance(),
            obj2.noise.getVariance() * galsim.real.HST_area**2)

    # area_norm is equivalant to an overall scaling
    rg3 = galsim.RealGalaxy(f606w_cat, index=1)
    rg3 /= galsim.real.HST_area
    obj3 = galsim.Convolve(rg3, psf)
    im3 = obj3.drawImage(exptime=1, area=galsim.real.HST_area)
    np.testing.assert_array_almost_equal(im3.array, im2.array)
    np.testing.assert_almost_equal(obj3.noise.getVariance(), obj2.noise.getVariance())
Beispiel #2
0
def test_real_galaxy_saved():
    """Test accuracy of various calculations with real RealGalaxy vs. stored SHERA result"""
    # read in real RealGalaxy from file
    # rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
    # This is an alternate way to give the directory -- as part of the catalog file name.
    full_catalog_file = os.path.join(image_dir, catalog_file)
    rgc = galsim.RealGalaxyCatalog(full_catalog_file)
    rg = galsim.RealGalaxy(rgc, index=ind_real)

    # read in expected result for some shear
    shera_image = galsim.fits.read(shera_file)
    shera_target_PSF_image = galsim.fits.read(shera_target_PSF_file)
    shera_target_PSF_image.scale = shera_target_pixel_scale

    # simulate the same galaxy with GalSim
    tmp_gal = rg.withFlux(shera_target_flux).shear(g1=targ_applied_shear1,
                                                   g2=targ_applied_shear2)
    tmp_psf = galsim.InterpolatedImage(shera_target_PSF_image)
    tmp_gal = galsim.Convolve(tmp_gal, tmp_psf)
    sim_image = tmp_gal.drawImage(scale=shera_target_pixel_scale,
                                  method='no_pixel')

    # there are centroid issues when comparing Shera vs. SBProfile outputs, so compare 2nd moments
    # instead of images
    sbp_res = sim_image.FindAdaptiveMom()
    shera_res = shera_image.FindAdaptiveMom()

    np.testing.assert_almost_equal(
        sbp_res.observed_shape.e1,
        shera_res.observed_shape.e1,
        2,
        err_msg="Error in comparison with SHERA result: e1")
    np.testing.assert_almost_equal(
        sbp_res.observed_shape.e2,
        shera_res.observed_shape.e2,
        2,
        err_msg="Error in comparison with SHERA result: e2")
    np.testing.assert_almost_equal(
        sbp_res.moments_sigma,
        shera_res.moments_sigma,
        2,
        err_msg="Error in comparison with SHERA result: sigma")

    check_basic(rg, "RealGalaxy", approx_maxsb=True)

    # Check picklability
    do_pickle(
        rgc, lambda x: [
            x.getGal(ind_real),
            x.getPSF(ind_real),
            x.getNoiseProperties(ind_real)
        ])
    do_pickle(
        rgc,
        lambda x: drawNoise(x.getNoise(ind_real, rng=galsim.BaseDeviate(123))))
    do_pickle(
        rg, lambda x: galsim.Convolve([x, galsim.Gaussian(sigma=1.7)]).
        drawImage(nx=20, ny=20, scale=0.7))
    do_pickle(rgc)
    do_pickle(rg)
Beispiel #3
0
    def sample(self, idx, px, py, flux, filter_norm, filters, psfs):
        obj = SimObj()
        obj.index = idx
        obj.x = px
        obj.y = py
        idx = np.random.randint(100)
        morphology = galsim.RealGalaxy(self.real_galaxy_catalog,
                                       index=idx,
                                       flux=flux)
        sed, redshift = self.generate_sed()
        sed = sed.withFlux(1, filters[filter_norm])
        sed = np.array([sed.calculateFlux(f) for _, f in filters.items()])
        convolved_image = {
            band: galsim.Convolve([morphology * sed[s], psfs[band]])
            for s, band in enumerate(filters)
        }

        obj.index = idx
        obj.redshift = redshift
        obj.is_star = False
        obj.catalog_index = idx
        obj.component = "mix"
        obj.sed = sed / np.sum(sed)

        return [obj], [convolved_image]
Beispiel #4
0
def test_real_galaxy_saved():
    """Test accuracy of various calculations with real RealGalaxy vs. stored SHERA result"""
    import time
    t1 = time.time()
    # read in real RealGalaxy from file
    rgc = galsim.RealGalaxyCatalog(catalog_file, image_dir)
    rg = galsim.RealGalaxy(rgc, index=ind_real)

    # read in expected result for some shear
    shera_image = galsim.fits.read(shera_file)
    shera_target_PSF_image = galsim.fits.read(shera_target_PSF_file)

    # simulate the same galaxy with GalSim
    sim_image = galsim.simReal(rg,
                               shera_target_PSF_image,
                               shera_target_pixel_scale,
                               g1=targ_applied_shear1,
                               g2=targ_applied_shear2,
                               rand_rotate=False,
                               target_flux=shera_target_flux)

    # there are centroid issues when comparing Shera vs. SBProfile outputs, so compare 2nd moments
    # instead of images
    sbp_res = sim_image.FindAdaptiveMom()
    shera_res = shera_image.FindAdaptiveMom()

    np.testing.assert_almost_equal(
        sbp_res.observed_shape.e1,
        shera_res.observed_shape.e1,
        2,
        err_msg="Error in comparison with SHERA result: e1")
    np.testing.assert_almost_equal(
        sbp_res.observed_shape.e2,
        shera_res.observed_shape.e2,
        2,
        err_msg="Error in comparison with SHERA result: e2")
    np.testing.assert_almost_equal(
        sbp_res.moments_sigma,
        shera_res.moments_sigma,
        2,
        err_msg="Error in comparison with SHERA result: sigma")

    # Check picklability
    do_pickle(
        rgc, lambda x: [
            x.getGal(ind_real),
            x.getPSF(ind_real),
            x.getNoiseProperties(ind_real)
        ])
    do_pickle(
        rgc,
        lambda x: drawNoise(x.getNoise(ind_real, rng=galsim.BaseDeviate(123))))
    do_pickle(
        rg, lambda x: galsim.Convolve([x, galsim.Gaussian(sigma=1.7)]).
        drawImage(nx=20, ny=20, scale=0.7))
    do_pickle(rgc)
    do_pickle(rg)

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Beispiel #5
0
def test_real_galaxy_makeFromImage():
    """Test accuracy of various calculations with fake Gaussian RealGalaxy vs. ideal expectations"""
    # read in faked Gaussian RealGalaxy from file
    rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
    rg = galsim.RealGalaxy(rgc, index=1)

    gal_image = rg.gal_image
    psf = rg.original_psf
    xi = rg.noise
    rg_2 = galsim.RealGalaxy.makeFromImage(gal_image, psf, xi)

    check_basic(rg_2, "RealGalaxy", approx_maxsb=True)
    do_pickle(
        rg_2, lambda x: [
            x.gal_image, x.psf_image,
            repr(x.noise), x.original_psf.flux, x.original_gal.flux, x.flux
        ])
    do_pickle(rg_2, lambda x: x.drawImage(nx=20, ny=20, scale=0.7))
    do_pickle(rg_2)

    # See if we get reasonably consistent results for rg and rg_2
    psf = galsim.Kolmogorov(fwhm=0.6)
    obj1 = galsim.Convolve(psf, rg)
    obj2 = galsim.Convolve(psf, rg_2)
    im1 = obj1.drawImage(scale=0.2, nx=12, ny=12)
    im2 = obj2.drawImage(image=im1.copy())
    atol = obj1.flux * 3e-5
    np.testing.assert_allclose(im1.array, im2.array, rtol=0, atol=atol)
Beispiel #6
0
def _BuildRealGalaxy(config, key, base, ignore, gsparams):
    """@brief Build a RealGalaxy type GSObject from user input.
    """
    if 'real_catalog' not in base:
        raise ValueError(
            "No real galaxy catalog available for building type = RealGalaxy")
    real_cat = base['real_catalog']

    # Special: if index is Sequence or Random, and max isn't set, set it to real_cat.nobjects-1
    if 'id' not in config:
        galsim.config.SetDefaultIndex(config, real_cat.nobjects)

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

    if 'rng' not in base:
        raise ValueError("No base['rng'] available for %s.type = RealGalaxy" %
                         (key))
    kwargs['rng'] = base['rng']

    if 'index' in kwargs:
        index = kwargs['index']
        if index >= real_cat.nobjects:
            raise IndexError(
                "%s index has gone past the number of entries in the catalog" %
                param_name)

    return galsim.RealGalaxy(real_cat, **kwargs), safe
Beispiel #7
0
def test_cosmos_fluxnorm():
    """Check for flux normalization properties of COSMOSCatalog class."""
    # Check that if we make a RealGalaxy catalog, and a COSMOSCatalog, and draw the real object, the
    # fluxes should match very well.  These correspond to 1s exposures.
    test_ind = 54
    rand_seed = 12345
    cat = galsim.COSMOSCatalog(
        file_name='real_galaxy_catalog_23.5_example.fits',
        dir=datapath,
        exclusion_level='none')
    rgc = galsim.RealGalaxyCatalog(
        file_name='real_galaxy_catalog_23.5_example.fits', dir=datapath)
    final_psf = galsim.Airy(diam=1.2,
                            lam=800.)  # PSF twice as big as HST in F814W.
    gal1 = cat.makeGalaxy(test_ind,
                          gal_type='real',
                          rng=galsim.BaseDeviate(rand_seed))
    gal2 = galsim.RealGalaxy(rgc,
                             index=test_ind,
                             rng=galsim.BaseDeviate(rand_seed))
    gal1 = galsim.Convolve(gal1, final_psf)
    gal2 = galsim.Convolve(gal2, final_psf)
    im1 = gal1.drawImage(scale=0.05)
    im2 = gal2.drawImage(scale=0.05)

    # Then check that if we draw a parametric representation that is achromatic, that the flux
    # matches reasonably well (won't be exact because model isn't perfect).
    gal1_param = cat.makeGalaxy(test_ind,
                                gal_type='parametric',
                                chromatic=False)
    gal1_param_final = galsim.Convolve(gal1_param, final_psf)
    im1_param = gal1_param_final.drawImage(scale=0.05)

    # Then check the same for a chromatic parametric representation that is drawn into the same
    # band.
    bp_file = os.path.join(galsim.meta_data.share_dir, 'bandpasses',
                           'ACS_wfc_F814W.dat')
    bandpass = galsim.Bandpass(bp_file,
                               wave_type='nm').withZeropoint(25.94)  #34.19)
    gal1_chrom = cat.makeGalaxy(test_ind,
                                gal_type='parametric',
                                chromatic=True)
    gal1_chrom = galsim.Convolve(gal1_chrom, final_psf)
    im1_chrom = gal1_chrom.drawImage(bandpass, scale=0.05)

    ref_val = [im1.array.sum(), im1.array.sum(), im1.array.sum()]
    test_val = [im2.array.sum(), im1_param.array.sum(), im1_chrom.array.sum()]
    np.testing.assert_allclose(
        ref_val,
        test_val,
        rtol=0.1,
        err_msg='Flux normalization problem in COSMOS galaxies')

    # Finally, check that the original COSMOS info is stored properly after transformations, for
    # both Sersic galaxies (like galaxy 0 in the catalog) and the one that is gal1_param above.
    gal0_param = cat.makeGalaxy(0, gal_type='parametric', chromatic=False)
    assert hasattr(gal0_param.shear(g1=0.05).original, 'index'), \
        'Sersic galaxy does not retain index information after transformation'
    assert hasattr(gal1_param.shear(g1=0.05).original, 'index'), \
        'Bulge+disk galaxy does not retain index information after transformation'
Beispiel #8
0
def _BuildRealGalaxy(config, base, ignore, gsparams, logger, param_name='RealGalaxy'):
    """@brief Build a RealGalaxy from the real_catalog input item.
    """
    real_cat = galsim.config.GetInputObj('real_catalog', config, base, param_name)

    # Special: if index is Sequence or Random, and max isn't set, set it to nobjects-1.
    # But not if they specify 'id' which overrides that.
    if 'id' not in config:
        galsim.config.SetDefaultIndex(config, real_cat.getNObjects())

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

    if 'rng' not in base:
        raise ValueError("No base['rng'] available for type = %s"%param_name)
    kwargs['rng'] = base['rng']

    if 'index' in kwargs:
        index = kwargs['index']
        if index >= real_cat.getNObjects():
            raise IndexError(
                "%s index has gone past the number of entries in the catalog"%index)

    kwargs['real_galaxy_catalog'] = real_cat
    if logger:
        logger.debug('obj %d: %s kwargs = %s',base['obj_num'],param_name,kwargs)

    gal = galsim.RealGalaxy(**kwargs)

    return gal, safe
Beispiel #9
0
def _BuildRealGalaxy(config, key, base, ignore, gsparams, logger):
    """@brief Build a RealGalaxy from the real_catalog input item.
    """
    if 'real_catalog' not in base:
        raise ValueError(
            "No real galaxy catalog available for building type = RealGalaxy")

    if 'num' in config:
        num, safe = ParseValue(config, 'num', base, int)
    else:
        num, safe = (0, True)
    ignore.append('num')

    if num < 0:
        raise ValueError("Invalid num < 0 supplied for RealGalaxy: num = %d" %
                         num)
    if num >= len(base['real_catalog']):
        raise ValueError(
            "Invalid num supplied for RealGalaxy (too large): num = %d" % num)

    real_cat = base['real_catalog'][num]

    # Special: if index is Sequence or Random, and max isn't set, set it to nobjects-1.
    # But not if they specify 'id' which overrides that.
    if 'id' not in config:
        galsim.config.SetDefaultIndex(config, real_cat.getNObjects())

    kwargs, safe1 = galsim.config.GetAllParams(
        config,
        key,
        base,
        req=galsim.__dict__['RealGalaxy']._req_params,
        opt=galsim.__dict__['RealGalaxy']._opt_params,
        single=galsim.__dict__['RealGalaxy']._single_params,
        ignore=ignore)
    safe = safe and safe1
    if gsparams: kwargs['gsparams'] = galsim.GSParams(**gsparams)
    if logger and galsim.RealGalaxy._takes_logger: kwargs['logger'] = logger

    if 'rng' not in base:
        raise ValueError("No base['rng'] available for %s.type = RealGalaxy" %
                         (key))
    kwargs['rng'] = base['rng']

    if 'index' in kwargs:
        index = kwargs['index']
        if index >= real_cat.getNObjects():
            raise IndexError(
                "%s index has gone past the number of entries in the catalog" %
                index)

    kwargs['real_galaxy_catalog'] = real_cat
    if logger:
        logger.debug('obj %d: RealGalaxy kwargs = %s', base['obj_num'],
                     str(kwargs))

    gal = galsim.RealGalaxy(**kwargs)

    return gal, safe
Beispiel #10
0
 def _makeReal(self, indices, noise_pad_size, rng, gsparams):
     return [
         galsim.RealGalaxy(self.real_cat,
                           index=self.orig_index[i],
                           noise_pad_size=noise_pad_size,
                           rng=rng,
                           gsparams=gsparams) for i in indices
     ]
Beispiel #11
0
def test_cosmos_fluxnorm():
    """Check for flux normalization properties of COSMOSCatalog class."""
    import time
    t1 = time.time()

    # Check that if we make a RealGalaxy catalog, and a COSMOSCatalog, and draw the real object, the
    # fluxes should match very well.  These correspond to 1s exposures.
    test_ind = 54
    rand_seed = 12345
    cat = galsim.COSMOSCatalog(file_name='real_galaxy_catalog_example.fits',
                               dir=datapath,
                               exclude_fail=False,
                               exclude_bad=False)
    rgc = galsim.RealGalaxyCatalog(
        file_name='real_galaxy_catalog_example.fits', dir=datapath)
    final_psf = galsim.Airy(diam=1.2,
                            lam=800.)  # PSF twice as big as HST in F814W.
    gal1 = cat.makeGalaxy(test_ind,
                          gal_type='real',
                          rng=galsim.BaseDeviate(rand_seed))
    gal2 = galsim.RealGalaxy(rgc,
                             index=test_ind,
                             rng=galsim.BaseDeviate(rand_seed))
    gal1 = galsim.Convolve(gal1, final_psf)
    gal2 = galsim.Convolve(gal2, final_psf)
    im1 = gal1.drawImage(scale=0.05)
    im2 = gal2.drawImage(scale=0.05)

    # Then check that if we draw a parametric representation that is achromatic, that the flux
    # matches reasonably well (won't be exact because model isn't perfect).
    gal1_param = cat.makeGalaxy(test_ind,
                                gal_type='parametric',
                                chromatic=False)
    gal1_param = galsim.Convolve(gal1_param, final_psf)
    im1_param = gal1_param.drawImage(scale=0.05)

    # Then check the same for a chromatic parametric representation that is drawn into the same
    # band.
    bp_file = os.path.join(galsim.meta_data.share_dir, 'wfc_F814W.dat.gz')
    bandpass = galsim.Bandpass(bp_file, wave_type='ang').thin().withZeropoint(
        25.94)  #34.19)
    gal1_chrom = cat.makeGalaxy(test_ind,
                                gal_type='parametric',
                                chromatic=True)
    gal1_chrom = galsim.Convolve(gal1_chrom, final_psf)
    im1_chrom = gal1_chrom.drawImage(bandpass, scale=0.05)

    ref_val = [im1.array.sum(), im1.array.sum(), im1.array.sum()]
    test_val = [im2.array.sum(), im1_param.array.sum(), im1_chrom.array.sum()]
    np.testing.assert_allclose(
        ref_val,
        test_val,
        rtol=0.1,
        err_msg='Flux normalization problem in COSMOS galaxies')

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Beispiel #12
0
    def _makeSingleGalaxy(cosmos_catalog, index, gal_type, noise_pad_size=5, deep=False,
                          rng=None, sersic_prec=0.05, gsparams=None):
        # A static function that mimics the functionality of COSMOSCatalog.makeGalaxy()
        # for single index and chromatic=False.
        # The only point of this class is to circumvent some pickling issues when using
        # config objects with type : COSMOSGalaxy.  It's a staticmethod, which means it
        # cannot use any self attributes.  Just methods.  (Which also means we can use it
        # through a proxy COSMOSCatalog object, which we need for the config layer.)

        if not cosmos_catalog.canMakeReal():
            if gal_type is None:
                gal_type = 'parametric'
            elif gal_type != 'parametric':
                raise ValueError("Only 'parametric' galaxy type is allowed when use_real == False")

        if gal_type not in ['real', 'parametric']:
            raise ValueError("Invalid galaxy type %r"%gal_type)

        if gal_type == 'real' and rng is None:
            rng = galsim.BaseDeviate()

        if gal_type == 'real':
            real_params = cosmos_catalog.getRealParams(index)
            gal = galsim.RealGalaxy(real_params, noise_pad_size=noise_pad_size, rng=rng,
                                    gsparams=gsparams)
        else:
            record = cosmos_catalog.getParametricRecord(index)
            gal = COSMOSCatalog._buildParametric(record, sersic_prec, gsparams, chromatic=False)

        # If trying to use the 23.5 sample and "fake" a deep sample, rescale the size and flux as
        # suggested in the GREAT3 handbook.
        if deep:
            if self.use_sample == '23.5':
                # Rescale the flux to get a limiting mag of 25 in F814W when starting with a
                # limiting mag of 23.5.  Make the galaxies a factor of 0.6 smaller and appropriately
                # fainter.
                flux_factor = 10.**(-0.4*1.5)
                size_factor = 0.6
                gal = gal.dilate(size_factor) * flux_factor
            else:
                import warnings
                warnings.warn(
                    'Ignoring `deep` argument, because the sample being used already '+
                    'corresponds to a flux limit of F814W<25.2')

        # Store the orig_index as gal.index, since the above RealGalaxy initialization just sets it
        # as 0.  Plus, it isn't set at all if we make a parametric galaxy.  And if we are doing the
        # deep scaling, then it gets messed up by that.  If we have done some transformations, and
        # are also doing later transformation, it will take the `original` attribute that is already
        # there.  So having `index` doesn't help, and we also need `original.index`.
        gal.index = cosmos_catalog.getOrigIndex(index)
        if hasattr(gal, 'original'):
            gal.original.index = cosmos_catalog.getOrigIndex(index)

        return gal
Beispiel #13
0
def test_ne():
    """ Check that inequality works as expected."""
    rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
    f606w_cat = galsim.RealGalaxyCatalog('AEGIS_F606w_catalog.fits',
                                         dir=image_dir)
    f814w_cat = galsim.RealGalaxyCatalog('AEGIS_F814w_catalog.fits',
                                         dir=image_dir)
    crg1 = galsim.ChromaticRealGalaxy([f606w_cat, f814w_cat], index=0)
    crg2 = galsim.ChromaticRealGalaxy([f606w_cat, f814w_cat], index=1)
    covspec1 = crg1.covspec
    covspec2 = crg2.covspec

    gsp = galsim.GSParams(folding_threshold=1.1e-3)

    objs = [
        galsim.RealGalaxy(rgc, index=0),
        galsim.RealGalaxy(rgc, index=1),
        galsim.RealGalaxy(rgc, index=0, x_interpolant='Linear'),
        galsim.RealGalaxy(rgc, index=0, k_interpolant='Linear'),
        galsim.RealGalaxy(rgc, index=0, flux=1.1),
        galsim.RealGalaxy(rgc, index=0, flux_rescale=1.2),
        galsim.RealGalaxy(rgc, index=0, area_norm=2),
        galsim.RealGalaxy(rgc, index=0, pad_factor=1.1),
        galsim.RealGalaxy(rgc, index=0, noise_pad_size=5.0),
        galsim.RealGalaxy(rgc, index=0, gsparams=gsp), crg1, crg2,
        galsim.ChromaticRealGalaxy([f606w_cat, f814w_cat],
                                   index=0,
                                   k_interpolant='Linear'), covspec1, covspec2
    ]
    all_obj_diff(objs)
    for obj in objs[:-5]:
        do_pickle(obj)

    # CovarianceSpectrum and ChromaticRealGalaxy are both reprable, but their reprs are rather
    # large, so the eval(repr) checks take a long time.
    # Therefore, run them from command line, but not from pytest.
    if __name__ == '__main__':
        do_pickle(crg1)
        do_pickle(covspec1)
    else:
        do_pickle(crg1, irreprable=True)
        do_pickle(covspec1, irreprable=True)
Beispiel #14
0
def test_flux():
    """ Check that setting flux and flux_rescale work properly"""
    rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
    psf = galsim.Gaussian(sigma=1.7)

    rg1 = galsim.RealGalaxy(rgc, index=0)
    rg2 = galsim.RealGalaxy(rgc, index=0, flux=1.7)
    rg3 = galsim.RealGalaxy(rgc, index=0, flux=17)
    rg4 = galsim.RealGalaxy(rgc, index=0, flux=-17)
    rg5 = galsim.RealGalaxy(rgc, index=0, flux_rescale=1.7)
    rg6 = galsim.RealGalaxy(rgc, index=0, flux_rescale=-17)

    np.testing.assert_almost_equal(rg2.flux, 1.7)
    np.testing.assert_almost_equal(rg3.flux, 17)
    np.testing.assert_almost_equal(rg4.flux, -17)
    np.testing.assert_almost_equal(rg5.flux, 1.7 * rg1.flux)
    np.testing.assert_almost_equal(rg6.flux, -17 * rg1.flux)

    check_basic(rg2, "RealGalaxy flux=1.7", approx_maxsb=True)
    check_basic(rg3, "RealGalaxy flux=17", approx_maxsb=True)
    check_basic(rg4, "RealGalaxy flux=-17", approx_maxsb=True)
    check_basic(rg5, "RealGalaxy flux_rescale=1.7", approx_maxsb=True)
    check_basic(rg6, "RealGalaxy flux_rescale=-17", approx_maxsb=True)

    do_pickle(rg2)
    do_pickle(rg3)
    do_pickle(rg4)
    do_pickle(rg5)
    do_pickle(rg6)
Beispiel #15
0
def galSimRealGalaxy(flux,
                     real_galaxy_catalog,
                     index=None,
                     psfImage=None,
                     random=False,
                     returnObj=True,
                     plotFake=False,
                     drawMethod='auto',
                     addPoisson=False,
                     scale=1.0,
                     transform=None):
    """
    Real galaxy
    """

    if index is None:
        random = True
    realObj = galsim.RealGalaxy(real_galaxy_catalog,
                                index=index,
                                random=random)
    index = realObj.index

    # Pass the flux to the object
    realObj = realObj.withFlux(flux)

    #do the transformation from sky to pixel coordinates, if given
    if transform is not None:
        realObj = realObj.transform(*tuple(transform.ravel()))

    # Convolve the Sersic model using the provided PSF image
    if psfImage is not None:
        # Convert the PSF Image Array into a GalSim Object
        # Norm=True by default
        psfObj = arrayToGSObj(psfImage, norm=True)
        realFinal = galsim.Convolve([realObj, psfObj])
    else:
        realFinal = realFinal

    # Make a PNG figure of the fake galaxy to check if everything is Ok
    # TODO: For test, should be removed later
    if plotFake:
        plotFakeGalaxy(realFinal, galID=index, suffix='realga')

    # Now, by default, the function will just return the GSObj
    if returnObj:
        return realFinal
    else:
        return galSimDrawImage(realFinal,
                               method=drawMethod,
                               scale=scale,
                               addPoisson=addPoisson)
Beispiel #16
0
def test_ne():
    """ Check that inequality works as expected."""
    rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
    gsp = galsim.GSParams(folding_threshold=1.1e-3)

    gals = [
        galsim.RealGalaxy(rgc, index=0),
        galsim.RealGalaxy(rgc, index=1),
        galsim.RealGalaxy(rgc, index=0, x_interpolant='Linear'),
        galsim.RealGalaxy(rgc, index=0, k_interpolant='Linear'),
        galsim.RealGalaxy(rgc, index=0, flux=1.1),
        galsim.RealGalaxy(rgc, index=0, pad_factor=1.1),
        galsim.RealGalaxy(rgc, index=0, noise_pad_size=5.0),
        galsim.RealGalaxy(rgc, index=0, gsparams=gsp)
    ]
    all_obj_diff(gals)
Beispiel #17
0
def _BuildRealGalaxy(config,
                     base,
                     ignore,
                     gsparams,
                     logger,
                     param_name='RealGalaxy'):
    """Build a RealGalaxy from the real_catalog input item.
    """
    real_cat = galsim.config.GetInputObj('real_catalog', config, base,
                                         param_name)

    # Special: if index is Sequence or Random, and max isn't set, set it to nobjects-1.
    # But not if they specify 'id' or have 'random=True', which overrides that.
    if 'id' not in config:
        if 'random' not in config:
            galsim.config.SetDefaultIndex(config, real_cat.getNObjects())
        else:
            if not config['random']:
                galsim.config.SetDefaultIndex(config, real_cat.getNObjects())
                # Need to do this to avoid being caught by the GetAllParams() call, which will flag
                # it if it has 'index' and 'random' set (but 'random' is False, so really it's OK).
                del config['random']

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

    kwargs['rng'] = galsim.config.GetRNG(config, base, logger, param_name)

    if 'index' in kwargs:
        index = kwargs['index']
        if index >= real_cat.getNObjects() or index < 0:
            raise galsim.GalSimConfigError(
                "index=%s has gone past the number of entries in the RealGalaxyCatalog"
                % index)

    kwargs['real_galaxy_catalog'] = real_cat
    logger.debug('obj %d: %s kwargs = %s', base.get('obj_num', 0), param_name,
                 kwargs)

    gal = galsim.RealGalaxy(**kwargs)

    return gal, safe
Beispiel #18
0
    def _makeSingleGalaxy(cosmos_catalog,
                          index,
                          gal_type,
                          noise_pad_size=5,
                          deep=False,
                          rng=None,
                          gsparams=None):
        # A static function that mimics the functionality of COSMOSCatalog.makeGalaxy()
        # for single index and chromatic=False.
        # The only point of this class is to circumvent some pickling issues when using
        # config objects with type : COSMOSGalaxy.  It's a staticmethod, which means it
        # cannot use any self attributes.  Just methods.  (Which also means we can use it
        # through a proxy COSMOSCatalog object, which we need for the config layer.)

        if not cosmos_catalog.canMakeReal():
            if gal_type is None:
                gal_type = 'parametric'
            elif gal_type != 'parametric':
                raise ValueError(
                    "Only 'parametric' galaxy type is allowed when use_real == False"
                )

        if gal_type not in ['real', 'parametric']:
            raise ValueError("Invalid galaxy type %r" % gal_type)

        if gal_type == 'real' and rng is None:
            rng = galsim.BaseDeviate()

        if gal_type == 'real':
            real_params = cosmos_catalog.getRealParams(index)
            gal = galsim.RealGalaxy(real_params,
                                    noise_pad_size=noise_pad_size,
                                    rng=rng,
                                    gsparams=gsparams)
        else:
            record = cosmos_catalog.getParametricRecord(index)
            gal = COSMOSCatalog._buildParametric(record, gsparams=gsparams)

        # If deep, rescale the size and flux
        if deep:
            # Rescale the flux to get a limiting mag of 25 in F814W.  Current limiting mag is 23.5,
            # so it's a magnitude difference of 1.5.  Make the galaxies a factor of 0.6 smaller and
            # appropriately fainter.
            flux_factor = 10.**(-0.4 * 1.5)
            size_factor = 0.6
            gal = gal.dilate(size_factor) * flux_factor

        return gal
Beispiel #19
0
def test_ne():
    import time
    t1 = time.time()
    rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
    gsp = galsim.GSParams(folding_threshold=1.1e-3)

    gals = [galsim.RealGalaxy(rgc, index=0),
            galsim.RealGalaxy(rgc, index=1),
            galsim.RealGalaxy(rgc, index=0, x_interpolant='Linear'),
            galsim.RealGalaxy(rgc, index=0, k_interpolant='Linear'),
            galsim.RealGalaxy(rgc, index=0, flux=1.1),
            galsim.RealGalaxy(rgc, index=0, pad_factor=1.1),
            galsim.RealGalaxy(rgc, index=0, noise_pad_size=5.0),
            galsim.RealGalaxy(rgc, index=0, gsparams=gsp)]
    all_obj_diff(gals)

    t2 = time.time()
    print 'time for %s = %.2f'%(funcname(),t2-t1)
Beispiel #20
0
def test_real_galaxy_saved():
    """Test accuracy of various calculations with real RealGalaxy vs. stored SHERA result"""
    import time
    t1 = time.time()
    # read in real RealGalaxy from file
    rgc = galsim.RealGalaxyCatalog(catalog_file, image_dir)
    rg = galsim.RealGalaxy(rgc, index=ind_real)

    # read in expected result for some shear
    shera_image = galsim.fits.read(shera_file)
    shera_target_PSF_image = galsim.fits.read(shera_target_PSF_file)

    # simulate the same galaxy with GalSim
    sim_image = galsim.simReal(rg,
                               shera_target_PSF_image,
                               shera_target_pixel_scale,
                               g1=targ_applied_shear1,
                               g2=targ_applied_shear2,
                               rand_rotate=False,
                               target_flux=shera_target_flux)

    # there are centroid issues when comparing Shera vs. SBProfile outputs, so compare 2nd moments
    # instead of images
    sbp_res = sim_image.FindAdaptiveMom()
    shera_res = shera_image.FindAdaptiveMom()

    np.testing.assert_almost_equal(
        sbp_res.observed_shape.e1,
        shera_res.observed_shape.e1,
        2,
        err_msg="Error in comparison with SHERA result: e1")
    np.testing.assert_almost_equal(
        sbp_res.observed_shape.e2,
        shera_res.observed_shape.e2,
        2,
        err_msg="Error in comparison with SHERA result: e2")
    np.testing.assert_almost_equal(
        sbp_res.moments_sigma,
        shera_res.moments_sigma,
        2,
        err_msg="Error in comparison with SHERA result: sigma")
    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Beispiel #21
0
def main(argv):
    """
    Make a fits image cube using real COSMOS galaxies from a catalog describing the training
    sample.

      - The number of images in the cube matches the number of rows in the catalog.
      - Each image size is computed automatically by GalSim based on the Nyquist size.
      - Both galaxies and stars.
      - PSF is a double Gaussian, the same for each galaxy.
      - Galaxies are randomly rotated to remove the imprint of any lensing shears in the COSMOS
        data.
      - The same shear is applied to each galaxy.
      - Noise is Poisson using a nominal sky value of 1.e6 ADU/arcsec^2,
        the noise in the original COSMOS data.
    """
    logging.basicConfig(format="%(message)s", level=logging.INFO, stream=sys.stdout)
    logger = logging.getLogger("demo6")

    # Define some parameters we'll use below.

    cat_file_name = 'real_galaxy_catalog_23.5_example.fits'
    dir = 'data'
    # Make output directory if not already present.
    if not os.path.isdir('output'):
        os.mkdir('output')
    cube_file_name = os.path.join('output','cube_real.fits')
    psf_file_name = os.path.join('output','psf_real.fits')

    random_seed = 1512413
    sky_level = 1.e6        # ADU / arcsec^2
    pixel_scale = 0.16      # arcsec
    gal_flux = 1.e5         # arbitrary choice, makes nice (not too) noisy images
    gal_g1 = -0.027         #
    gal_g2 = 0.031          #
    gal_mu = 1.082          # mu = ( (1-kappa)^2 - g1^2 - g2^2 )^-1
    psf_inner_fwhm = 0.6    # arcsec
    psf_outer_fwhm = 2.3    # arcsec
    psf_inner_fraction = 0.8  # fraction of total PSF flux in the inner Gaussian
    psf_outer_fraction = 0.2  # fraction of total PSF flux in the inner Gaussian
    ngal = 100

    logger.info('Starting demo script 6 using:')
    logger.info('    - real galaxies from catalog %r',cat_file_name)
    logger.info('    - double Gaussian PSF')
    logger.info('    - pixel scale = %.2f',pixel_scale)
    logger.info('    - Applied gravitational shear = (%.3f,%.3f)',gal_g1,gal_g2)
    logger.info('    - Poisson noise (sky level = %.1e).', sky_level)

    # Read in galaxy catalog
    # Note: dir is the directory both for the catalog itself and also the directory prefix
    # for the image files listed in the catalog.
    # If the images are in a different directory, you may also specify image_dir, which gives
    # the relative path from dir to wherever the images are located.
    real_galaxy_catalog = galsim.RealGalaxyCatalog(cat_file_name, dir=dir)
    logger.info('Read in %d real galaxies from catalog', real_galaxy_catalog.nobjects)

    # Make the double Gaussian PSF
    psf1 = galsim.Gaussian(fwhm = psf_inner_fwhm, flux = psf_inner_fraction)
    psf2 = galsim.Gaussian(fwhm = psf_outer_fwhm, flux = psf_outer_fraction)
    psf = psf1+psf2
    # Draw the PSF with no noise.
    psf_image = psf.drawImage(scale = pixel_scale)
    # write to file
    psf_image.write(psf_file_name)
    logger.info('Created PSF and wrote to file %r',psf_file_name)

    # Build the images
    all_images = []
    for k in range(ngal):
        logger.debug('Start work on image %d',k)
        t1 = time.time()

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

        gal = galsim.RealGalaxy(real_galaxy_catalog, index = k)
        logger.debug('   Read in training sample galaxy and PSF from file')
        t2 = time.time()

        # Set the flux
        gal = gal.withFlux(gal_flux)

        # Rotate by a random angle
        theta = 2.*math.pi * rng() * galsim.radians
        gal = gal.rotate(theta)

        # Apply the desired shear
        gal = gal.shear(g1=gal_g1, g2=gal_g2)

        # Also apply a magnification mu = ( (1-kappa)^2 - |gamma|^2 )^-1
        # This conserves surface brightness, so it scales both the area and flux.
        gal = gal.magnify(gal_mu)

        # Make the combined profile
        final = galsim.Convolve([psf, gal])

        # Offset by up to 1/2 pixel in each direction
        # We had previously (in demo4 and demo5) used shift(dx,dy) as a way to shift the center of
        # the image.  Since that is applied to the galaxy, the units are arcsec (since the galaxy
        # profile itself doesn't know about the pixel scale).  Here, the offset applies to the
        # drawn image, which does know about the pixel scale, so the units of offset are pixels,
        # not arcsec.  Here, we apply an offset of up to half a pixel in each direction.
        dx = rng() - 0.5
        dy = rng() - 0.5

        # Draw the profile
        if k == 0:
            # Note that the offset argument may be a galsim.PositionD object or a tuple (dx,dy).
            im = final.drawImage(scale=pixel_scale, offset=(dx,dy))
            xsize, ysize = im.array.shape
        else:
            im = galsim.ImageF(xsize,ysize)
            final.drawImage(im, scale=pixel_scale, offset=(dx,dy))

        logger.debug('   Drew image')
        t3 = time.time()

        # Add a constant background level
        background = sky_level * pixel_scale**2
        im += background

        # Add Poisson noise.  This time, we don't give a sky_level, since we have already
        # added it to the image, so we don't want any more added.  The sky_level parameter
        # really defines how much _extra_ sky should be added above what is already in the image.
        im.addNoise(galsim.PoissonNoise(rng))

        logger.debug('   Added Poisson noise')
        t4 = time.time()

        # Store that into the list of all images
        all_images += [im]
        t5 = time.time()

        logger.debug('   Times: %f, %f, %f, %f',t2-t1, t3-t2, t4-t3, t5-t4)
        logger.info('Image %d: size = %d x %d, total time = %f sec', k, xsize, ysize, t5-t1)

    logger.info('Done making images of galaxies')

    # Now write the image to disk.
    # We write the images to a fits data cube.
    galsim.fits.writeCube(all_images, cube_file_name)
    logger.info('Wrote image to fits data cube %r',cube_file_name)
Beispiel #22
0
def test_real_galaxy_ideal():
    """Test accuracy of various calculations with fake Gaussian RealGalaxy vs. ideal expectations"""
    ind_fake = 1  # index of mock galaxy (Gaussian) in catalog
    fake_gal_fwhm = 0.7  # arcsec
    fake_gal_shear1 = 0.29  # shear representing intrinsic shape component 1
    fake_gal_shear2 = -0.21  # shear representing intrinsic shape component 2
    # note non-round, to detect possible issues with x<->y or others that might not show up using
    # circular galaxy

    fake_gal_flux = 1000.0
    fake_gal_orig_PSF_fwhm = 0.1  # arcsec
    fake_gal_orig_PSF_shear1 = 0.0
    fake_gal_orig_PSF_shear2 = -0.07

    # read in faked Gaussian RealGalaxy from file
    rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
    assert len(rgc) == rgc.getNObjects() == rgc.nobjects == len(rgc.cat)
    rg = galsim.RealGalaxy(rgc, index=ind_fake)
    # as a side note, make sure it behaves okay given a legit RNG and a bad RNG
    # or when trying to specify the galaxy too many ways
    rg_1 = galsim.RealGalaxy(rgc, index=ind_fake, rng=galsim.BaseDeviate(1234))
    rg_2 = galsim.RealGalaxy(rgc, random=True)

    assert_raises(TypeError, galsim.RealGalaxy, rgc, index=ind_fake, rng='foo')
    assert_raises(TypeError, galsim.RealGalaxy, rgc)
    assert_raises(TypeError,
                  galsim.RealGalaxy,
                  rgc,
                  index=ind_fake,
                  flux=12,
                  flux_rescale=2)

    assert_raises(ValueError, galsim.RealGalaxy, rgc, index=ind_fake, id=0)
    assert_raises(ValueError,
                  galsim.RealGalaxy,
                  rgc,
                  index=ind_fake,
                  random=True)
    assert_raises(ValueError, galsim.RealGalaxy, rgc, id=0, random=True)

    # Different RNGs give different random galaxies.
    rg_3 = galsim.RealGalaxy(rgc, random=True, rng=galsim.BaseDeviate(12345))
    rg_4 = galsim.RealGalaxy(rgc, random=True, rng=galsim.BaseDeviate(67890))
    assert rg_3.index != rg_4.index, 'Different seeds did not give different random objects!'

    gsp = galsim.GSParams(xvalue_accuracy=1.e-8, kvalue_accuracy=1.e-8)
    rg_5 = galsim.RealGalaxy(rgc,
                             random=True,
                             rng=galsim.BaseDeviate(67890),
                             gsparams=gsp)
    assert rg_5 != rg_4
    assert rg_5 == rg_4.withGSParams(gsp)

    check_basic(rg, "RealGalaxy", approx_maxsb=True)
    check_basic(rg_1, "RealGalaxy", approx_maxsb=True)
    check_basic(rg_2, "RealGalaxy", approx_maxsb=True)

    do_pickle(
        rgc, lambda x: [
            x.getGalImage(ind_fake),
            x.getPSFImage(ind_fake),
            x.getNoiseProperties(ind_fake)
        ])
    do_pickle(
        rgc,
        lambda x: drawNoise(x.getNoise(ind_fake, rng=galsim.BaseDeviate(123))))
    do_pickle(rgc)
    do_pickle(
        rg, lambda x: [
            x.gal_image, x.psf_image,
            repr(x.noise), x.original_psf.flux, x.original_gal.flux, x.flux
        ])
    do_pickle(rg, lambda x: x.drawImage(nx=20, ny=20, scale=0.7))
    do_pickle(rg_1, lambda x: x.drawImage(nx=20, ny=20, scale=0.7))
    do_pickle(rg)
    do_pickle(rg_1)

    ## for the generation of the ideal right answer, we need to add the intrinsic shape of the
    ## galaxy and the lensing shear using the rule for addition of distortions which is ugly, but oh
    ## well:
    targ_pixel_scale = [0.18, 0.25]  # arcsec
    targ_PSF_fwhm = [0.7, 1.0]  # arcsec
    targ_PSF_shear1 = [-0.03, 0.0]
    targ_PSF_shear2 = [0.05, -0.08]
    targ_applied_shear1 = 0.06
    targ_applied_shear2 = -0.04

    fwhm_to_sigma = 1.0 / (2.0 * np.sqrt(2.0 * np.log(2.0)))

    (d1, d2) = galsim.utilities.g1g2_to_e1e2(fake_gal_shear1, fake_gal_shear2)
    (d1app, d2app) = galsim.utilities.g1g2_to_e1e2(targ_applied_shear1,
                                                   targ_applied_shear2)
    denom = 1.0 + d1 * d1app + d2 * d2app
    dapp_sq = d1app**2 + d2app**2
    d1tot = (d1 + d1app + d2app / dapp_sq * (1.0 - np.sqrt(1.0 - dapp_sq)) *
             (d2 * d1app - d1 * d2app)) / denom
    d2tot = (d2 + d2app + d1app / dapp_sq * (1.0 - np.sqrt(1.0 - dapp_sq)) *
             (d1 * d2app - d2 * d1app)) / denom

    # convolve with a range of Gaussians, with and without shear (note, for this test all the
    # original and target ePSFs are Gaussian - there's no separate pixel response so that everything
    # can be calculated analytically)
    for tps in targ_pixel_scale:
        for tpf in targ_PSF_fwhm:
            for tps1 in targ_PSF_shear1:
                for tps2 in targ_PSF_shear2:
                    print('tps,tpf,tps1,tps2 = ', tps, tpf, tps1, tps2)
                    # make target PSF
                    targ_PSF = galsim.Gaussian(fwhm=tpf).shear(g1=tps1,
                                                               g2=tps2)
                    # simulate image
                    tmp_gal = rg.withFlux(fake_gal_flux).shear(
                        g1=targ_applied_shear1, g2=targ_applied_shear2)
                    final_tmp_gal = galsim.Convolve(targ_PSF, tmp_gal)
                    sim_image = final_tmp_gal.drawImage(scale=tps,
                                                        method='no_pixel')
                    # galaxy sigma, in units of pixels on the final image
                    sigma_ideal = (fake_gal_fwhm / tps) * fwhm_to_sigma
                    # compute analytically the expected galaxy moments:
                    mxx_gal, myy_gal, mxy_gal = ellip_to_moments(
                        d1tot, d2tot, sigma_ideal)
                    # compute analytically the expected PSF moments:
                    targ_PSF_e1, targ_PSF_e2 = galsim.utilities.g1g2_to_e1e2(
                        tps1, tps2)
                    targ_PSF_sigma = (tpf / tps) * fwhm_to_sigma
                    mxx_PSF, myy_PSF, mxy_PSF = ellip_to_moments(
                        targ_PSF_e1, targ_PSF_e2, targ_PSF_sigma)
                    # get expected e1, e2, sigma for the PSF-convolved image
                    tot_e1, tot_e2, tot_sigma = moments_to_ellip(
                        mxx_gal + mxx_PSF, myy_gal + myy_PSF,
                        mxy_gal + mxy_PSF)

                    # compare with images that are expected
                    expected_gaussian = galsim.Gaussian(flux=fake_gal_flux,
                                                        sigma=tps * tot_sigma)
                    expected_gaussian = expected_gaussian.shear(e1=tot_e1,
                                                                e2=tot_e2)
                    expected_image = galsim.ImageD(sim_image.array.shape[0],
                                                   sim_image.array.shape[1])
                    expected_gaussian.drawImage(expected_image,
                                                scale=tps,
                                                method='no_pixel')
                    printval(expected_image, sim_image)
                    np.testing.assert_array_almost_equal(
                        sim_image.array,
                        expected_image.array,
                        decimal=3,
                        err_msg=
                        "Error in comparison of ideal Gaussian RealGalaxy calculations"
                    )
Beispiel #23
0
def main(argv):
    """
    Make images using variable PSF and shear:
      - The main image is 10 x 10 postage stamps.
      - Each postage stamp is 48 x 48 pixels.
      - The second HDU has the corresponding PSF image.
      - Applied shear is from a power spectrum P(k) ~ k^1.8.
      - Galaxies are real galaxies oriented in a ring test of 20 each.
      - The PSF is Gaussian with FWHM, ellipticity and position angle functions of (x,y)
      - Noise is Poisson using a nominal sky value of 1.e6.
    """
    logging.basicConfig(format="%(message)s",
                        level=logging.INFO,
                        stream=sys.stdout)
    logger = logging.getLogger("demo10")

    # Define some parameters we'll use below.
    # Normally these would be read in from some parameter file.

    n_tiles = 10  # number of tiles in each direction.
    stamp_size = 48  # pixels

    pixel_scale = 0.44  # arcsec / pixel
    sky_level = 1.e6  # ADU / arcsec^2

    # The random seed is used for both the power spectrum realization and the random properties
    # of the galaxies.
    random_seed = 3339201

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

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

    # These will be created for each object below.  The values we'll use will be functions
    # of (x,y) relative to the center of the image.  (r = sqrt(x^2+y^2))
    # psf_fwhm = 0.9 + 0.5 * (r/100)^2  -- arcsec
    # psf_e = 0.4 * (r/100)^1.5         -- large value at the edge, so visible by eye.
    # psf_beta = atan2(y/x) + pi/2      -- tangential pattern

    gal_dilation = 3  # Make the galaxies a bit larger than their original size.
    gal_signal_to_noise = 100  # Pretty high.
    psf_signal_to_noise = 1000  # Even higher.

    logger.info('Starting demo script 10')

    # Read in galaxy catalog
    cat_file_name = 'real_galaxy_catalog_23.5_example.fits'
    dir = 'data'
    real_galaxy_catalog = galsim.RealGalaxyCatalog(cat_file_name, dir=dir)
    logger.info('Read in %d real galaxies from catalog',
                real_galaxy_catalog.nobjects)

    # List of IDs to use.  We select 5 particularly irregular galaxies for this demo.
    # Then we'll choose randomly from this list.
    id_list = [106416, 106731, 108402, 116045, 116448]

    # Make the 5 galaxies we're going to use here rather than remake them each time.
    # This means the Fourier transforms of the real galaxy images don't need to be recalculated
    # each time, so it's a bit more efficient.
    gal_list = [
        galsim.RealGalaxy(real_galaxy_catalog, id=id) for id in id_list
    ]
    # Grab the index numbers before we transform them and lose the index attribute.
    cosmos_index = [gal.index for gal in gal_list]

    # Make the galaxies a bit larger than their original observed size.
    gal_list = [gal.dilate(gal_dilation) for gal in gal_list]

    # Setup the PowerSpectrum object we'll be using:
    ps = galsim.PowerSpectrum(lambda k: k**1.8)
    # The argument here is "e_power_function" which defines the E-mode power to use.

    # There is also a b_power_function if you want to include any B-mode power:
    #     ps = galsim.PowerSpectrum(e_power_function, b_power_function)

    # You may even omit the e_power_function argument and have a pure B-mode power spectrum.
    #     ps = galsim.PowerSpectrum(b_power_function = b_power_function)

    # All the random number generator classes derive from BaseDeviate.
    # When we construct another kind of deviate class from any other
    # kind of deviate class, the two share the same underlying random number
    # generator.  Sometimes it can be clearer to just construct a BaseDeviate
    # explicitly and then construct anything else you need from that.
    # Note: A BaseDeviate cannot be used to generate any values.  It can
    # only be used in the constructor for other kinds of deviates.
    # The seeds for the objects are random_seed+1..random_seed+nobj.
    # The seeds for things at the image or file level use random_seed itself.
    nobj = n_tiles * n_tiles
    rng = galsim.BaseDeviate(random_seed)

    # Have the PowerSpectrum object build a grid of shear values for us to use.
    grid_g1, grid_g2 = ps.buildGrid(grid_spacing=stamp_size * pixel_scale,
                                    ngrid=n_tiles,
                                    rng=rng)

    # Setup the images:
    gal_image = galsim.ImageF(stamp_size * n_tiles, stamp_size * n_tiles)
    psf_image = galsim.ImageF(stamp_size * n_tiles, stamp_size * n_tiles)

    # Update the image WCS to use the image center as the origin of the WCS.
    # The class that acts like a PixelScale except for this offset is called OffsetWCS.
    im_center = gal_image.true_center
    wcs = galsim.OffsetWCS(scale=pixel_scale, origin=im_center)
    gal_image.wcs = wcs
    psf_image.wcs = wcs

    # We will place the tiles in a random order.  To do this, we make two lists for the
    # ix and iy values.  Then we apply a random permutation to the lists (in tandem).
    ix_list = []
    iy_list = []
    for ix in range(n_tiles):
        for iy in range(n_tiles):
            ix_list.append(ix)
            iy_list.append(iy)
    # This next function will use the given random number generator, rng, and use it to
    # randomly permute any number of lists.  All lists will have the same random permutation
    # applied.
    galsim.random.permute(rng, ix_list, iy_list)

    # Initialize the OutputCatalog for the truth values
    names = [
        'gal_num', 'x_image', 'y_image', 'psf_e1', 'psf_e2', 'psf_fwhm',
        'cosmos_id', 'cosmos_index', 'theta', 'g1', 'g2', 'shift_x', 'shift_y'
    ]
    types = [
        int, float, float, float, float, float, str, int, float, float, float,
        float, float
    ]
    truth_catalog = galsim.OutputCatalog(names, types)

    # Build each postage stamp:
    for k in range(nobj):
        # The usual random number generator using a different seed for each galaxy.
        rng = galsim.BaseDeviate(random_seed + k + 1)

        # Determine the bounds for this stamp and its center position.
        ix = ix_list[k]
        iy = iy_list[k]
        b = galsim.BoundsI(ix * stamp_size + 1, (ix + 1) * stamp_size,
                           iy * stamp_size + 1, (iy + 1) * stamp_size)
        sub_gal_image = gal_image[b]
        sub_psf_image = psf_image[b]

        pos = wcs.toWorld(b.true_center)
        # The image comes out as about 211 arcsec across, so we define our variable
        # parameters in terms of (r/100 arcsec), so roughly the scale size of the image.
        rsq = (pos.x**2 + pos.y**2)
        r = math.sqrt(rsq)

        psf_fwhm = 0.9 + 0.5 * rsq / 100**2  # arcsec
        psf_e = 0.4 * (r / 100.)**1.5
        psf_beta = (math.atan2(pos.y, pos.x) + math.pi / 2) * galsim.radians

        # Define the PSF profile
        psf = galsim.Gaussian(fwhm=psf_fwhm)
        psf_shape = galsim.Shear(e=psf_e, beta=psf_beta)
        psf = psf.shear(psf_shape)

        # Define the galaxy profile:

        # For this demo, we are doing a ring test where the same galaxy profile is drawn at many
        # orientations stepped uniformly in angle, making a ring in e1-e2 space.
        # We're drawing each profile at 20 different orientations and then skipping to the
        # next galaxy in the list.  So theta steps by 1/20 * 360 degrees:
        theta_deg = (k % 20) * 360. / 20
        theta = theta_deg * galsim.degrees

        # The index needs to increment every 20 objects so we use k/20 using integer math.
        index = k // 20
        gal = gal_list[index]

        # This makes a new copy so we're not changing the object in the gal_list.
        gal = gal.rotate(theta)

        # Apply the shear from the power spectrum.  We should either turn the gridded shears
        # grid_g1[iy, ix] and grid_g2[iy, ix] into gridded reduced shears using a utility called
        # galsim.lensing.theoryToObserved, or use ps.getShear() which by default gets the reduced
        # shear.  ps.getShear() is also more flexible because it can get the shear at positions that
        # are not on the original grid, as long as they are contained within the bounds of the full
        # grid. So in this example we'll use ps.getShear().
        alt_g1, alt_g2 = ps.getShear(pos)
        gal = gal.shear(g1=alt_g1, g2=alt_g2)

        # Apply half-pixel shift in a random direction.
        shift_r = pixel_scale * 0.5
        ud = galsim.UniformDeviate(rng)
        t = ud() * 2. * math.pi
        dx = shift_r * math.cos(t)
        dy = shift_r * math.sin(t)
        gal = gal.shift(dx, dy)

        # Make the final image, convolving with the psf
        final = galsim.Convolve([psf, gal])

        # Draw the image
        final.drawImage(sub_gal_image)

        # For the PSF image, we don't match the galaxy shift.  Rather, we use the offset
        # parameter to drawImage to apply a random offset of up to 0.5 pixels in each direction.
        # Note the difference in units between shift and offset.  The shift is applied to the
        # surface brightness profile, so it is in sky coordinates (as all dimension are for
        # GSObjects), which are arcsec here.  The offset though is applied to the image itself,
        # so it is in pixels.  Hence, we don't multiply by pixel_scale.
        psf_dx = ud() - 0.5
        psf_dy = ud() - 0.5
        psf_offset = galsim.PositionD(psf_dx, psf_dy)

        # Draw the PSF image:
        # We use real space integration over the pixels to avoid some of the
        # artifacts that can show up with Fourier convolution.
        # The level of the artifacts is quite low, but when drawing with
        # so little noise, they are apparent with ds9's zscale viewing.
        psf.drawImage(sub_psf_image, method='real_space', offset=psf_offset)

        # Build the noise model: Poisson noise with a given sky level.
        sky_level_pixel = sky_level * pixel_scale**2
        noise = galsim.PoissonNoise(rng, sky_level=sky_level_pixel)

        # Add noise to the PSF image, using the normal noise model, but scaling the
        # PSF flux high enough to reach the desired signal-to-noise.
        # See demo5.py for more info about how this works.
        sub_psf_image.addNoiseSNR(noise, psf_signal_to_noise)

        # And also to the galaxy image using its signal-to-noise.
        sub_gal_image.addNoiseSNR(noise, gal_signal_to_noise)

        # Add the truth values to the truth catalog
        row = [
            k, b.true_center.x, b.true_center.y, psf_shape.e1,
            psf_shape.e2, psf_fwhm, id_list[index], cosmos_index[index],
            (theta_deg % 360.), alt_g1, alt_g2, dx, dy
        ]
        truth_catalog.addRow(row)

        logger.info('Galaxy (%d,%d): position relative to center = %s', ix, iy,
                    str(pos))

    logger.info('Done making images of postage stamps')

    # In this case, we'll attach the truth catalog as an additional HDU in the same file as
    # the image data.
    truth_hdu = truth_catalog.writeFitsHdu()

    # Now write the images to disk.
    images = [gal_image, psf_image, truth_hdu]
    # Any items in the "images" list that is already an hdu is just used directly.
    # The actual images are converted to FITS hdus that contain the image data.
    galsim.fits.writeMulti(images, file_name)
    logger.info('Wrote image to %r', file_name)
Beispiel #24
0
def test_real_galaxy_ideal():
    """Test accuracy of various calculations with fake Gaussian RealGalaxy vs. ideal expectations"""
    import time
    t1 = time.time()
    # read in faked Gaussian RealGalaxy from file
    rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
    rg = galsim.RealGalaxy(rgc, index=ind_fake)
    # as a side note, make sure it behaves okay given a legit RNG and a bad RNG
    # or when trying to specify the galaxy too many ways
    rg_1 = galsim.RealGalaxy(rgc, index = ind_fake, rng = galsim.BaseDeviate(1234))
    rg_2 = galsim.RealGalaxy(rgc, random=True)
    try:
        np.testing.assert_raises(TypeError, galsim.RealGalaxy, rgc, index=ind_fake, rng='foo')
        np.testing.assert_raises(AttributeError, galsim.RealGalaxy, rgc, index=ind_fake, id=0)
        np.testing.assert_raises(AttributeError, galsim.RealGalaxy, rgc, index=ind_fake, random=True)
        np.testing.assert_raises(AttributeError, galsim.RealGalaxy, rgc, id=0, random=True)
        np.testing.assert_raises(AttributeError, galsim.RealGalaxy, rgc)
    except ImportError:
        print 'The assert_raises tests require nose'

    do_pickle(rgc, lambda x: [ x.getGal(ind_fake), x.getPSF(ind_fake),
                               x.getNoiseProperties(ind_fake) ])
    do_pickle(rgc, lambda x: drawNoise(x.getNoise(ind_fake,rng=galsim.BaseDeviate(123))))
    do_pickle(rgc)
    do_pickle(rg, lambda x: [ x.gal_image, x.psf_image, repr(x.noise),
                              x.original_psf.flux, x.original_gal.flux, x.flux ])
    do_pickle(rg, lambda x: x.drawImage(nx=20, ny=20, scale=0.7))
    do_pickle(rg_1, lambda x: x.drawImage(nx=20, ny=20, scale=0.7))
    do_pickle(rg)
    do_pickle(rg_1)

    ## for the generation of the ideal right answer, we need to add the intrinsic shape of the
    ## galaxy and the lensing shear using the rule for addition of distortions which is ugly, but oh
    ## well:
    (d1, d2) = galsim.utilities.g1g2_to_e1e2(fake_gal_shear1, fake_gal_shear2)
    (d1app, d2app) = galsim.utilities.g1g2_to_e1e2(targ_applied_shear1, targ_applied_shear2)
    denom = 1.0 + d1*d1app + d2*d2app
    dapp_sq = d1app**2 + d2app**2
    d1tot = (d1 + d1app + d2app/dapp_sq*(1.0 - np.sqrt(1.0-dapp_sq))*(d2*d1app - d1*d2app))/denom
    d2tot = (d2 + d2app + d1app/dapp_sq*(1.0 - np.sqrt(1.0-dapp_sq))*(d1*d2app - d2*d1app))/denom

    # convolve with a range of Gaussians, with and without shear (note, for this test all the
    # original and target ePSFs are Gaussian - there's no separate pixel response so that everything
    # can be calculated analytically)
    for tps in targ_pixel_scale:
        for tpf in targ_PSF_fwhm:
            for tps1 in targ_PSF_shear1:
                for tps2 in targ_PSF_shear2:
                    print 'tps,tpf,tps1,tps2 = ',tps,tpf,tps1,tps2
                    # make target PSF
                    targ_PSF = galsim.Gaussian(fwhm = tpf).shear(g1=tps1, g2=tps2)
                    # simulate image
                    sim_image = galsim.simReal(
                            rg, targ_PSF, tps,
                            g1 = targ_applied_shear1, g2 = targ_applied_shear2,
                            rand_rotate = False, target_flux = fake_gal_flux)
                    # galaxy sigma, in units of pixels on the final image
                    sigma_ideal = (fake_gal_fwhm/tps)*fwhm_to_sigma
                    # compute analytically the expected galaxy moments:
                    mxx_gal, myy_gal, mxy_gal = ellip_to_moments(d1tot, d2tot, sigma_ideal)
                    # compute analytically the expected PSF moments:
                    targ_PSF_e1, targ_PSF_e2 = galsim.utilities.g1g2_to_e1e2(tps1, tps2)
                    targ_PSF_sigma = (tpf/tps)*fwhm_to_sigma
                    mxx_PSF, myy_PSF, mxy_PSF = ellip_to_moments(
                            targ_PSF_e1, targ_PSF_e2, targ_PSF_sigma)
                    # get expected e1, e2, sigma for the PSF-convolved image
                    tot_e1, tot_e2, tot_sigma = moments_to_ellip(
                            mxx_gal+mxx_PSF, myy_gal+myy_PSF, mxy_gal+mxy_PSF)

                    # compare with images that are expected
                    expected_gaussian = galsim.Gaussian(
                            flux = fake_gal_flux, sigma = tps*tot_sigma)
                    expected_gaussian = expected_gaussian.shear(e1 = tot_e1, e2 = tot_e2)
                    expected_image = galsim.ImageD(
                            sim_image.array.shape[0], sim_image.array.shape[1])
                    expected_gaussian.drawImage(expected_image, scale=tps, method='no_pixel')
                    printval(expected_image,sim_image)
                    np.testing.assert_array_almost_equal(
                        sim_image.array, expected_image.array, decimal = 3,
                        err_msg = "Error in comparison of ideal Gaussian RealGalaxy calculations")

    t2 = time.time()
    print 'time for %s = %.2f'%(funcname(),t2-t1)
Beispiel #25
0
def test_cosmos_random():
    """Check the random object functionality of the COSMOS catalog."""
    # For most of this test, we'll use the selectRandomIndex() routine, which does not try to
    # construct the GSObjects.  This makes the test go fast.  However, we will at the end have a
    # test to ensure that calling makeGalaxy() while requesting a random object has the same
    # behavior as using selectRandomIndex() in limited cases.

    # Initialize the catalog.  The first will have weights, while the second will not (since they
    # are in the RealGalaxyCatalog).
    cat = galsim.COSMOSCatalog(
        file_name='real_galaxy_catalog_23.5_example.fits', dir=datapath)
    cat_param = galsim.COSMOSCatalog(
        file_name='real_galaxy_catalog_23.5_example.fits',
        dir=datapath,
        use_real=False)
    assert cat_param.real_cat is None
    assert cat.real_cat is not None

    # Check for exception handling if bad inputs given for the random functionality.
    assert_raises(ValueError, cat.selectRandomIndex, 0)
    assert_raises(ValueError, cat.selectRandomIndex, 10.7)
    assert_raises(TypeError, cat.selectRandomIndex, 10, rng=3)

    # Check that random objects give the right <weight> without/with weighting.
    wt = cat.real_cat.weight[cat.orig_index]
    wt /= np.max(wt)
    avg_weight_val = np.sum(wt) / len(wt)
    wavg_weight_val = np.sum(wt**2) / np.sum(wt)
    with assert_raises(AssertionError):
        np.testing.assert_almost_equal(avg_weight_val, wavg_weight_val, 3)
    # Make sure we use enough objects that the mean weights converge properly.
    randind_wt = cat.selectRandomIndex(30000, rng=galsim.BaseDeviate(1234))
    wtrand = cat.real_cat.weight[cat.orig_index[randind_wt]] / \
        np.max(cat.real_cat.weight[cat.orig_index])
    # The average value of wtrand should be wavgw_weight_val in this case, since we used the weights
    # to probabilistically select galaxies.
    np.testing.assert_almost_equal(
        np.mean(wtrand),
        wavg_weight_val,
        3,
        err_msg='Average weight for random sample is wrong')

    # The example catalog doesn't have weights, so it does unweighted selection, which emits a
    # warning.  We know about this and want to ignore it here.
    with assert_warns(galsim.GalSimWarning):
        randind = cat_param.selectRandomIndex(30000,
                                              rng=galsim.BaseDeviate(1234))
    wtrand = cat.real_cat.weight[cat.orig_index[randind]] / \
        np.max(cat.real_cat.weight[cat.orig_index])
    # The average value of wtrand should be avg_weight_val, since we did not do a weighted
    # selection.
    np.testing.assert_almost_equal(
        np.mean(wtrand),
        avg_weight_val,
        3,
        err_msg='Average weight for random sample is wrong')

    # Check for consistency of randoms with same random seed.  Do this both for the weighted and the
    # unweighted calculation.
    # Check for inconsistency of randoms with different random seed, or same seed but without/with
    # weighting.
    rng1 = galsim.BaseDeviate(1234)
    rng2 = galsim.BaseDeviate(1234)
    ind1 = cat.selectRandomIndex(10, rng=rng1)
    ind2 = cat.selectRandomIndex(10, rng=rng2)
    np.testing.assert_array_equal(
        ind1,
        ind2,
        err_msg='Different random indices selected with same seed!')
    with assert_warns(galsim.GalSimWarning):
        ind1p = cat_param.selectRandomIndex(10, rng=rng1)
    with assert_warns(galsim.GalSimWarning):
        ind2p = cat_param.selectRandomIndex(10, rng=rng2)
    np.testing.assert_array_equal(
        ind1p,
        ind2p,
        err_msg='Different random indices selected with same seed!')
    rng3 = galsim.BaseDeviate(5678)
    ind3 = cat.selectRandomIndex(10, rng=rng3)
    with assert_warns(galsim.GalSimWarning):
        ind3p = cat_param.selectRandomIndex(10)  # initialize RNG based on time
    assert_raises(AssertionError, np.testing.assert_array_equal, ind1, ind1p)
    assert_raises(AssertionError, np.testing.assert_array_equal, ind1, ind3)
    assert_raises(AssertionError, np.testing.assert_array_equal, ind1p, ind3p)

    # Finally, make sure that directly calling selectRandomIndex() gives the same random ones as
    # makeGalaxy().  We'll do one real object because they are slower, and multiple parametric (just
    # to make sure that the multi-object selection works consistently).
    use_seed = 567
    obj = cat.makeGalaxy(rng=galsim.BaseDeviate(use_seed))
    ind = cat.selectRandomIndex(1, rng=galsim.BaseDeviate(use_seed))
    obj_2 = cat.makeGalaxy(ind)
    # Note: for real galaxies we cannot require that obj==obj_2, just that obj.index==obj_2.index.
    # That's because we want to make sure the same galaxy is being randomly selected, but we cannot
    # require that noise padding be the same, given the inconsistency in how the BaseDeviates are
    # used in the above cases.
    assert obj.index == obj_2.index, 'makeGalaxy selects random objects inconsistently'

    n_random = 3
    with assert_warns(galsim.GalSimWarning):
        # Warns because we aren't using weights
        objs = cat_param.makeGalaxy(rng=galsim.BaseDeviate(use_seed),
                                    n_random=n_random)
    with assert_warns(galsim.GalSimWarning):
        inds = cat_param.selectRandomIndex(n_random,
                                           rng=galsim.BaseDeviate(use_seed))
    objs_2 = cat_param.makeGalaxy(inds)
    for i in range(n_random):
        # With parametric objects there is no noise padding, so we can require completely identical
        # GSObjects (not just equal indices).
        assert objs[i] == objs_2[
            i], 'makeGalaxy selects random objects inconsistently'

    # Finally, check for consistency with random object selected from RealGalaxyCatalog.  For this
    # case, we need to make another COSMOSCatalog that does not flag the bad objects.
    use_seed = 31415
    cat = galsim.COSMOSCatalog(
        file_name='real_galaxy_catalog_23.5_example.fits',
        dir=datapath,
        exclusion_level='none')
    rgc = galsim.RealGalaxyCatalog(
        file_name='real_galaxy_catalog_23.5_example.fits', dir=datapath)
    ind_cc = cat.selectRandomIndex(1, rng=galsim.BaseDeviate(use_seed))
    foo = galsim.RealGalaxy(rgc, random=True, rng=galsim.BaseDeviate(use_seed))
    ind_rgc = foo.index
    assert ind_cc==ind_rgc,\
        'Different weighted random index selected from COSMOSCatalog and RealGalaxyCatalog'

    # Also check for the unweighted case.  Just remove that info from the catalogs and redo the
    # test.
    cat.real_cat = None
    del rgc.weight
    with assert_warns(galsim.GalSimWarning):
        ind_cc = cat.selectRandomIndex(1, rng=galsim.BaseDeviate(use_seed))
    foo = galsim.RealGalaxy(rgc, random=True, rng=galsim.BaseDeviate(use_seed))
    ind_rgc = foo.index
    assert ind_cc==ind_rgc,\
        'Different unweighted random index selected from COSMOSCatalog and RealGalaxyCatalog'

    # Check that setting _n_rng_calls properly tracks the RNG calls for n_random=1 and >1.
    test_seed = 123456
    ud = galsim.UniformDeviate(test_seed)
    with assert_warns(galsim.GalSimWarning):
        obj, n_rng_calls = cat.selectRandomIndex(1, rng=ud, _n_rng_calls=True)
    ud2 = galsim.UniformDeviate(test_seed)
    ud2.discard(n_rng_calls)
    assert ud() == ud2(
    ), '_n_rng_calls kwarg did not give proper tracking of RNG calls'
    ud = galsim.UniformDeviate(test_seed)
    with assert_warns(galsim.GalSimWarning):
        obj, n_rng_calls = cat.selectRandomIndex(17, rng=ud, _n_rng_calls=True)
    ud2 = galsim.UniformDeviate(test_seed)
    ud2.discard(n_rng_calls)
    assert ud() == ud2(
    ), '_n_rng_calls kwarg did not give proper tracking of RNG calls'

    # Invalid to both privide index and ask for random selection
    with assert_raises(galsim.GalSimIncompatibleValuesError):
        cat_param.makeGalaxy(index=(11, 13, 17), n_random=3)
Beispiel #26
0
def test_flip():
    """Test several ways to flip a profile
    """
    # The Shapelet profile has the advantage of being fast and not circularly symmetric, so
    # it is a good test of the actual code for doing the flips (in SBTransform).
    # But since the bug Rachel reported in #645 was actually in SBInterpolatedImage
    # (one calculation implicitly assumed dx > 0), it seems worthwhile to run through all the
    # classes to make sure we hit everything with negative steps for dx and dy.
    prof_list = [
        galsim.Shapelet(sigma=0.17, order=2,
                        bvec=[1.7, 0.01,0.03, 0.29, 0.33, -0.18]),
    ]
    if __name__ == "__main__":
        image_dir = './real_comparison_images'
        catalog_file = 'test_catalog.fits'
        rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
        # Some of these are slow, so only do the Shapelet test as part of the normal unit tests.
        prof_list += [
            galsim.Airy(lam_over_diam=0.17, flux=1.7),
            galsim.Airy(lam_over_diam=0.17, obscuration=0.2, flux=1.7),
            # Box gets rendered with real-space convolution.  The default accuracy isn't quite
            # enough to get the flip to match at 6 decimal places.
            galsim.Box(0.17, 0.23, flux=1.7,
                       gsparams=galsim.GSParams(realspace_relerr=1.e-6)),
            # Without being convolved by anything with a reasonable k cutoff, this needs
            # a very large fft.
            galsim.DeVaucouleurs(half_light_radius=0.17, flux=1.7),
            # I don't really understand why this needs a lower maxk_threshold to work, but
            # without it, the k-space tests fail.
            galsim.Exponential(scale_radius=0.17, flux=1.7,
                               gsparams=galsim.GSParams(maxk_threshold=1.e-4)),
            galsim.Gaussian(sigma=0.17, flux=1.7),
            galsim.Kolmogorov(fwhm=0.17, flux=1.7),
            galsim.Moffat(beta=2.5, fwhm=0.17, flux=1.7),
            galsim.Moffat(beta=2.5, fwhm=0.17, flux=1.7, trunc=0.82),
            galsim.OpticalPSF(lam_over_diam=0.17, obscuration=0.2, nstruts=6,
                              coma1=0.2, coma2=0.5, defocus=-0.1, flux=1.7),
            # Like with Box, we need to increase the real-space convolution accuracy.
            # This time lowering both relerr and abserr.
            galsim.Pixel(0.23, flux=1.7,
                         gsparams=galsim.GSParams(realspace_relerr=1.e-6,
                                                  realspace_abserr=1.e-8)),
            # Note: RealGalaxy should not be rendered directly because of the deconvolution.
            # Here we convolve it by a Gaussian that is slightly larger than the original PSF.
            galsim.Convolve([ galsim.RealGalaxy(rgc, index=0, flux=1.7),  # "Real" RealGalaxy
                              galsim.Gaussian(sigma=0.08) ]),
            galsim.Convolve([ galsim.RealGalaxy(rgc, index=1, flux=1.7),  # "Fake" RealGalaxy
                              galsim.Gaussian(sigma=0.08) ]),             # (cf. test_real.py)
            galsim.Spergel(nu=-0.19, half_light_radius=0.17, flux=1.7),
            galsim.Spergel(nu=0., half_light_radius=0.17, flux=1.7),
            galsim.Spergel(nu=0.8, half_light_radius=0.17, flux=1.7),
            galsim.Sersic(n=2.3, half_light_radius=0.17, flux=1.7),
            galsim.Sersic(n=2.3, half_light_radius=0.17, flux=1.7, trunc=0.82),
            # The shifts here caught a bug in how SBTransform handled the recentering.
            # Two of the shifts (0.125 and 0.375) lead back to 0.0 happening on an integer
            # index, which now works correctly.
            galsim.Sum([ galsim.Gaussian(sigma=0.17, flux=1.7).shift(-0.2,0.125),
                         galsim.Exponential(scale_radius=0.23, flux=3.1).shift(0.375,0.23)]),
            galsim.TopHat(0.23, flux=1.7),
            # Box and Pixel use real-space convolution.  Convolve with a Gaussian to get fft.
            galsim.Convolve([ galsim.Box(0.17, 0.23, flux=1.7).shift(-0.2,0.1),
                              galsim.Gaussian(sigma=0.09) ]),
            galsim.Convolve([ galsim.TopHat(0.17, flux=1.7).shift(-0.275,0.125),
                              galsim.Gaussian(sigma=0.09) ]),
            # Test something really crazy with several layers worth of transformations
            galsim.Convolve([
                galsim.Sum([
                    galsim.Gaussian(sigma=0.17, flux=1.7).shear(g1=0.1,g2=0.2).shift(2,3),
                    galsim.Kolmogorov(fwhm=0.33, flux=3.9).transform(0.31,0.19,-0.23,0.33) * 88.,
                    galsim.Box(0.11, 0.44, flux=4).rotate(33 * galsim.degrees) / 1.9
                ]).shift(-0.3,1),
                galsim.AutoConvolve(galsim.TopHat(0.5).shear(g1=0.3,g2=0)).rotate(3*galsim.degrees),
                (galsim.AutoCorrelate(galsim.Box(0.2, 0.3)) * 11).shift(3,2).shift(2,-3) * 0.31
            ]).shift(0,0).transform(0,-1,-1,0).shift(-1,1)
        ]

    s = galsim.Shear(g1=0.11, g2=-0.21)
    s1 = galsim.Shear(g1=0.11, g2=0.21)  # Appropriate for the flips around x and y axes
    s2 = galsim.Shear(g1=-0.11, g2=-0.21)  # Appropriate for the flip around x=y

    # Also use shears with just a g1 to get dx != dy, but dxy, dyx = 0.
    q = galsim.Shear(g1=0.11, g2=0.)
    q1 = galsim.Shear(g1=0.11, g2=0.)  # Appropriate for the flips around x and y axes
    q2 = galsim.Shear(g1=-0.11, g2=0.)  # Appropriate for the flip around x=y

    decimal=6  # Oddly, these aren't as precise as I would have expected.
               # Even when we only go to this many digits of accuracy, the Exponential needed
               # a lower than default value for maxk_threshold.
    im = galsim.ImageD(16,16, scale=0.05)

    for prof in prof_list:
        print('prof = ',prof)

        # Not all profiles are expected to have a max_sb value close to the maximum pixel value,
        # so mark the ones where we don't want to require this to be true.
        close_maxsb = True
        name = str(prof)
        if ('DeVauc' in name or 'Sersic' in name or 'Spergel' in name or
            'Optical' in name or 'shift' in name):
            close_maxsb = False

        # Make sure we hit all 4 fill functions.
        # image_x uses fillXValue with izero, jzero
        # image_x1 uses fillXValue with izero, jzero, and unequal dx,dy
        # image_x2 uses fillXValue with dxy, dyx
        # image_k uses fillKValue with izero, jzero
        # image_k1 uses fillKValue with izero, jzero, and unequal dx,dy
        # image_k2 uses fillKValue with dxy, dyx
        image_x = prof.drawImage(image=im.copy(), method='no_pixel')
        image_x1 = prof.shear(q).drawImage(image=im.copy(), method='no_pixel')
        image_x2 = prof.shear(s).drawImage(image=im.copy(), method='no_pixel')
        image_k = prof.drawImage(image=im.copy())
        image_k1 = prof.shear(q).drawImage(image=im.copy())
        image_k2 = prof.shear(s).drawImage(image=im.copy())

        if close_maxsb:
            np.testing.assert_allclose(
                    image_x.array.max(), prof.max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image_x1.array.max(), prof.shear(q).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image_x2.array.max(), prof.shear(s).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")

        # Flip around y axis (i.e. x -> -x)
        flip1 = prof.transform(-1, 0, 0, 1)
        image2_x = flip1.drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x.array, image2_x.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed x test")
        image2_x1 = flip1.shear(q1).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x1.array, image2_x1.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed x1 test")
        image2_x2 = flip1.shear(s1).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x2.array, image2_x2.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed x2 test")
        image2_k = flip1.drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k.array, image2_k.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed k test")
        image2_k1 = flip1.shear(q1).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k1.array, image2_k1.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed k1 test")
        image2_k2 = flip1.shear(s1).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k2.array, image2_k2.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed k2 test")

        if close_maxsb:
            np.testing.assert_allclose(
                    image2_x.array.max(), flip1.max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x1.array.max(), flip1.shear(q).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x2.array.max(), flip1.shear(s).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")

        # Flip around x axis (i.e. y -> -y)
        flip2 = prof.transform(1, 0, 0, -1)
        image2_x = flip2.drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x.array, image2_x.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed x test")
        image2_x1 = flip2.shear(q1).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x1.array, image2_x1.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed x1 test")
        image2_x2 = flip2.shear(s1).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x2.array, image2_x2.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed x2 test")
        image2_k = flip2.drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k.array, image2_k.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed k test")
        image2_k1 = flip2.shear(q1).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k1.array, image2_k1.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed k1 test")
        image2_k2 = flip2.shear(s1).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k2.array, image2_k2.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed k2 test")

        if close_maxsb:
            np.testing.assert_allclose(
                    image2_x.array.max(), flip2.max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x1.array.max(), flip2.shear(q).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x2.array.max(), flip2.shear(s).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")

        # Flip around x=y (i.e. y -> x, x -> y)
        flip3 = prof.transform(0, 1, 1, 0)
        image2_x = flip3.drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x.array, np.transpose(image2_x.array), decimal=decimal,
            err_msg="Flipping image around x=y failed x test")
        image2_x1 = flip3.shear(q2).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x1.array, np.transpose(image2_x1.array), decimal=decimal,
            err_msg="Flipping image around x=y failed x1 test")
        image2_x2 = flip3.shear(s2).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x2.array, np.transpose(image2_x2.array), decimal=decimal,
            err_msg="Flipping image around x=y failed x2 test")
        image2_k = flip3.drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k.array, np.transpose(image2_k.array), decimal=decimal,
            err_msg="Flipping image around x=y failed k test")
        image2_k1 = flip3.shear(q2).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k1.array, np.transpose(image2_k1.array), decimal=decimal,
            err_msg="Flipping image around x=y failed k1 test")
        image2_k2 = flip3.shear(s2).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k2.array, np.transpose(image2_k2.array), decimal=decimal,
            err_msg="Flipping image around x=y failed k2 test")

        if close_maxsb:
            np.testing.assert_allclose(
                    image2_x.array.max(), flip3.max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x1.array.max(), flip3.shear(q).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x2.array.max(), flip3.shear(s).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")

        do_pickle(prof, lambda x: x.drawImage(image=im.copy(), method='no_pixel'))
        do_pickle(flip1, lambda x: x.drawImage(image=im.copy(), method='no_pixel'))
        do_pickle(flip2, lambda x: x.drawImage(image=im.copy(), method='no_pixel'))
        do_pickle(flip3, lambda x: x.drawImage(image=im.copy(), method='no_pixel'))
        do_pickle(prof)
        do_pickle(flip1)
        do_pickle(flip2)
        do_pickle(flip3)
Beispiel #27
0
def main(argv):
    """
    Make a fits image cube using real COSMOS galaxies from a catalog describing the training
    sample.

      - The number of images in the cube matches the number of rows in the catalog.
      - Each image size is computed automatically by GalSim based on the Nyquist size.
      - Both galaxies and stars.
      - PSF is a double Gaussian, the same for each galaxy.
      - Galaxies are randomly rotated to remove the imprint of any lensing shears in the COSMOS
        data.
      - The same shear is applied to each galaxy.
      - Noise is Poisson using a nominal sky value of 1.e6 ADU/arcsec^2,
        the noise in the original COSMOS data.
    """
    logging.basicConfig(format="%(message)s",
                        level=logging.INFO,
                        stream=sys.stdout)
    logger = logging.getLogger("demo6")

    # Define some parameters we'll use below.

    cat_file_name = 'real_galaxy_catalog_example.fits'
    # This script is designed to be run from the examples directory so dir is a relative path.
    # But the '../examples/' part lets bin/demo6 also be run from the bin directory.
    dir = '../examples/data'
    # Make output directory if not already present.
    if not os.path.isdir('output'):
        os.mkdir('output')
    cube_file_name = os.path.join('output', 'cube_real.fits')
    psf_file_name = os.path.join('output', 'psf_real.fits')

    random_seed = 1512413
    sky_level = 1.e6  # ADU / arcsec^2
    pixel_scale = 0.15  # arcsec
    gal_flux = 1.e5  # arbitrary choice, makes nice (not too) noisy images
    gal_g1 = -0.027  #
    gal_g2 = 0.031  #
    gal_mu = 1.082  # mu = ( (1-kappa)^2 - g1^2 - g2^2 )^-1
    psf_inner_fwhm = 0.6  # arcsec
    psf_outer_fwhm = 2.3  # arcsec
    psf_inner_fraction = 0.8  # fraction of total PSF flux in the inner Gaussian
    psf_outer_fraction = 0.2  # fraction of total PSF flux in the inner Gaussian
    ngal = 100

    logger.info('Starting demo script 6 using:')
    logger.info('    - real galaxies from catalog %r', cat_file_name)
    logger.info('    - double Gaussian PSF')
    logger.info('    - pixel scale = %.2f', pixel_scale)
    logger.info('    - Applied gravitational shear = (%.3f,%.3f)', gal_g1,
                gal_g2)
    logger.info('    - Poisson noise (sky level = %.1e).', sky_level)

    # Read in galaxy catalog
    # Note: dir is the directory both for the catalog itself and also the directory prefix
    # for the image files listed in the catalog.
    # If the images are in a different directory, you may also specify image_dir, which gives
    # the relative path from dir to wherever the images are located.
    real_galaxy_catalog = galsim.RealGalaxyCatalog(cat_file_name, dir=dir)

    # Preloading the header information usually speeds up subsequent access.
    # Basically, it tells pyfits to read all the headers in once and save them, rather
    # than re-open the galaxy catalog fits file each time you want to access a new galaxy.
    # If you are doing more than a few galaxies, then it seems to be worthwhile.
    real_galaxy_catalog.preload()
    logger.info('Read in %d real galaxies from catalog',
                real_galaxy_catalog.nobjects)

    # Make the ePSF
    # first make the double Gaussian PSF
    psf1 = galsim.Gaussian(fwhm=psf_inner_fwhm, flux=psf_inner_fraction)
    psf2 = galsim.Gaussian(fwhm=psf_outer_fwhm, flux=psf_outer_fraction)
    psf = psf1 + psf2
    # make the pixel response
    pix = galsim.Pixel(pixel_scale)
    # convolve PSF and pixel response function to get the effective PSF (ePSF)
    epsf = galsim.Convolve([psf, pix])
    # Draw this one with no noise.
    epsf_image = epsf.draw(dx=pixel_scale)
    # write to file
    epsf_image.write(psf_file_name)
    logger.info('Created ePSF and wrote to file %r', psf_file_name)

    # Build the images
    all_images = []
    for k in range(ngal):
        logger.debug('Start work on image %d', k)
        t1 = time.time()

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

        gal = galsim.RealGalaxy(real_galaxy_catalog, index=k)
        logger.debug('   Read in training sample galaxy and PSF from file')
        t2 = time.time()

        # Set the flux
        gal.setFlux(gal_flux)

        # Rotate by a random angle
        theta = 2. * math.pi * rng() * galsim.radians
        gal.applyRotation(theta)

        # Apply the desired shear
        gal.applyShear(g1=gal_g1, g2=gal_g2)

        # Also apply a magnification mu = ( (1-kappa)^2 - |gamma|^2 )^-1
        # This conserves surface brightness, so it scales both the area and flux.
        gal.applyMagnification(gal_mu)

        # Make the combined profile
        final = galsim.Convolve([psf, pix, gal])

        # Draw the profile
        if k == 0:
            im = final.draw(dx=pixel_scale)
            xsize, ysize = im.array.shape
        else:
            im = galsim.ImageF(xsize, ysize)
            final.draw(im, dx=pixel_scale)

        logger.debug('   Drew image')
        t3 = time.time()

        # Add a constant background level
        background = sky_level * pixel_scale**2
        im += background

        # Add Poisson noise.  This time, we don't give a sky_level, since we have already
        # added it to the image, so we don't want any more added.  The sky_level parameter
        # really defines how much _extra_ sky should be added above what is already in the image.
        im.addNoise(galsim.PoissonNoise(rng))

        logger.debug('   Added Poisson noise')
        t4 = time.time()

        # Store that into the list of all images
        all_images += [im]
        t5 = time.time()

        logger.debug('   Times: %f, %f, %f, %f', t2 - t1, t3 - t2, t4 - t3,
                     t5 - t4)
        logger.info('Image %d: size = %d x %d, total time = %f sec', k, xsize,
                    ysize, t5 - t1)

    logger.info('Done making images of galaxies')

    # Now write the image to disk.
    # We write the images to a fits data cube.
    galsim.fits.writeCube(all_images, cube_file_name)
    logger.info('Wrote image to fits data cube %r', cube_file_name)
Beispiel #28
0
def main(argv):
    """
    Make images using variable PSF and shear:
      - The main image is 10 x 10 postage stamps.
      - Each postage stamp is 48 x 48 pixels.
      - The second HDU has the corresponding PSF image.
      - Applied shear is from a power spectrum P(k) ~ k^1.8.
      - Galaxies are real galaxies oriented in a ring test of 20 each.
      - The PSF is Gaussian with FWHM, ellipticity and position angle functions of (x,y)
      - Noise is Poisson using a nominal sky value of 1.e6.
    """
    logging.basicConfig(format="%(message)s",
                        level=logging.INFO,
                        stream=sys.stdout)
    logger = logging.getLogger("demo10")

    # Define some parameters we'll use below.
    # Normally these would be read in from some parameter file.

    n_tiles = 10  # number of tiles in each direction.
    stamp_size = 48  # pixels

    pixel_scale = 0.44  # arcsec / pixel
    sky_level = 1.e6  # ADU / arcsec^2

    # The random seed is used for both the power spectrum realization and the random properties
    # of the galaxies.
    random_seed = 3339201

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

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

    # These will be created for each object below.  The values we'll use will be functions
    # of (x,y) relative to the center of the image.  (r = sqrt(x^2+y^2))
    # psf_fwhm = 0.9 + 0.5 * (r/100)^2  -- arcsec
    # psf_e = 0.4 * (r/100)^1.5         -- large value at the edge, so visible by eye.
    # psf_beta = atan2(y/x) + pi/2      -- tangential pattern

    gal_dilation = 3  # Make the galaxies a bit larger than their original size.
    gal_signal_to_noise = 100  # Pretty high.
    psf_signal_to_noise = 1000  # Even higher.

    logger.info('Starting demo script 10')

    # Read in galaxy catalog
    cat_file_name = 'real_galaxy_catalog_example.fits'
    dir = 'data'
    real_galaxy_catalog = galsim.RealGalaxyCatalog(cat_file_name, dir=dir)
    logger.info('Read in %d real galaxies from catalog',
                real_galaxy_catalog.nobjects)

    # List of IDs to use.  We select 5 particularly irregular galaxies for this demo.
    # Then we'll choose randomly from this list.
    id_list = [106416, 106731, 108402, 116045, 116448]

    # Make the 5 galaxies we're going to use here rather than remake them each time.
    # This means the Fourier transforms of the real galaxy images don't need to be recalculated
    # each time, so it's a bit more efficient.
    gal_list = [
        galsim.RealGalaxy(real_galaxy_catalog, id=id) for id in id_list
    ]

    # Make the galaxies a bit larger than their original observed size.
    gal_list = [gal.dilate(gal_dilation) for gal in gal_list]

    # Setup the PowerSpectrum object we'll be using:
    ps = galsim.PowerSpectrum(lambda k: k**1.8)
    # The argument here is "e_power_function" which defines the E-mode power to use.

    # There is also a b_power_function if you want to include any B-mode power:
    #     ps = galsim.PowerSpectrum(e_power_function, b_power_function)

    # You may even omit the e_power_function argument and have a pure B-mode power spectrum.
    #     ps = galsim.PowerSpectrum(b_power_function = b_power_function)

    # All the random number generator classes derive from BaseDeviate.
    # When we construct another kind of deviate class from any other
    # kind of deviate class, the two share the same underlying random number
    # generator.  Sometimes it can be clearer to just construct a BaseDeviate
    # explicitly and then construct anything else you need from that.
    # Note: A BaseDeviate cannot be used to generate any values.  It can
    # only be used in the constructor for other kinds of deviates.
    # The seeds for the objects are random_seed..random_seed+nobj-1 (which comes later),
    # so use the next one.
    nobj = n_tiles * n_tiles
    rng = galsim.BaseDeviate(random_seed + nobj)

    # Setup the images:
    gal_image = galsim.ImageF(stamp_size * n_tiles, stamp_size * n_tiles)
    psf_image = galsim.ImageF(stamp_size * n_tiles, stamp_size * n_tiles)

    # Update the image WCS to use the image center as the origin of the WCS.
    # The class that acts like a PixelScale except for this offset is called OffsetWCS.
    im_center = gal_image.bounds.trueCenter()
    wcs = galsim.OffsetWCS(scale=pixel_scale, origin=im_center)
    gal_image.wcs = wcs
    psf_image.wcs = wcs

    # We will place the tiles in a random order.  To do this, we make two lists for the
    # ix and iy values.  Then we apply a random permutation to the lists (in tandem).
    ix_list = []
    iy_list = []
    for ix in range(n_tiles):
        for iy in range(n_tiles):
            ix_list.append(ix)
            iy_list.append(iy)
    # This next function will use the given random number generator, rng, and use it to
    # randomly permute any number of lists.  All lists will have the same random permutation
    # applied.
    galsim.random.permute(rng, ix_list, iy_list)

    # Now have the PowerSpectrum object build a grid of shear values for us to use.
    # Also, because of some technical details about how the config stuff handles the random
    # number generator here, we need to duplicate the rng object if we want to have the
    # two output files match.  This means that technically, the same sequence of random numbers
    # will be used in building the grid as will be used by the other uses of rng (permuting the
    # postage stamps and adding noise).  But since they are used in such completely different
    # ways, it is hard to imagine how this could lead to any kind of bias in the images.
    grid_g1, grid_g2 = ps.buildGrid(grid_spacing=stamp_size * pixel_scale,
                                    ngrid=n_tiles,
                                    rng=rng.duplicate())

    # Build each postage stamp:
    for k in range(nobj):
        # The usual random number generator using a different seed for each galaxy.
        rng = galsim.BaseDeviate(random_seed + k)

        # Determine the bounds for this stamp and its center position.
        ix = ix_list[k]
        iy = iy_list[k]
        b = galsim.BoundsI(ix * stamp_size + 1, (ix + 1) * stamp_size,
                           iy * stamp_size + 1, (iy + 1) * stamp_size)
        sub_gal_image = gal_image[b]
        sub_psf_image = psf_image[b]

        pos = wcs.toWorld(b.trueCenter())
        # The image comes out as about 211 arcsec across, so we define our variable
        # parameters in terms of (r/100 arcsec), so roughly the scale size of the image.
        r = math.sqrt(pos.x**2 + pos.y**2) / 100
        psf_fwhm = 0.9 + 0.5 * r**2  # arcsec
        psf_e = 0.4 * r**1.5
        psf_beta = (math.atan2(pos.y, pos.x) + math.pi / 2) * galsim.radians

        # Define the PSF profile
        psf = galsim.Gaussian(fwhm=psf_fwhm)
        psf = psf.shear(e=psf_e, beta=psf_beta)

        # Define the galaxy profile:

        # For this demo, we are doing a ring test where the same galaxy profile is drawn at many
        # orientations stepped uniformly in angle, making a ring in e1-e2 space.
        # We're drawing each profile at 20 different orientations and then skipping to the
        # next galaxy in the list.  So theta steps by 1/20 * 360 degrees:
        theta = k / 20. * 360. * galsim.degrees

        # The index needs to increment every 20 objects so we use k/20 using integer math.
        index = k / 20
        gal = gal_list[index]

        # This makes a new copy so we're not changing the object in the gal_list.
        gal = gal.rotate(theta)

        # Apply the shear from the power spectrum.  We should either turn the gridded shears
        # grid_g1[iy, ix] and grid_g2[iy, ix] into gridded reduced shears using a utility called
        # galsim.lensing.theoryToObserved, or use ps.getShear() which by default gets the reduced
        # shear.  ps.getShear() is also more flexible because it can get the shear at positions that
        # are not on the original grid, as long as they are contained within the bounds of the full
        # grid. So in this example we'll use ps.getShear().
        alt_g1, alt_g2 = ps.getShear(pos)
        gal = gal.shear(g1=alt_g1, g2=alt_g2)

        # Apply half-pixel shift in a random direction.
        shift_r = pixel_scale * 0.5
        ud = galsim.UniformDeviate(rng)
        theta = ud() * 2. * math.pi
        dx = shift_r * math.cos(theta)
        dy = shift_r * math.sin(theta)
        gal = gal.shift(dx, dy)

        # Make the final image, convolving with the psf
        final = galsim.Convolve([psf, gal])

        # Draw the image
        final.drawImage(sub_gal_image)

        # Now add noise to get our desired S/N
        # See demo5.py for more info about how this works.
        sky_level_pixel = sky_level * pixel_scale**2
        noise = galsim.PoissonNoise(rng, sky_level=sky_level_pixel)
        sub_gal_image.addNoiseSNR(noise, gal_signal_to_noise)

        # For the PSF image, we also shift the PSF by the same amount.
        psf = psf.shift(dx, dy)

        # Draw the PSF image:
        # We use real space integration over the pixels to avoid some of the
        # artifacts that can show up with Fourier convolution.
        # The level of the artifacts is quite low, but when drawing with
        # so little noise, they are apparent with ds9's zscale viewing.
        psf.drawImage(sub_psf_image, method='real_space')

        # Again, add noise, but at higher S/N this time.
        sub_psf_image.addNoiseSNR(noise, psf_signal_to_noise)

        logger.info('Galaxy (%d,%d): position relative to center = %s', ix, iy,
                    str(pos))

    logger.info('Done making images of postage stamps')

    # Now write the images to disk.
    images = [gal_image, psf_image]
    galsim.fits.writeMulti(images, file_name)
    logger.info('Wrote image to %r', file_name)
Beispiel #29
0
def main(args):
    # Draw the original galaxies and measure their shapes
    rgc = galsim.RealGalaxyCatalog(catalog_filename, dir=catalog_dir)

    g1_list = []
    g2_list = []
    sigma_list = []
    for i in range(args.first_index, args.first_index + args.nitems):
        test_image = galsim.ImageD(imsize, imsize)
        real_galaxy = galsim.RealGalaxy(rgc, index=i)
        real_galaxy.original_image.draw(test_image)
        shape = CatchAdaptiveMomErrors(test_image)
        if shape == -10:
            g1_list.append(-10)
            g2_list.append(-10)
            sigma_list.append(-10)
        else:
            g1_list.append(shape.observed_shape.g1)
            g2_list.append(shape.observed_shape.g2)
            sigma_list.append(shape.moments_sigma)
    g1_list = numpy.array(g1_list)
    g2_list = numpy.array(g2_list)

    # Define the config dictionaries we will use for all the following tests
    config_and_file_list = get_config(nitems=args.nitems,
                                      first_index=args.first_index,
                                      file_root=args.file_root)

    i = 1  # For printing status statements

    # Now, run through the various things we need to test in loops.
    for base_config, output_file in config_and_file_list:
        f = open(output_file, 'w')
        for padding in padding_list:  # Amount of padding
            for interpolant in use_interpolants:  # Possible interpolants
                print 'Angle test ',
                for angle in angle_list:  # Possible rotation angles
                    print i,
                    i += 1
                    print_results(f,
                                  g1_list,
                                  g2_list,
                                  sigma_list,
                                  test_realgalaxy(base_config,
                                                  angle=angle,
                                                  x_interpolant=interpolant,
                                                  padding=padding,
                                                  seed=rseed +
                                                  args.first_index),
                                  first_index=args.first_index)
                    print_results(f,
                                  g1_list,
                                  g2_list,
                                  sigma_list,
                                  test_realgalaxy(base_config,
                                                  angle=angle,
                                                  k_interpolant=interpolant,
                                                  padding=padding,
                                                  seed=rseed +
                                                  args.first_index),
                                  first_index=args.first_index)
                print ''
                print 'Shear/magnification test ',
                for (
                        g1, g2, mag
                ) in shear_and_magnification_list:  # Shear and magnification
                    print i, "(", g1, g2, ")",
                    i += 1
                    print_results(f,
                                  g1_list,
                                  g2_list,
                                  sigma_list,
                                  test_realgalaxy(base_config,
                                                  shear=(g1, g2),
                                                  magnification=mag,
                                                  x_interpolant=interpolant,
                                                  padding=padding,
                                                  seed=rseed +
                                                  args.first_index),
                                  first_index=args.first_index)
                    print_results(f,
                                  g1_list,
                                  g2_list,
                                  sigma_list,
                                  test_realgalaxy(base_config,
                                                  shear=(g1, g2),
                                                  magnification=mag,
                                                  k_interpolant=interpolant,
                                                  padding=padding,
                                                  seed=rseed +
                                                  args.first_index),
                                  first_index=args.first_index)
                print ''
                for shift in shift_list:
                    print i, "(", shift, ")",
                    i += 1
                    print_results(f,
                                  g1_list,
                                  g2_list,
                                  sigma_list,
                                  test_realgalaxy(base_config,
                                                  shift=shift,
                                                  x_interpolant=interpolant,
                                                  padding=padding,
                                                  seed=rseed +
                                                  args.first_index),
                                  first_index=args.first_index)
                    print_results(f,
                                  g1_list,
                                  g2_list,
                                  sigma_list,
                                  test_realgalaxy(base_config,
                                                  shift=shift,
                                                  k_interpolant=interpolant,
                                                  padding=padding,
                                                  seed=rseed +
                                                  args.first_index),
                                  first_index=args.first_index)
                print ''
        f.close()
Beispiel #30
0
def test_whiten():
    """Test the options in config to whiten images
    """
    real_gal_dir = os.path.join('..','examples','data')
    real_gal_cat = 'real_galaxy_catalog_23.5_example.fits'
    config = {
        'image' : {
            'type' : 'Single',
            'random_seed' : 1234,
            'pixel_scale' : 0.05,
        },
        'stamp' : {
            'type' : 'Basic',
            'size' : 32,
        },
        'gal' : {
            'type' : 'RealGalaxy',
            'index' : 79,
            'flux' : 100,
        },
        'psf' : {  # This is really slow if we don't convolve by a PSF.
            'type' : 'Gaussian',
            'sigma' : 0.05
        },
        'input' : {
            'real_catalog' : {
                'dir' : real_gal_dir ,
                'file_name' : real_gal_cat
            }
        }
    }

    # First build by hand (no whitening yet)
    rng = galsim.BaseDeviate(1234 + 1)
    rgc = galsim.RealGalaxyCatalog(os.path.join(real_gal_dir, real_gal_cat))
    gal = galsim.RealGalaxy(rgc, index=79, flux=100, rng=rng)
    psf = galsim.Gaussian(sigma=0.05)
    final = galsim.Convolve(gal,psf)
    im1a = final.drawImage(nx=32, ny=32, scale=0.05)

    # Compare to what config builds
    galsim.config.ProcessInput(config)
    im1b, cv1b = galsim.config.BuildStamp(config, do_noise=False)
    np.testing.assert_equal(cv1b, 0.)
    np.testing.assert_equal(im1b.array, im1a.array)

    # Now add whitening, but no noise yet.
    cv1a = final.noise.whitenImage(im1a)
    print('From whiten, current_var = ',cv1a)
    galsim.config.RemoveCurrent(config)
    config['image']['noise'] =  { 'whiten' : True, }
    im1c, cv1c = galsim.config.BuildStamp(config, do_noise=False)
    print('From BuildStamp, current_var = ',cv1c)
    np.testing.assert_equal(cv1c, cv1a)
    np.testing.assert_equal(im1c.array, im1a.array)
    rng1 = rng.duplicate()  # Save current state of rng

    # 1. Gaussian noise
    #####
    config['image']['noise'] =  {
        'type' : 'Gaussian',
        'variance' : 50,
        'whiten' : True,
    }
    galsim.config.RemoveCurrent(config)
    im2a = im1a.copy()
    im2a.addNoise(galsim.GaussianNoise(sigma=math.sqrt(50-cv1a), rng=rng))
    im2b, cv2b = galsim.config.BuildStamp(config)
    np.testing.assert_almost_equal(cv2b, 50)
    np.testing.assert_almost_equal(im2b.array, im2a.array, decimal=5)

    # If whitening already added too much noise, raise an exception
    config['image']['noise']['variance'] = 1.e-5
    try:
        np.testing.assert_raises(RuntimeError, galsim.config.BuildStamp,config)
    except ImportError:
        pass

    # 2. Poisson noise
    #####
    config['image']['noise'] =  {
        'type' : 'Poisson',
        'sky_level_pixel' : 50,
        'whiten' : True,
    }
    galsim.config.RemoveCurrent(config)
    im3a = im1a.copy()
    sky = 50 - cv1a
    rng.reset(rng1.duplicate())
    im3a.addNoise(galsim.PoissonNoise(sky_level=sky, rng=rng))
    im3b, cv3b = galsim.config.BuildStamp(config)
    np.testing.assert_almost_equal(cv3b, 50, decimal=5)
    np.testing.assert_almost_equal(im3b.array, im3a.array, decimal=5)

    # It's more complicated if the sky is quoted per arcsec and the wcs is not uniform.
    config2 = galsim.config.CopyConfig(config)
    galsim.config.RemoveCurrent(config2)
    config2['image']['sky_level'] = 100
    config2['image']['wcs'] =  {
        'type' : 'UVFunction',
        'ufunc' : '0.05*x + 0.001*x**2',
        'vfunc' : '0.05*y + 0.001*y**2',
    }
    del config2['image']['pixel_scale']
    del config2['wcs']
    config2['image']['noise']['symmetrize'] = 4 # Also switch to symmetrize, just to mix it up.
    del config2['image']['noise']['whiten']
    rng.reset(1234+1) # Start fresh, since redoing the whitening/symmetrizing
    wcs = galsim.UVFunction(ufunc='0.05*x + 0.001*x**2', vfunc='0.05*y + 0.001*y**2')
    im3c = galsim.Image(32,32, wcs=wcs)
    im3c = final.drawImage(im3c)
    cv3c = final.noise.symmetrizeImage(im3c,4)
    sky = galsim.Image(im3c.bounds, wcs=wcs)
    wcs.makeSkyImage(sky, 100)
    mean_sky = np.mean(sky.array)
    im3c += sky
    extra_sky = 50 - cv3c
    im3c.addNoise(galsim.PoissonNoise(sky_level=extra_sky, rng=rng))
    im3d, cv3d = galsim.config.BuildStamp(config2)
    np.testing.assert_almost_equal(cv3d, 50 + mean_sky, decimal=4)
    np.testing.assert_almost_equal(im3d.array, im3c.array, decimal=5)

    config['image']['noise']['sky_level_pixel'] = 1.e-5
    try:
        np.testing.assert_raises(RuntimeError, galsim.config.BuildStamp,config)
    except ImportError:
        pass

    # 3. CCDNoise
    #####
    config['image']['noise'] =  {
        'type' : 'CCD',
        'sky_level_pixel' : 25,
        'read_noise' : 5,
        'gain' : 1,
        'whiten' : True,
    }
    galsim.config.RemoveCurrent(config)
    im4a = im1a.copy()
    rn = math.sqrt(25-cv1a)
    rng.reset(rng1.duplicate())
    im4a.addNoise(galsim.CCDNoise(sky_level=25, read_noise=rn, gain=1, rng=rng))
    im4b, cv4b = galsim.config.BuildStamp(config)
    np.testing.assert_almost_equal(cv4b, 50, decimal=5)
    np.testing.assert_almost_equal(im4b.array, im4a.array, decimal=5)

    # Repeat with gain != 1
    config['image']['noise']['gain'] = 3.7
    galsim.config.RemoveCurrent(config)
    im5a = im1a.copy()
    rn = math.sqrt(25-cv1a * 3.7**2)
    rng.reset(rng1.duplicate())
    im5a.addNoise(galsim.CCDNoise(sky_level=25, read_noise=rn, gain=3.7, rng=rng))
    im5b, cv5b = galsim.config.BuildStamp(config)
    np.testing.assert_almost_equal(cv5b, 50, decimal=5)
    np.testing.assert_almost_equal(im5b.array, im5a.array, decimal=5)

    # And again with a non-trivial sky image
    galsim.config.RemoveCurrent(config2)
    config2['image']['noise'] = config['image']['noise']
    config2['image']['noise']['symmetrize'] = 4
    del config2['image']['noise']['whiten']
    rng.reset(1234+1)
    im5c = galsim.Image(32,32, wcs=wcs)
    im5c = final.drawImage(im5c)
    cv5c = final.noise.symmetrizeImage(im5c, 4)
    sky = galsim.Image(im5c.bounds, wcs=wcs)
    wcs.makeSkyImage(sky, 100)
    mean_sky = np.mean(sky.array)
    im5c += sky
    rn = math.sqrt(25-cv5c * 3.7**2)
    im5c.addNoise(galsim.CCDNoise(sky_level=25, read_noise=rn, gain=3.7, rng=rng))
    im5d, cv5d = galsim.config.BuildStamp(config2)
    np.testing.assert_almost_equal(cv5d, 50 + mean_sky, decimal=4)
    np.testing.assert_almost_equal(im5d.array, im5c.array, decimal=5)

    config['image']['noise']['sky_level_pixel'] = 1.e-5
    config['image']['noise']['read_noise'] = 0
    try:
        np.testing.assert_raises(RuntimeError, galsim.config.BuildStamp,config)
    except ImportError:
        pass

    # 4. COSMOSNoise
    #####
    file_name = os.path.join(galsim.meta_data.share_dir,'acs_I_unrot_sci_20_cf.fits')
    config['image']['noise'] =  {
        'type' : 'COSMOS',
        'file_name' : file_name,
        'variance' : 50,
        'whiten' : True,
    }
    galsim.config.RemoveCurrent(config)
    im6a = im1a.copy()
    rng.reset(rng1.duplicate())
    noise = galsim.getCOSMOSNoise(file_name=file_name, variance=50, rng=rng)
    noise -= galsim.UncorrelatedNoise(cv1a, rng=rng, wcs=noise.wcs)
    im6a.addNoise(noise)
    im6b, cv6b = galsim.config.BuildStamp(config)
    np.testing.assert_almost_equal(cv6b, 50, decimal=5)
    np.testing.assert_almost_equal(im6b.array, im6a.array, decimal=5)

    config['image']['noise']['variance'] = 1.e-5
    del config['_current_cn_tag']
    try:
        np.testing.assert_raises(RuntimeError, galsim.config.BuildStamp,config)
    except ImportError:
        pass