Ejemplo n.º 1
0
def _GenerateFromRandomGaussian(config, base, value_type):
    """@brief Return a random value drawn from a Gaussian distribution
    """
    rng = galsim.config.GetRNG(config, base)

    req = { 'sigma' : float }
    opt = { 'mean' : float, 'min' : float, 'max' : float }
    kwargs, safe = galsim.config.GetAllParams(config, base, req=req, opt=opt)

    sigma = kwargs['sigma']

    if 'gd' in base and base['current_gdsigma'] == sigma:
        # Minor subtlety here.  GaussianDeviate requires two random numbers to
        # generate a single Gaussian deviate.  But then it gets a second
        # deviate for free.  So it's more efficient to store gd than to make
        # a new one each time.  So check if we did that.
        gd = base['gd']
    else:
        # Otherwise, just go ahead and make a new one.
        gd = galsim.GaussianDeviate(rng,sigma=sigma)
        base['gd'] = gd
        base['current_gdsigma'] = sigma

    if 'min' in kwargs or 'max' in kwargs:
        # Clip at min/max.
        # However, special cases if min == mean or max == mean
        #  -- can use fabs to double the chances of falling in the range.
        mean = kwargs.get('mean',0.)
        min = kwargs.get('min',-float('inf'))
        max = kwargs.get('max',float('inf'))

        do_abs = False
        do_neg = False
        if (min >= mean) and (max > mean):
            do_abs = True
            lo = min - mean
            hi = max - mean
        elif (min < mean) and (max <= mean):
            do_abs = True
            do_neg = True
            hi = mean - min
            lo = mean - max
        else:
            lo = min - mean
            hi = max - mean

        # Emulate a do-while loop
        import math
        while True:
            val = gd()
            if do_abs: val = math.fabs(val)
            if val >= lo and val <= hi: break
        if do_neg: val = -val
        val += mean
    else:
        val = gd()
        if 'mean' in kwargs: val += kwargs['mean']

    #print(base['obj_num'],'RandomGaussian: ',val)
    return val, False
Ejemplo n.º 2
0
    def _getAtmKwargs(self):
        ud = galsim.UniformDeviate(self.rng)
        gd = galsim.GaussianDeviate(self.rng)

        # Use values measured from Ellerbroek 2008.
        altitudes = [0.0, 2.58, 5.16, 7.73, 12.89, 15.46]
        # Elevate the ground layer though.  Otherwise, PSFs come out too correlated
        # across the field of view.
        altitudes[0] = 0.2

        # Use weights from Ellerbroek too, but add some random perturbations.
        weights = [0.652, 0.172, 0.055, 0.025, 0.074, 0.022]
        weights = [np.abs(w * (1.0 + 0.1 * gd())) for w in weights]
        weights = np.clip(weights, 0.01,
                          0.8)  # keep weights from straying too far.
        weights /= np.sum(weights)  # renormalize

        # Draw outer scale from truncated log normal
        L0 = 0
        while L0 < 10.0 or L0 > 100:
            L0 = np.exp(gd() * 0.6 + np.log(25.0))
        # Given the desired targetFWHM and randomly selected L0, determine appropriate
        # r0_500
        if self.logger:
            self.logger.debug("target FWHM: {}".format(self.targetFWHM))
        r0_500 = AtmosphericPSF._r0_500(self.wlen_eff, L0, self.targetFWHM)
        if self.logger:
            self.logger.debug("Found r0_500, L0: {}, {}".format(r0_500, L0))
            self.logger.debug("yields vonKarman FWHM: {}".format(
                AtmosphericPSF._vkSeeing(r0_500, self.wlen_eff, L0)))

        # Broadcast common outer scale across all layers
        L0 = [L0] * 6

        # Uniformly draw layer speeds between 0 and max_speed.
        maxSpeed = 20.0
        speeds = [ud() * maxSpeed for _ in range(6)]
        # Isotropically draw directions.
        directions = [ud() * 360.0 * galsim.degrees for _ in range(6)]

        if self.logger:
            self.logger.debug("airmass = {}".format(self.airmass))
            self.logger.debug("wlen_eff = {}".format(self.wlen_eff))
            self.logger.debug("r0_500 = {}".format(r0_500))
            self.logger.debug("L0 = {}".format(L0))
            self.logger.debug("speeds = {}".format(speeds))
            self.logger.debug("directions = {}".format(directions))
            self.logger.debug("altitudes = {}".format(altitudes))
            self.logger.debug("weights = {}".format(weights))

        return dict(r0_500=r0_500,
                    L0=L0,
                    speed=speeds,
                    direction=directions,
                    altitude=altitudes,
                    r0_weights=weights,
                    rng=self.rng,
                    screen_size=self.screen_size,
                    screen_scale=self.screen_scale)
Ejemplo n.º 3
0
def simulate_shear(constants, redshift, nbins, noise_sd=0.0, seed=0):
    """Takes cosmological parameters, generates a shear map, and adds
    noise.

    Inputs:
        constants: Constants, object for cosmological constants
        redshift: float, the redshift value for the sample
        nbins: int, the number of bins for the correlation function
        noise_sd: float, the standard deviation for IID Gaussian noise.
        seed: integer, seed for the RNG; if 0 it uses a randomly chosen seed.

    Returns:
        A pair of shear spectrum grids.
    """

    grid_nx = 100  # length of grid in one dimension (degrees)
    theta = 10.0  # grid spacing
    dtheta = theta / grid_nx

    # wavenumbers at which to evaluate power spectra
    ell = np.logspace(-2.0, 4.0, num=50)

    nicaea_obj = constants.nicaea_object()
    psObs_nicaea = nicaea_obj.convergencePowerSpectrum(ell=ell, z=redshift)
    psObs_tabulated = galsim.LookupTable(ell,
                                         psObs_nicaea,
                                         interpolant='linear')
    ps_galsim = galsim.PowerSpectrum(psObs_tabulated,
                                     delta2=False,
                                     units=galsim.radians)

    grid_deviate = galsim.BaseDeviate(seed)
    g1, g2, kappa = ps_galsim.buildGrid(grid_spacing=dtheta,
                                        ngrid=grid_nx,
                                        rng=grid_deviate,
                                        units='degrees',
                                        kmin_factor=2,
                                        kmax_factor=2,
                                        get_convergence=True)
    g1_r, g2_r, _ = galsim.lensing_ps.theoryToObserved(g1, g2, kappa)
    rng = galsim.GaussianDeviate(seed=seed)

    g1_noise_grid = galsim.ImageD(grid_nx, grid_nx)
    g2_noise_grid = galsim.ImageD(grid_nx, grid_nx)

    g1_noise_grid.addNoise(galsim.GaussianNoise(rng=rng, sigma=noise_sd))
    g2_noise_grid.addNoise(galsim.GaussianNoise(rng=rng, sigma=noise_sd))

    g1_noisy = np.add(g1_r, g1_noise_grid.array)
    g2_noisy = np.add(g2_r, g2_noise_grid.array)

    min_sep = dtheta
    max_sep = grid_nx * np.sqrt(2) * dtheta
    grid_range = dtheta * np.arange(grid_nx)
    x, y = np.meshgrid(grid_range, grid_range)
    stats = run_treecorr(x, y, g1, g2, min_sep, max_sep, nbins=nbins)

    return g1_noisy, g2_noisy, stats
Ejemplo n.º 4
0
    def _add_read_noise_and_bias(self, amp_name):
        """
        Add read noise and bias.  This should be done as the final
        step before returning the processed image.

        Parameters
        ----------
        amp_name : str
            The amplifier name, e.g., "R22_S11_C00".
        """
        amp_info = self.camera_info.get_amp_info(amp_name)
        full_arr = self.amp_images[amp_name].getArray()
        rng = galsim.GaussianDeviate(seed=self.rng,
                                     sigma=amp_info.getReadNoise())
        rn_data = np.zeros(np.prod(full_arr.shape))
        rng.generate(rn_data)
        full_arr += rn_data.reshape(full_arr.shape)
        full_arr += self.config['electronics_readout']['bias_level']
Ejemplo n.º 5
0
def GenLogNormal(config, base, value_type):
    """Generate a random number from a log-normal distribution.
    """
    if 'rng' not in base:
        raise ValueError("No base['rng'] available for type = LogNormal")

    rng = base['rng']

    req = {'mean': float, 'sigma': float}
    params, safe = galsim.config.GetAllParams(config, base, req=req)

    mean = params['mean']
    sigma = params['sigma']

    try:
        # This uses the ngmix code, downloadable from here:
        # https://github.com/esheldon/ngmix

        # Specifically, we use the LogNormal class here:
        # https://github.com/esheldon/ngmix/blob/master/ngmix/priors.py

        # The only thing we need to be careful about is the random number generator.
        # Erin's code uses numpy.random, not a GalSim rng.  So we use the GalSim rng to
        # seed numpy.random.  This should produce deterministic results.
        import ngmix

        lgn = ngmix.priors.LogNormal(mean, sigma)
        seed = rng.raw()
        numpy.random.seed(seed)
        value = lgn.sample()

    except ImportError:
        # If the user doesn't have ngmix installed, it will use this branch, which is equivalent.
        # The above was mostly a demonstration of how one could use an external module such as
        # ngmix that uses numpy.random for its random number generator.
        # Here is an equivalent code using GalSim's GaussianDeviate class.

        logmean = numpy.log(mean) - 0.5 * numpy.log(1 + sigma**2 / mean**2)
        logvar = numpy.log(1 + sigma**2 / mean**2)
        logsigma = numpy.sqrt(logvar)
        gd = galsim.GaussianDeviate(rng, mean=logmean, sigma=logsigma)
        return numpy.exp(gd())

    return value, False
Ejemplo n.º 6
0
def draw_atmosphere_params(random_state=None, save=None):
    '''
    draw inputs for galsim.Atmosphere simulation based on: 
    Tokovinin 2006 OTP model, seeing from LSST site characterization, and NOAA GFS model winds
    Inputs
    ======
    - random_state to seed generation (default is None)
    - save: where to save the dict of parameters, except if None (default)
    '''
    pgen = pws.gen_params.ParameterGenerator()
    params = pgen.draw_parameters()

    out = {'altitude': params['h']}
    out['r0_weights'] = params['j']
    out['speed'] = params['speed'].flatten()
    out['direction'] = [
        i * galsim.degrees for i in params['direction'].flatten()
    ]

    # use random seed to seed a gaussian random number generator
    gd = galsim.GaussianDeviate(galsim.BaseDeviate(random_state))

    # outer scale, use Josh's ImSim numbers (truncated log normal, median at 25m):
    L0 = 0
    while L0 < 10.0 or L0 > 100:
        L0 = np.exp(gd() * .6 + np.log(25.))
    out['L0'] = [L0]

    # set parameters of log-normal seeing distributino:
    # from the LSST SRD (or similar document)
    s = .452
    mu = -.5174

    # set an r0 value
    fwhm = np.exp(gd() * s + mu)

    out['r0_500'] = [r0_from_vk(fwhm, L0)]

    if save is not None:
        with open(save, 'wb') as file:
            pickle.dump(out, file)

    ## or maybe store results in a dict that I can unzip/whatever directly into Atmosphere
    return out
Ejemplo n.º 7
0
def GenLogNormal(config, base, value_type):
    """
    Generate a random number from a log-normal distribution.
    """
    if 'rng' not in base:
        raise ValueError("No base['rng'] available for type = LogNormal")

    rng = base['rng']

    req = {'mean': float, 'sigma': float}
    params, safe = galsim.config.GetAllParams(config, base, req=req)

    mean = params['mean']
    sigma = params['sigma']

    logmean = numpy.log(mean) - 0.5 * numpy.log(1 + sigma**2 / mean**2)
    logvar = numpy.log(1 + sigma**2 / mean**2)
    logsigma = numpy.sqrt(logvar)
    gd = galsim.GaussianDeviate(rng, mean=logmean, sigma=logsigma)
    value = numpy.exp(gd())

    return value, False
Ejemplo n.º 8
0
def main(argv):
    """
    Make images similar to that done for the Great08 challenge:
      - Each fits file is 10 x 10 postage stamps.
        (The real Great08 images are 100x100, but in the interest of making the Demo
         script a bit quicker, we only build 100 stars and 100 galaxies.)
      - Each postage stamp is 40 x 40 pixels.
      - One image is all stars.
      - A second image is all galaxies.
      - Applied shear is the same for each galaxy.
      - Galaxies are oriented randomly, but in pairs to cancel shape noise.
      - Noise is Poisson using a nominal sky value of 1.e6.
      - Galaxies are Exponential profiles.
    """
    logging.basicConfig(format="%(message)s", level=logging.INFO, stream=sys.stdout)
    logger = logging.getLogger("demo5")

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

    nx_tiles = 10                   #
    ny_tiles = 10                   #
    stamp_xsize = 40                #
    stamp_ysize = 40                #

    random_seed = 6424512           #

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

    # Make output directory if not already present.
    if not os.path.isdir('output'):
        os.mkdir('output')
    psf_file_name = os.path.join('output','g08_psf.fits')
    psf_beta = 3                    #
    psf_fwhm = 2.85                 # arcsec (=pixels)
    psf_trunc = 2.*psf_fwhm         # arcsec (=pixels)
    psf_e1 = -0.019                 #
    psf_e2 = -0.007                 #

    gal_file_name = os.path.join('output','g08_gal.fits')
    gal_signal_to_noise = 200       # Great08 "LowNoise" run
    gal_resolution = 0.98           # r_gal / r_psf (use r = half_light_radius)
    # Note: Great08 defined their resolution as r_obs / r_psf, using the convolved
    #       size rather than the pre-convolved size.
    #       Therefore, our r_gal/r_psf = 0.98 approximately corresponds to
    #       their r_obs / r_psf = 1.4.

    gal_ellip_rms = 0.2             # using "distortion" definition of ellipticity:
                                    #   e = (a^2-b^2)/(a^2+b^2), where a and b are the
                                    #   semi-major and semi-minor axes, respectively.
    gal_ellip_max = 0.6             # Maximum value of e, to avoid getting near e=1.
    gal_g1 = 0.013                  # Applied shear, using normal shear definition:
    gal_g2 = -0.008                 #   g = (a-b)/(a+b)

    shift_radius = 1.0              # arcsec (=pixels)

    logger.info('Starting demo script 5 using:')
    logger.info('    - image with %d x %d postage stamps',nx_tiles,ny_tiles)
    logger.info('    - postage stamps of size %d x %d pixels',stamp_xsize,stamp_ysize)
    logger.info('    - Moffat PSF (beta = %.1f, FWHM = %.2f, trunc = %.2f),',
                psf_beta,psf_fwhm,psf_trunc)
    logger.info('    - PSF ellip = (%.3f,%.3f)',psf_e1,psf_e2)
    logger.info('    - Exponential galaxies')
    logger.info('    - Resolution (r_gal / r_psf) = %.2f',gal_resolution)
    logger.info('    - Ellipticities have rms = %.1f, max = %.1f',
                gal_ellip_rms, gal_ellip_max)
    logger.info('    - Applied gravitational shear = (%.3f,%.3f)',gal_g1,gal_g2)
    logger.info('    - Poisson noise (sky level = %.1e).', sky_level)
    logger.info('    - Centroid shifts up to = %.2f pixels',shift_radius)


    # Define the PSF profile
    psf = galsim.Moffat(beta=psf_beta, fwhm=psf_fwhm, trunc=psf_trunc)

    # When something can be constructed from multiple sizes, e.g. Moffat, then
    # you can get any size out even if it wasn't the way the object was constructed.
    # In this case, we extract the half-light radius, even though we built it with fwhm.
    # We'll use this later to set the galaxy's half-light radius in terms of a resolution.
    psf_re = psf.getHalfLightRadius()

    psf = psf.shear(e1=psf_e1,e2=psf_e2)
    logger.debug('Made PSF profile')

    # Define the galaxy profile

    # First figure out the size we need from the resolution
    gal_re = psf_re * gal_resolution

    # Make the galaxy profile starting with flux = 1.
    gal = galsim.Exponential(flux=1., half_light_radius=gal_re)
    logger.debug('Made galaxy profile')

    # This profile is placed with different orientations and noise realizations
    # at each postage stamp in the gal image.
    gal_image = galsim.ImageF(stamp_xsize * nx_tiles-1 , stamp_ysize * ny_tiles-1,
                              scale=pixel_scale)
    psf_image = galsim.ImageF(stamp_xsize * nx_tiles-1 , stamp_ysize * ny_tiles-1,
                              scale=pixel_scale)

    shift_radius_sq = shift_radius**2

    first_in_pair = True  # Make pairs that are rotated by 90 degrees

    k = 0
    for iy in range(ny_tiles):
        for ix in range(nx_tiles):
            # The normal procedure for setting random numbers in GalSim is to start a new
            # random number generator for each object using sequential seed values.
            # This sounds weird at first (especially if you were indoctrinated by Numerical
            # Recipes), but for the boost random number generator we use, the "random"
            # number sequences produced from sequential initial seeds are highly uncorrelated.
            #
            # The reason for this procedure is that when we use multiple processes to build
            # our images, we want to make sure that the results are deterministic regardless
            # of the way the objects get parcelled out to the different processes.
            #
            # Of course, this script isn't using multiple processes, so it isn't required here.
            # However, we do it nonetheless in order to get the same results as the config
            # version of this demo script (demo5.yaml).
            ud = galsim.UniformDeviate(random_seed+k+1)

            # Any kind of random number generator can take another RNG as its first
            # argument rather than a seed value.  This makes both objects use the same
            # underlying generator for their pseudo-random values.
            gd = galsim.GaussianDeviate(ud, sigma=gal_ellip_rms)

            # The -1's in the next line are to provide a border of
            # 1 pixel between postage stamps
            b = galsim.BoundsI(ix*stamp_xsize+1 , (ix+1)*stamp_xsize-1,
                               iy*stamp_ysize+1 , (iy+1)*stamp_ysize-1)
            sub_gal_image = gal_image[b]
            sub_psf_image = psf_image[b]

            # Great08 randomized the locations of the two galaxies in each pair,
            # but for simplicity, we just do them in sequential postage stamps.
            if first_in_pair:
                # Use a random orientation:
                beta = ud() * 2. * math.pi * galsim.radians

                # Determine the ellipticity to use for this galaxy.
                ellip = 1
                while (ellip > gal_ellip_max):
                    # Don't do `ellip = math.fabs(gd())`
                    # Python basically implements this as a macro, so gd() is called twice!
                    val = gd()
                    ellip = math.fabs(val)

                # Make a new copy of the galaxy with an applied e1/e2-type distortion
                # by specifying the ellipticity and a real-space position angle
                ellip_gal = gal.shear(e=ellip, beta=beta)

                first_in_pair = False
            else:
                # Use the previous ellip_gal profile and rotate it by 90 degrees
                ellip_gal = ellip_gal.rotate(90 * galsim.degrees)

                first_in_pair = True

            # Apply the gravitational reduced shear by specifying g1/g2
            this_gal = ellip_gal.shear(g1=gal_g1, g2=gal_g2)

            # Apply a random shift_radius:
            rsq = 2 * shift_radius_sq
            while (rsq > shift_radius_sq):
                dx = (2*ud()-1) * shift_radius
                dy = (2*ud()-1) * shift_radius
                rsq = dx**2 + dy**2

            this_gal = this_gal.shift(dx,dy)
            # Note that the shifted psf that we create here is purely for the purpose of being able
            # to draw a separate, shifted psf image.  We do not use it when convolving the galaxy
            # with the psf.
            this_psf = psf.shift(dx,dy)

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

            # Draw the image
            final_gal.drawImage(sub_gal_image)

            # Now add an appropriate amount of noise to get our desired S/N
            # There are lots of definitions of S/N, but here is the one used by Great08
            # We use a weighted integral of the flux:
            #   S = sum W(x,y) I(x,y) / sum W(x,y)
            #   N^2 = Var(S) = sum W(x,y)^2 Var(I(x,y)) / (sum W(x,y))^2
            # Now we assume that Var(I(x,y)) is constant so
            #   Var(I(x,y)) = noise_var
            # We also assume that we are using a matched filter for W, so W(x,y) = I(x,y).
            # Then a few things cancel and we find that
            # S/N = sqrt( sum I(x,y)^2 / noise_var )
            #
            # The above procedure is encapsulated in the function image.addNoiseSNR which
            # sets the flux appropriately given the variance of the noise model.
            # In our case, noise_var = sky_level_pixel
            sky_level_pixel = sky_level * pixel_scale**2
            noise = galsim.PoissonNoise(ud, sky_level=sky_level_pixel)
            sub_gal_image.addNoiseSNR(noise, gal_signal_to_noise)

            # Draw the PSF image
            # No noise on PSF images.  Just draw it as is.
            this_psf.drawImage(sub_psf_image)

            # For first instance, measure moments
            if ix==0 and iy==0:
                psf_shape = sub_psf_image.FindAdaptiveMom()
                temp_e = psf_shape.observed_shape.e
                if temp_e > 0.0:
                    g_to_e = psf_shape.observed_shape.g / temp_e
                else:
                    g_to_e = 0.0
                logger.info('Measured best-fit elliptical Gaussian for first PSF image: ')
                logger.info('  g1, g2, sigma = %7.4f, %7.4f, %7.4f (pixels)',
                            g_to_e*psf_shape.observed_shape.e1,
                            g_to_e*psf_shape.observed_shape.e2, psf_shape.moments_sigma)

            x = b.center().x
            y = b.center().y
            logger.info('Galaxy (%d,%d): center = (%.0f,%0.f)  (e,beta) = (%.4f,%.3f)',
                        ix,iy,x,y,ellip,beta/galsim.radians)
            k = k+1

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

    # Now write the images to disk.
    psf_image.write(psf_file_name)
    logger.info('Wrote PSF file %s',psf_file_name)

    gal_image.write(gal_file_name)
    logger.info('Wrote image to %r',gal_file_name)  # using %r adds quotes around filename for us
Ejemplo n.º 9
0
    def __init__(self,
                 real_galaxy_catalog,
                 index=None,
                 id=None,
                 random=False,
                 rng=None,
                 x_interpolant=None,
                 k_interpolant=None,
                 flux=None,
                 pad_factor=0,
                 noise_pad=False,
                 pad_image=None,
                 use_cache=True,
                 gsparams=None):

        import pyfits
        import numpy as np

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Calculate the PSF "deconvolution" kernel
        psf_inv = galsim.SBDeconvolve(self.original_PSF, gsparams=gsparams)
        # Initialize the SBProfile attribute
        GSObject.__init__(
            self,
            galsim.SBConvolve([self.original_image, psf_inv],
                              gsparams=gsparams))
Ejemplo n.º 10
0
def _GenerateFromRandomGaussian(param, param_name, base, value_type):
    """@brief Return a random value drawn from a Gaussian distribution
    """
    if 'rng' not in base:
        raise ValueError(
            "No base['rng'] available for %s.type = RandomGaussian" %
            param_name)
    rng = base['rng']

    req = {'sigma': float}
    opt = {'mean': float, 'min': float, 'max': float}
    kwargs, safe = GetAllParams(param, param_name, base, req=req, opt=opt)

    sigma = kwargs['sigma']

    if 'gd' in base:
        # Minor subtlety here.  GaussianDeviate requires two random numbers to
        # generate a single Gaussian deviate.  But then it gets a second
        # deviate for free.  So it's more efficient to store gd than to make
        # a new one each time.  So check if we did that.
        gd = base['gd']
        if base['current_gdsigma'] != sigma:
            gd.setSigma(sigma)
            base['current_gdsigma'] = sigma
    else:
        # Otherwise, just go ahead and make a new one.
        gd = galsim.GaussianDeviate(rng, sigma=sigma)
        base['gd'] = gd
        base['current_gdsigma'] = sigma

    if 'min' in kwargs or 'max' in kwargs:
        # Clip at min/max.
        # However, special cases if min == mean or max == mean
        #  -- can use fabs to double the chances of falling in the range.
        mean = kwargs.get('mean', 0.)
        min = kwargs.get('min', -float('inf'))
        max = kwargs.get('max', float('inf'))

        do_abs = False
        do_neg = False
        if min == mean:
            do_abs = True
            max -= mean
            min = -max
        elif max == mean:
            do_abs = True
            do_neg = True
            min -= mean
            max = -min
        else:
            min -= mean
            max -= mean

        # Emulate a do-while loop
        #print 'sigma = ',sigma
        import math
        while True:
            val = gd()
            #print 'val = ',val
            if do_abs: val = math.fabs(val)
            if val >= min and val <= max: break
        if do_neg: val = -val
        val += mean
    else:
        val = gd()
        if 'mean' in kwargs: val += kwargs['mean']

    #print 'RandomGaussian: ',val
    return val, False
Ejemplo n.º 11
0
    def build_file(seed, file_name, mass):
        """A function that does all the work to build a single file.
           Returns the total time taken.
        """
        t1 = time.time()

        full_image = galsim.ImageF(image_size, image_size)
        full_image.setScale(pixel_scale)

        # The weight image will hold the inverse variance for each pixel.
        weight_image = galsim.ImageF(image_size, image_size)
        weight_image.setScale(pixel_scale)

        # It is common for astrometric images to also have a bad pixel mask.  We don't have any
        # defect simulation currently, so our bad pixel masks are currently all zeros. 
        # But someday, we plan to add defect functionality to GalSim, at which point, we'll
        # be able to mark those defects on a bad pixel mask.
        # Note: the S in ImageS means to use "short int" for the data type.
        # This is a typical choice for a bad pixel image.
        badpix_image = galsim.ImageS(image_size, image_size)
        badpix_image.setScale(pixel_scale)

        # Setup the NFWHalo stuff:
        nfw = galsim.NFWHalo(mass=mass, conc=nfw_conc, redshift=nfw_z_halo,
                             omega_m=omega_m, omega_lam=omega_lam)
        # Note: the last two are optional.  If they are omitted, then (omega_m=0.3, omega_lam=0.7) 
        # are actually the defaults.  If you only specify one of them, the other is set so that 
        # the total is 1.  But you can define both values so that the total is not 1 if you want.
        # Radiation is assumed to be zero and dark energy equation of state w = -1.
        # If you want to include either radiation or more complicated dark energy models,
        # you can define your own cosmology class that defines the functions a(z), E(a), and 
        # Da(z_source, z_lens).  Then you can pass this to NFWHalo as a `cosmo` parameter.

        # The "true" center of the image is allowed to be halfway between two pixels, as is the 
        # case for even-sized images.  full_image.bounds.center() is an integer position,
        # which would be 1/2 pixel up and to the right of the true center in this case.
        im_center = full_image.bounds.trueCenter()

        for k in range(nobj):

            # Initialize the random number generator we will be using for this object:
            rng = galsim.UniformDeviate(seed+k)

            # Determine where this object is going to go.
            # We choose points randomly within a donut centered at the center of the main image
            # in order to avoid placing galaxies too close to the halo center where the lensing 
            # is not weak.  We use an inner radius of 10 arcsec and an outer radius of 50 arcsec,
            # which takes us essentially to the edge of the image.
            radius = 50
            inner_radius = 10
            max_rsq = radius**2
            min_rsq = inner_radius**2
            while True:  # (This is essentially a do..while loop.)
                x = (2.*rng()-1) * radius
                y = (2.*rng()-1) * radius
                rsq = x**2 + y**2
                if rsq >= min_rsq and rsq <= max_rsq: break
            pos = galsim.PositionD(x,y)

            # We also need the position in pixels to determine where to place the postage
            # stamp on the full image.
            image_pos = pos / pixel_scale + im_center

            # For even-sized postage stamps, the nominal center (returned by stamp.bounds.center())
            # cannot be at the true center (returned by stamp.bounds.trueCenter()) of the postage 
            # stamp, since the nominal center values have to be integers.  Thus, the nominal center
            # is 1/2 pixel up and to the right of the true center.
            # If we used odd-sized postage stamps, we wouldn't need to do this.
            x_nominal = image_pos.x + 0.5
            y_nominal = image_pos.y + 0.5

            # Get the integer values of these which will be the actual nominal center of the 
            # postage stamp image.
            ix_nominal = int(math.floor(x_nominal+0.5))
            iy_nominal = int(math.floor(y_nominal+0.5))

            # The remainder will be accounted for in a shift
            dx = x_nominal - ix_nominal
            dy = y_nominal - iy_nominal

            # Make the pixel:
            pix = galsim.Pixel(pixel_scale)

            # Make the PSF profile:
            psf = galsim.Kolmogorov(fwhm = psf_fwhm)

            # Determine the random values for the galaxy:
            flux = rng() * (gal_flux_max-gal_flux_min) + gal_flux_min
            hlr = rng() * (gal_hlr_max-gal_hlr_min) + gal_hlr_min
            gd = galsim.GaussianDeviate(rng, sigma = gal_eta_rms)
            eta1 = gd()  # Unlike g or e, large values of eta are valid, so no need to cutoff.
            eta2 = gd()

            # Make the galaxy profile with these values:
            gal = galsim.Exponential(half_light_radius=hlr, flux=flux)
            gal.applyShear(eta1=eta1, eta2=eta2)

            # Now apply the appropriate lensing effects for this position from 
            # the NFW halo mass.
            try:
                g1,g2 = nfw.getShear( pos , nfw_z_source )
                shear = galsim.Shear(g1=g1,g2=g2)
            except:
                # This shouldn't happen, since we exclude the inner 10 arcsec, but it's a 
                # good idea to use the try/except block here anyway.
                import warnings        
                warnings.warn("Warning: NFWHalo shear is invalid -- probably strong lensing!  " +
                              "Using shear = 0.")
                shear = galsim.Shear(g1=0,g2=0)

            mu = nfw.getMagnification( pos , nfw_z_source )
            if mu < 0:
                import warnings
                warnings.warn("Warning: mu < 0 means strong lensing!  Using mu=25.")
                mu = 25
            elif mu > 25:
                import warnings
                warnings.warn("Warning: mu > 25 means strong lensing!  Using mu=25.")
                mu = 25

            gal.applyMagnification(mu)
            gal.applyShear(shear)

            # Build the final object
            final = galsim.Convolve([psf, pix, gal])

            # Account for the non-integral portion of the position
            final.applyShift(dx*pixel_scale,dy*pixel_scale)

            # Draw the stamp image
            stamp = final.draw(dx=pixel_scale)

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

            # Find overlapping bounds
            bounds = stamp.bounds & full_image.bounds
            full_image[bounds] += stamp[bounds]


        # Add Poisson noise to the full image
        sky_level_pixel = sky_level * pixel_scale**2

        # Going to the next seed isn't really required, but it matches the behavior of the 
        # config parser, so doing this will result in identical output files.
        # If you didn't care about that, you could instead construct this as a continuation
        # of the last RNG from the above loop
        rng = galsim.BaseDeviate(seed+nobj)
        full_image.addNoise(galsim.PoissonNoise(rng,sky_level=sky_level_pixel))

        # For the weight image, we only want the noise from the sky.  (If we were including
        # read_noise, we'd want that as well.)  Including the Poisson noise from the objects
        # as well tends to bias fits that use this as a weight, since the model becomes
        # magnitude-dependent.
        # The variance is just sky_level_pixel.  And we want the inverse of this.
        weight_image.fill(1./sky_level_pixel)

        # Write the file to disk:
        galsim.fits.writeMulti([full_image, badpix_image, weight_image], file_name)

        t2 = time.time()
        return t2-t1
Ejemplo n.º 12
0
def test_float_value():
    """Test various ways to generate a float value
    """
    import time
    t1 = time.time()

    config = {
        'input': {
            'catalog': [{
                'dir': 'config_input',
                'file_name': 'catalog.txt'
            }, {
                'dir': 'config_input',
                'file_name': 'catalog.fits'
            }],
            'dict': [{
                'dir': 'config_input',
                'file_name': 'dict.p'
            }, {
                'dir': 'config_input',
                'file_name': 'dict.json'
            }, {
                'dir': 'config_input',
                'file_name': 'dict.yaml'
            }]
        },
        'val1': 9.9,
        'val2': int(400),
        'str1': '8.73',
        'str2': '2.33e-9',
        'str3': '6.e-9',
        'cat1': {
            'type': 'Catalog',
            'col': 0
        },
        'cat2': {
            'type': 'Catalog',
            'col': 1
        },
        'cat3': {
            'type': 'Catalog',
            'num': 1,
            'col': 'float1'
        },
        'cat4': {
            'type': 'Catalog',
            'num': 1,
            'col': 'float2'
        },
        'ran1': {
            'type': 'Random',
            'min': 0.5,
            'max': 3
        },
        'ran2': {
            'type': 'Random',
            'min': -5,
            'max': 0
        },
        'gauss1': {
            'type': 'RandomGaussian',
            'sigma': 1
        },
        'gauss2': {
            'type': 'RandomGaussian',
            'sigma': 3,
            'mean': 4
        },
        'gauss3': {
            'type': 'RandomGaussian',
            'sigma': 1.5,
            'min': -2,
            'max': 2
        },
        'gauss4': {
            'type': 'RandomGaussian',
            'sigma': 0.5,
            'min': 0,
            'max': 0.8
        },
        'gauss5': {
            'type': 'RandomGaussian',
            'sigma': 0.3,
            'mean': 0.5,
            'min': 0,
            'max': 0.5
        },
        'dist1': {
            'type': 'RandomDistribution',
            'function': 'config_input/distribution.txt',
            'interpolant': 'linear'
        },
        'dist2': {
            'type': 'RandomDistribution',
            'function': 'config_input/distribution2.txt',
            'interpolant': 'linear'
        },
        'dist3': {
            'type': 'RandomDistribution',
            'function': 'x*x',
            'x_min': 0.,
            'x_max': 2.0
        },
        'dev1': {
            'type': 'RandomPoisson',
            'mean': 137
        },
        'dev2': {
            'type': 'RandomBinomial',
            'N': 17
        },
        'dev3': {
            'type': 'RandomBinomial',
            'N': 17,
            'p': 0.2
        },
        'dev4': {
            'type': 'RandomWeibull',
            'a': 1.7,
            'b': 4.3
        },
        'dev5': {
            'type': 'RandomGamma',
            'k': 1,
            'theta': 4
        },
        'dev6': {
            'type': 'RandomGamma',
            'k': 1.9,
            'theta': 4.1
        },
        'dev7': {
            'type': 'RandomChi2',
            'n': 17
        },
        'seq1': {
            'type': 'Sequence'
        },
        'seq2': {
            'type': 'Sequence',
            'step': 0.1
        },
        'seq3': {
            'type': 'Sequence',
            'first': 1.5,
            'step': 0.5
        },
        'seq4': {
            'type': 'Sequence',
            'first': 10,
            'step': -2
        },
        'seq5': {
            'type': 'Sequence',
            'first': 1,
            'last': 2.1,
            'repeat': 2
        },
        'list1': {
            'type': 'List',
            'items': [73, 8.9, 3.14]
        },
        'list2': {
            'type': 'List',
            'items':
            [0.6, 1.8, 2.1, 3.7, 4.3, 5.5, 6.1, 7.0, 8.6, 9.3, 10.8, 11.2],
            'index': {
                'type': 'Sequence',
                'first': 10,
                'step': -3
            }
        },
        'dict1': {
            'type': 'Dict',
            'key': 'f'
        },
        'dict2': {
            'type': 'Dict',
            'num': 1,
            'key': 'f'
        },
        'dict3': {
            'type': 'Dict',
            'num': 2,
            'key': 'f'
        },
        'dict4': {
            'type': 'Dict',
            'num': 2,
            'key': 'noise.models.1.gain'
        },
        'sum1': {
            'type': 'Sum',
            'items': [72, '2.33', {
                'type': 'Dict',
                'key': 'f'
            }]
        }
    }

    test_yaml = True
    try:
        galsim.config.ProcessInput(config)
    except:
        # We don't require PyYAML as a dependency, so if this fails, just remove the YAML dict.
        del config['input']['dict'][2]
        galsim.config.ProcessInput(config)
        test_yaml = False

    # Test direct values
    val1 = galsim.config.ParseValue(config, 'val1', config, float)[0]
    np.testing.assert_almost_equal(val1, 9.9)

    val2 = galsim.config.ParseValue(config, 'val2', config, float)[0]
    np.testing.assert_almost_equal(val2, 400)

    # Test conversions from strings
    str1 = galsim.config.ParseValue(config, 'str1', config, float)[0]
    np.testing.assert_almost_equal(str1, 8.73)

    str2 = galsim.config.ParseValue(config, 'str2', config, float)[0]
    np.testing.assert_almost_equal(str2, 2.33e-9)

    str3 = galsim.config.ParseValue(config, 'str3', config, float)[0]
    np.testing.assert_almost_equal(str3, 6.0e-9)

    # Test values read from a Catalog
    cat1 = []
    cat2 = []
    cat3 = []
    cat4 = []
    config['index_key'] = 'file_num'
    for k in range(5):
        config['file_num'] = k
        cat1.append(galsim.config.ParseValue(config, 'cat1', config, float)[0])
        cat2.append(galsim.config.ParseValue(config, 'cat2', config, float)[0])
        cat3.append(galsim.config.ParseValue(config, 'cat3', config, float)[0])
        cat4.append(galsim.config.ParseValue(config, 'cat4', config, float)[0])

    np.testing.assert_array_almost_equal(cat1,
                                         [1.234, 2.345, 3.456, 1.234, 2.345])
    np.testing.assert_array_almost_equal(cat2,
                                         [4.131, -900, 8000, 4.131, -900])
    np.testing.assert_array_almost_equal(cat3,
                                         [1.234, 2.345, 3.456, 1.234, 2.345])
    np.testing.assert_array_almost_equal(cat4,
                                         [4.131, -900, 8000, 4.131, -900])

    # Test values generated from a uniform deviate
    rng = galsim.UniformDeviate(1234)
    config['rng'] = galsim.UniformDeviate(
        1234)  # A second copy starting with the same seed.
    for k in range(6):
        config[
            'obj_num'] = k  # The Random type doesn't use obj_num, but this keeps it
        # from thinking current_val is still current.
        ran1 = galsim.config.ParseValue(config, 'ran1', config, float)[0]
        np.testing.assert_almost_equal(ran1, rng() * 2.5 + 0.5)

        ran2 = galsim.config.ParseValue(config, 'ran2', config, float)[0]
        np.testing.assert_almost_equal(ran2, rng() * 5 - 5)

    # Test values generated from a Gaussian deviate
    for k in range(6):
        config['obj_num'] = k
        gauss1 = galsim.config.ParseValue(config, 'gauss1', config, float)[0]
        gd = galsim.GaussianDeviate(rng, mean=0, sigma=1)
        np.testing.assert_almost_equal(gauss1, gd())

        gauss2 = galsim.config.ParseValue(config, 'gauss2', config, float)[0]
        gd = galsim.GaussianDeviate(rng, mean=4, sigma=3)
        np.testing.assert_almost_equal(gauss2, gd())

        gauss3 = galsim.config.ParseValue(config, 'gauss3', config, float)[0]
        gd = galsim.GaussianDeviate(rng, mean=0, sigma=1.5)
        gd_val = gd()
        while math.fabs(gd_val) > 2:
            gd_val = gd()
        np.testing.assert_almost_equal(gauss3, gd_val)

        gauss4 = galsim.config.ParseValue(config, 'gauss4', config, float)[0]
        gd = galsim.GaussianDeviate(rng, mean=0, sigma=0.5)
        gd_val = math.fabs(gd())
        while gd_val > 0.8:
            gd_val = math.fabs(gd())
        np.testing.assert_almost_equal(gauss4, gd_val)

        gauss5 = galsim.config.ParseValue(config, 'gauss5', config, float)[0]
        gd = galsim.GaussianDeviate(rng, mean=0.5, sigma=0.3)
        gd_val = gd()
        if gd_val > 0.5:
            gd_val = 1 - gd_val
        while gd_val < 0:
            gd_val = gd()
            if gd_val > 0.5:
                gd_val = 1 - gd_val
        np.testing.assert_almost_equal(gauss5, gd_val)

    # Test values generated from a distribution in a file
    dd = galsim.DistDeviate(rng,
                            function='config_input/distribution.txt',
                            interpolant='linear')
    for k in range(6):
        config['obj_num'] = k
        dist1 = galsim.config.ParseValue(config, 'dist1', config, float)[0]
        np.testing.assert_almost_equal(dist1, dd())
    dd = galsim.DistDeviate(rng,
                            function='config_input/distribution2.txt',
                            interpolant='linear')
    for k in range(6):
        config['obj_num'] = k
        dist2 = galsim.config.ParseValue(config, 'dist2', config, float)[0]
        np.testing.assert_almost_equal(dist2, dd())
    dd = galsim.DistDeviate(rng, function=lambda x: x * x, x_min=0., x_max=2.)
    for k in range(6):
        config['obj_num'] = k
        dist3 = galsim.config.ParseValue(config, 'dist3', config, float)[0]
        np.testing.assert_almost_equal(dist3, dd())

    # Test values generated from various other deviates
    for k in range(6):
        config['obj_num'] = k
        dev = galsim.PoissonDeviate(rng, mean=137)
        dev1 = galsim.config.ParseValue(config, 'dev1', config, float)[0]
        np.testing.assert_almost_equal(dev1, dev())

        dev = galsim.BinomialDeviate(rng, N=17)
        dev2 = galsim.config.ParseValue(config, 'dev2', config, float)[0]
        np.testing.assert_almost_equal(dev2, dev())

        dev = galsim.BinomialDeviate(rng, N=17, p=0.2)
        dev3 = galsim.config.ParseValue(config, 'dev3', config, float)[0]
        np.testing.assert_almost_equal(dev3, dev())

        dev = galsim.WeibullDeviate(rng, a=1.7, b=4.3)
        dev4 = galsim.config.ParseValue(config, 'dev4', config, float)[0]
        np.testing.assert_almost_equal(dev4, dev())

        dev = galsim.GammaDeviate(rng, k=1, theta=4)
        dev5 = galsim.config.ParseValue(config, 'dev5', config, float)[0]
        np.testing.assert_almost_equal(dev5, dev())

        dev = galsim.GammaDeviate(rng, k=1.9, theta=4.1)
        dev6 = galsim.config.ParseValue(config, 'dev6', config, float)[0]
        np.testing.assert_almost_equal(dev6, dev())

        dev = galsim.Chi2Deviate(rng, n=17)
        dev7 = galsim.config.ParseValue(config, 'dev7', config, float)[0]
        np.testing.assert_almost_equal(dev7, dev())

    # Test values generated from a Sequence
    seq1 = []
    seq2 = []
    seq3 = []
    seq4 = []
    seq5 = []
    config['index_key'] = 'file_num'
    for k in range(6):
        config['file_num'] = k
        seq1.append(galsim.config.ParseValue(config, 'seq1', config, float)[0])
    config['index_key'] = 'image_num'
    for k in range(6):
        config['image_num'] = k
        seq2.append(galsim.config.ParseValue(config, 'seq2', config, float)[0])
    config['index_key'] = 'obj_num'
    for k in range(6):
        config['obj_num'] = k
        seq3.append(galsim.config.ParseValue(config, 'seq3', config, float)[0])
    config['index_key'] = 'obj_num_in_file'
    config['start_obj_num'] = 10
    for k in range(6):
        config['obj_num'] = k + 10
        seq4.append(galsim.config.ParseValue(config, 'seq4', config, float)[0])
        seq5.append(galsim.config.ParseValue(config, 'seq5', config, float)[0])

    np.testing.assert_array_almost_equal(seq1, [0, 1, 2, 3, 4, 5])
    np.testing.assert_array_almost_equal(seq2, [0, 0.1, 0.2, 0.3, 0.4, 0.5])
    np.testing.assert_array_almost_equal(seq3, [1.5, 2, 2.5, 3, 3.5, 4])
    np.testing.assert_array_almost_equal(seq4, [10, 8, 6, 4, 2, 0])
    np.testing.assert_array_almost_equal(seq5, [1, 1, 2, 2, 1, 1])

    # Test values taken from a List
    list1 = []
    list2 = []
    config['index_key'] = 'obj_num'
    for k in range(5):
        config['obj_num'] = k
        list1.append(
            galsim.config.ParseValue(config, 'list1', config, float)[0])
        list2.append(
            galsim.config.ParseValue(config, 'list2', config, float)[0])

    np.testing.assert_array_almost_equal(list1, [73, 8.9, 3.14, 73, 8.9])
    np.testing.assert_array_almost_equal(list2, [10.8, 7.0, 4.3, 1.8, 10.8])

    # Test values read from a Dict
    dict = []
    dict.append(galsim.config.ParseValue(config, 'dict1', config, float)[0])
    dict.append(galsim.config.ParseValue(config, 'dict2', config, float)[0])
    if test_yaml:
        dict.append(
            galsim.config.ParseValue(config, 'dict3', config, float)[0])
        dict.append(
            galsim.config.ParseValue(config, 'dict4', config, float)[0])
    else:
        dict.append(0.1)
        dict.append(1.9)
    np.testing.assert_array_almost_equal(dict, [23.17, -17.23, 0.1, 1.9])

    sum1 = galsim.config.ParseValue(config, 'sum1', config, float)[0]
    np.testing.assert_almost_equal(sum1, 72 + 2.33 + 23.17)

    t2 = time.time()
    print 'time for %s = %.2f' % (funcname(), t2 - t1)
Ejemplo n.º 13
0
def test_variable_gaussian_noise():
    """Test VariableGaussian random number generator
    """
    # Make a checkerboard image with two values for the variance
    gSigma1 = 17.23
    gSigma2 = 28.55
    var_image = galsim.ImageD(galsim.BoundsI(0, 9, 0, 9))
    coords = np.ogrid[0:10, 0:10]
    var_image.array[(coords[0] + coords[1]) % 2 == 1] = gSigma1**2
    var_image.array[(coords[0] + coords[1]) % 2 == 0] = gSigma2**2
    print('var_image.array = ', var_image.array)

    g = galsim.GaussianDeviate(testseed, sigma=1.)
    vgResult = np.empty((10, 10))
    g.generate(vgResult)
    vgResult *= np.sqrt(var_image.array)

    # Test filling an image
    vgn = galsim.VariableGaussianNoise(galsim.BaseDeviate(testseed), var_image)
    testimage = galsim.ImageD(10, 10)
    testimage.addNoise(vgn)
    np.testing.assert_array_almost_equal(
        testimage.array,
        vgResult,
        precision,
        err_msg=
        "VariableGaussianNoise applied to Images does not reproduce expected sequence"
    )

    # Test filling an image with Fortran ordering
    vgn.rng.seed(testseed)
    testimage = galsim.ImageD(np.zeros((10, 10)).T)
    testimage.addNoise(vgn)
    np.testing.assert_array_almost_equal(
        testimage.array,
        vgResult,
        precision,
        err_msg=
        "Wrong VariableGaussian noise generated for Fortran-ordered Image")

    # Check var_image property
    np.testing.assert_almost_equal(
        vgn.var_image.array,
        var_image.array,
        precision,
        err_msg="VariableGaussianNoise var_image returns wrong var_image")

    # Check that the noise model really does produce this variance.
    big_var_image = galsim.ImageD(galsim.BoundsI(0, 2047, 0, 2047))
    big_coords = np.ogrid[0:2048, 0:2048]
    mask1 = (big_coords[0] + big_coords[1]) % 2 == 0
    mask2 = (big_coords[0] + big_coords[1]) % 2 == 1
    big_var_image.array[mask1] = gSigma1**2
    big_var_image.array[mask2] = gSigma2**2
    big_vgn = galsim.VariableGaussianNoise(galsim.BaseDeviate(testseed),
                                           big_var_image)

    big_im = galsim.Image(2048, 2048, dtype=float)
    big_im.addNoise(big_vgn)
    var = np.var(big_im.array)
    print('variance = ', var)
    print('getVar = ', big_vgn.var_image.array.mean())
    np.testing.assert_almost_equal(
        var,
        big_vgn.var_image.array.mean(),
        1,
        err_msg=
        'Realized variance for VariableGaussianNoise did not match var_image')

    # Check realized variance in each mask
    print('rms1 = ', np.std(big_im.array[mask1]))
    print('rms2 = ', np.std(big_im.array[mask2]))
    np.testing.assert_almost_equal(np.std(big_im.array[mask1]),
                                   gSigma1,
                                   decimal=1)
    np.testing.assert_almost_equal(np.std(big_im.array[mask2]),
                                   gSigma2,
                                   decimal=1)

    # Check that VariableGaussianNoise adds to the image, not overwrites the image.
    gal = galsim.Exponential(half_light_radius=2.3, flux=1.e4)
    gal.drawImage(image=big_im)
    big_vgn.rng.seed(testseed)
    big_im.addNoise(big_vgn)
    gal.withFlux(-1.e4).drawImage(image=big_im, add_to_image=True)
    var = np.var(big_im.array)
    np.testing.assert_almost_equal(
        var,
        big_vgn.var_image.array.mean(),
        1,
        err_msg=
        'VariableGaussianNoise wrong when already an object drawn on the image'
    )

    # Check picklability
    do_pickle(vgn, lambda x: (x.rng.serialize(), x.var_image))
    do_pickle(vgn, drawNoise)
    do_pickle(vgn)

    # Check copy, eq and ne
    vgn2 = galsim.VariableGaussianNoise(vgn.rng.duplicate(), var_image)
    vgn3 = vgn.copy()
    vgn4 = vgn.copy(rng=galsim.BaseDeviate(11))
    vgn5 = galsim.VariableGaussianNoise(vgn.rng, 2. * var_image)
    assert vgn == vgn2
    assert vgn == vgn3
    assert vgn != vgn4
    assert vgn != vgn5
    assert vgn.rng.raw() == vgn2.rng.raw()
    assert vgn == vgn2
    assert vgn == vgn3
    vgn.rng.raw()
    assert vgn != vgn2
    assert vgn == vgn3

    assert_raises(TypeError, vgn.applyTo, 23)
    assert_raises(ValueError, vgn.applyTo, galsim.ImageF(3, 3))
    assert_raises(galsim.GalSimError, vgn.getVariance)
    assert_raises(galsim.GalSimError, vgn.withVariance, 23)
    assert_raises(galsim.GalSimError, vgn.withScaledVariance, 23)
Ejemplo n.º 14
0
def test_dep_random():
    """Test the deprecated methods in galsim/deprecated/random.py
    """
    rng = galsim.BaseDeviate(123)

    gd = galsim.GaussianDeviate(rng, mean=0.5, sigma=1.7)
    np.testing.assert_almost_equal(gd.getMean(), 0.5)
    np.testing.assert_almost_equal(gd.getSigma(), 1.7)

    check_dep(gd.setMean, 0.9)
    np.testing.assert_almost_equal(gd.getMean(), 0.9)
    np.testing.assert_almost_equal(gd.getSigma(), 1.7)

    check_dep(gd.setSigma, 2.3)
    np.testing.assert_almost_equal(gd.getMean(), 0.9)
    np.testing.assert_almost_equal(gd.getSigma(), 2.3)

    bd = galsim.BinomialDeviate(rng, N=7, p=0.7)
    np.testing.assert_almost_equal(bd.getN(), 7)
    np.testing.assert_almost_equal(bd.getP(), 0.7)

    check_dep(bd.setN, 9)
    np.testing.assert_almost_equal(bd.getN(), 9)
    np.testing.assert_almost_equal(bd.getP(), 0.7)

    check_dep(bd.setP, 0.3)
    np.testing.assert_almost_equal(bd.getN(), 9)
    np.testing.assert_almost_equal(bd.getP(), 0.3)

    pd = galsim.PoissonDeviate(rng, mean=0.5)
    np.testing.assert_almost_equal(pd.getMean(), 0.5)

    check_dep(pd.setMean, 0.9)
    np.testing.assert_almost_equal(pd.getMean(), 0.9)

    wd = galsim.WeibullDeviate(rng, a=0.5, b=1.7)
    np.testing.assert_almost_equal(wd.getA(), 0.5)
    np.testing.assert_almost_equal(wd.getB(), 1.7)

    check_dep(wd.setA, 0.9)
    np.testing.assert_almost_equal(wd.getA(), 0.9)
    np.testing.assert_almost_equal(wd.getB(), 1.7)

    check_dep(wd.setB, 2.3)
    np.testing.assert_almost_equal(wd.getA(), 0.9)
    np.testing.assert_almost_equal(wd.getB(), 2.3)

    gd = galsim.GammaDeviate(rng, k=0.5, theta=1.7)
    np.testing.assert_almost_equal(gd.getK(), 0.5)
    np.testing.assert_almost_equal(gd.getTheta(), 1.7)

    check_dep(gd.setK, 0.9)
    np.testing.assert_almost_equal(gd.getK(), 0.9)
    np.testing.assert_almost_equal(gd.getTheta(), 1.7)

    check_dep(gd.setTheta, 2.3)
    np.testing.assert_almost_equal(gd.getK(), 0.9)
    np.testing.assert_almost_equal(gd.getTheta(), 2.3)

    cd = galsim.Chi2Deviate(rng, n=5)
    np.testing.assert_almost_equal(cd.getN(), 5)

    check_dep(cd.setN, 9)
    np.testing.assert_almost_equal(cd.getN(), 9)
Ejemplo n.º 15
0
    def build_file(seed, file_name, mass, nobj):
        """A function that does all the work to build a single file.
           Returns the total time taken.
        """
        t1 = time.time()

        # Build the image onto which we will draw the galaxies.
        full_image = galsim.ImageF(image_size, image_size)

        # The "true" center of the image is allowed to be halfway between two pixels, as is the
        # case for even-sized images.  full_image.bounds.center() is an integer position,
        # which would be 1/2 pixel up and to the right of the true center in this case.
        im_center = full_image.bounds.trueCenter()

        # For the WCS, this time we use UVFunction, which lets you define arbitrary u(x,y)
        # and v(x,y) functions.  We use a simple cubic radial function to create a
        # pincushion distortion.  This is a typical kind of telescope distortion, although
        # we exaggerate the magnitude of the effect to make it more apparent.
        # The pixel size in the center of the image is 0.05, but near the corners (r=362),
        # the pixel size is approximately 0.075, which is much more distortion than is
        # normally present in typical telescopes.  But it makes the effect of the variable
        # pixel area obvious when you look at the weight image in the output files.
        ufunc1 = lambda x, y: 0.05 * x * (1. + 2.e-6 * (x**2 + y**2))
        vfunc1 = lambda x, y: 0.05 * y * (1. + 2.e-6 * (x**2 + y**2))

        # It's not required to provide the inverse functions.  However, if we don't, then
        # you will only be able to do toWorld operations, not the inverse toImage.
        # The inverse function does not have to be exact either.  For example, you could provide
        # a function that does some kind of iterative solution to whatever accuracy you care
        # about.  But in this case, we can do the exact inverse.
        #
        # Let w = sqrt(u**2 + v**2) and r = sqrt(x**2 + y**2).  Then the solutions are:
        # x = (u/w) r and y = (u/w) r, and we use Cardano's method to solve for r given w:
        # See http://en.wikipedia.org/wiki/Cubic_function#Cardano.27s_method
        #
        # w = 0.05 r + 2.e-6 * 0.05 * r**3
        # r = 100 * ( ( 5 sqrt(w**2 + 5.e3/27) + 5 w )**(1./3.) -
        #           - ( 5 sqrt(w**2 + 5.e3/27) - 5 w )**(1./3.) )

        def xfunc1(u, v):
            import math
            wsq = u * u + v * v
            if wsq == 0.:
                return 0.
            else:
                w = math.sqrt(wsq)
                temp = 5. * math.sqrt(wsq + 5.e3 / 27)
                r = 100. * ((temp + 5 * w)**(1. / 3.) -
                            (temp - 5 * w)**(1. / 3))
                return u * r / w

        def yfunc1(u, v):
            import math
            wsq = u * u + v * v
            if wsq == 0.:
                return 0.
            else:
                w = math.sqrt(wsq)
                temp = 5. * math.sqrt(wsq + 5.e3 / 27)
                r = 100. * ((temp + 5 * w)**(1. / 3.) -
                            (temp - 5 * w)**(1. / 3))
                return v * r / w

        # You could pass the above functions to UVFunction, and normally we would do that.
        # The only down side to doing so is that the specification of the WCS in the FITS
        # file is rather ugly.  GalSim is able to turn the python byte code into strings,
        # but they are basically a really ugly mess of random-looking characters.  GalSim
        # will be able to read it back in, but human readers will have no idea what WCS
        # function was used.  To see what they look like, uncomment this line and comment
        # out the later wcs line.
        #wcs = galsim.UVFunction(ufunc1, vfunc1, xfunc1, yfunc1, origin=im_center)

        # If you provide the functions as strings, then those strings will be preserved
        # in the FITS header in a form that is more legible to human readers.
        # It also has the extra benefit of matching the output from demo9.yaml, which we
        # always try to do.  The config file has no choice but to specify the functions
        # as strings.

        ufunc = '0.05 * x * (1. + 2.e-6 * (x**2 + y**2))'
        vfunc = '0.05 * y * (1. + 2.e-6 * (x**2 + y**2))'
        xfunc = (
            '( lambda w: ( 0 if w==0 else ' +
            '100.*u/w*(( 5*(w**2 + 5.e3/27.)**0.5 + 5*w )**(1./3.) - ' +
            '( 5*(w**2 + 5.e3/27.)**0.5 - 5*w )**(1./3.))))( (u**2+v**2)**0.5 )'
        )
        yfunc = (
            '( lambda w: ( 0 if w==0 else ' +
            '100.*v/w*(( 5*(w**2 + 5.e3/27.)**0.5 + 5*w )**(1./3.) - ' +
            '( 5*(w**2 + 5.e3/27.)**0.5 - 5*w )**(1./3.))))( (u**2+v**2)**0.5 )'
        )

        # The origin parameter defines where on the image should be considered (x,y) = (0,0)
        # in the WCS functions.
        wcs = galsim.UVFunction(ufunc, vfunc, xfunc, yfunc, origin=im_center)

        # Assign this wcs to full_image
        full_image.wcs = wcs

        # The weight image will hold the inverse variance for each pixel.
        # We can set the wcs directly on construction with the wcs parameter.
        weight_image = galsim.ImageF(image_size, image_size, wcs=wcs)

        # It is common for astrometric images to also have a bad pixel mask.  We don't have any
        # defect simulation currently, so our bad pixel masks are currently all zeros.
        # But someday, we plan to add defect functionality to GalSim, at which point, we'll
        # be able to mark those defects on a bad pixel mask.
        # Note: the S in ImageS means to use "short int" for the data type.
        # This is a typical choice for a bad pixel image.
        badpix_image = galsim.ImageS(image_size, image_size, wcs=wcs)

        # We also draw a PSF image at the location of every galaxy.  This isn't normally done,
        # and since some of the PSFs overlap, it's not necessarily so useful to have this kind
        # of image.  But in this case, it's fun to look at the psf image, especially with
        # something like log scaling in ds9 to see how crazy an aberrated OpticalPSF with
        # struts can look when there is no atmospheric component to blur it out.
        psf_image = galsim.ImageF(image_size, image_size, wcs=wcs)

        # Setup the NFWHalo stuff:
        nfw = galsim.NFWHalo(mass=mass,
                             conc=nfw_conc,
                             redshift=nfw_z_halo,
                             omega_m=omega_m,
                             omega_lam=omega_lam)
        # Note: the last two are optional.  If they are omitted, then (omega_m=0.3, omega_lam=0.7)
        # are actually the defaults.  If you only specify one of them, the other is set so that
        # the total is 1.  But you can define both values so that the total is not 1 if you want.
        # Radiation is assumed to be zero and dark energy equation of state w = -1.
        # If you want to include either radiation or more complicated dark energy models,
        # you can define your own cosmology class that defines the functions a(z), E(a), and
        # Da(z_source, z_lens).  Then you can pass this to NFWHalo as a `cosmo` parameter.

        # Make the PSF profile outside the loop to minimize the (significant) OpticalPSF
        # construction overhead.
        psf = galsim.OpticalPSF(lam_over_diam=psf_lam_over_D,
                                obscuration=psf_obsc,
                                nstruts=psf_nstruts,
                                strut_thick=psf_strut_thick,
                                strut_angle=psf_strut_angle,
                                defocus=psf_defocus,
                                astig1=psf_astig1,
                                astig2=psf_astig2,
                                coma1=psf_coma1,
                                coma2=psf_coma2,
                                trefoil1=psf_trefoil1,
                                trefoil2=psf_trefoil2)

        for k in range(nobj):

            # Initialize the random number generator we will be using for this object:
            rng = galsim.UniformDeviate(seed + k)

            # Determine where this object is going to go.
            # We choose points randomly within a donut centered at the center of the main image
            # in order to avoid placing galaxies too close to the halo center where the lensing
            # is not weak.  We use an inner radius of 3 arcsec and an outer radius of 12 arcsec,
            # which takes us essentially to the edge of the image.
            radius = 12
            inner_radius = 3
            max_rsq = radius**2
            min_rsq = inner_radius**2
            while True:  # (This is essentially a do..while loop.)
                x = (2. * rng() - 1) * radius
                y = (2. * rng() - 1) * radius
                rsq = x**2 + y**2
                if rsq >= min_rsq and rsq <= max_rsq: break
            pos = galsim.PositionD(x, y)

            # We also need the position in pixels to determine where to place the postage
            # stamp on the full image.
            image_pos = wcs.toImage(pos)

            # For even-sized postage stamps, the nominal center (returned by stamp.bounds.center())
            # cannot be at the true center (returned by stamp.bounds.trueCenter()) of the postage
            # stamp, since the nominal center values have to be integers.  Thus, the nominal center
            # is 1/2 pixel up and to the right of the true center.
            # If we used odd-sized postage stamps, we wouldn't need to do this.
            x_nominal = image_pos.x + 0.5
            y_nominal = image_pos.y + 0.5

            # Get the integer values of these which will be the actual nominal center of the
            # postage stamp image.
            ix_nominal = int(math.floor(x_nominal + 0.5))
            iy_nominal = int(math.floor(y_nominal + 0.5))

            # The remainder will be accounted for in an offset when we draw.
            dx = x_nominal - ix_nominal
            dy = y_nominal - iy_nominal
            offset = galsim.PositionD(dx, dy)

            # Determine the random values for the galaxy:
            flux = rng() * (gal_flux_max - gal_flux_min) + gal_flux_min
            hlr = rng() * (gal_hlr_max - gal_hlr_min) + gal_hlr_min
            gd = galsim.GaussianDeviate(rng, sigma=gal_eta_rms)
            eta1 = gd(
            )  # Unlike g or e, large values of eta are valid, so no need to cutoff.
            eta2 = gd()

            # Make the galaxy profile with these values:
            gal = galsim.Exponential(half_light_radius=hlr, flux=flux)
            gal = gal.shear(eta1=eta1, eta2=eta2)

            # Now apply the appropriate lensing effects for this position from
            # the NFW halo mass.
            try:
                g1, g2 = nfw.getShear(pos, nfw_z_source)
                nfw_shear = galsim.Shear(g1=g1, g2=g2)
            except:
                # This shouldn't happen, since we exclude the inner 10 arcsec, but it's a
                # good idea to use the try/except block here anyway.
                import warnings
                warnings.warn(
                    "Warning: NFWHalo shear is invalid -- probably strong lensing!  "
                    + "Using shear = 0.")
                nfw_shear = galsim.Shear(g1=0, g2=0)

            nfw_mu = nfw.getMagnification(pos, nfw_z_source)
            if nfw_mu < 0:
                import warnings
                warnings.warn(
                    "Warning: mu < 0 means strong lensing!  Using mu=25.")
                nfw_mu = 25
            elif nfw_mu > 25:
                import warnings
                warnings.warn(
                    "Warning: mu > 25 means strong lensing!  Using mu=25.")
                nfw_mu = 25

            # Calculate the total shear to apply
            # Since shear addition is not commutative, it is worth pointing out that
            # the order is in the sense that the second shear is applied first, and then
            # the first shear.  i.e. The field shear is taken to be behind the cluster.
            # Kind of a cosmic shear contribution between the source and the cluster.
            # However, this is not quite the same thing as doing:
            #     gal.shear(field_shear).shear(nfw_shear)
            # since the shear addition ignores the rotation that would occur when doing the
            # above lines.  This is normally ok, because the rotation is not observable, but
            # it is worth keeping in mind.
            total_shear = nfw_shear + field_shear

            # Apply the magnification and shear to the galaxy
            gal = gal.magnify(nfw_mu)
            gal = gal.shear(total_shear)

            # Build the final object
            final = galsim.Convolve([psf, gal])

            # Draw the stamp image
            # To draw the image at a position other than the center of the image, you can
            # use the offset parameter, which applies an offset in pixels relative to the
            # center of the image.
            # We also need to provide the local wcs at the current position.
            local_wcs = wcs.local(image_pos)
            stamp = final.drawImage(wcs=local_wcs, offset=offset)

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

            # Find overlapping bounds
            bounds = stamp.bounds & full_image.bounds
            full_image[bounds] += stamp[bounds]

            # Also draw the PSF
            psf_stamp = galsim.ImageF(
                stamp.bounds)  # Use same bounds as galaxy stamp
            psf.drawImage(psf_stamp, wcs=local_wcs, offset=offset)
            psf_image[bounds] += psf_stamp[bounds]

        # Add Poisson noise to the full image
        # Note: The normal calculation of Poission noise isn't quite correct right now.
        # The pixel area is variable, which means the amount of sky flux that enters each
        # pixel is also variable.  The wcs classes have a function `makeSkyImage` which
        # will fill an image with the correct amount of sky flux given the sky level
        # in units of ADU/arcsec^2.  We use the weight image as our work space for this.
        wcs.makeSkyImage(weight_image, sky_level)

        # Add this to the current full_image (temporarily).
        full_image += weight_image

        # Add Poisson noise, given the current full_image.
        # Going to the next seed isn't really required, but it matches the behavior of the
        # config parser, so doing this will result in identical output files.
        # If you didn't care about that, you could instead construct this as a continuation
        # of the last RNG from the above loop
        rng = galsim.BaseDeviate(seed + nobj)
        full_image.addNoise(galsim.PoissonNoise(rng))

        # Subtract the sky back off.
        full_image -= weight_image

        # The weight image is nominally the inverse variance of the pixel noise.  However, it is
        # common to exclude the Poisson noise from the objects themselves and only include the
        # noise from the sky photons.  The variance of the noise is just the sky level, which is
        # what is currently in the weight_image.  (If we wanted to include the variance from the
        # objects too, then we could use the full_image before we added the PoissonNoise to it.)
        # So all we need to do now is to invert the values in weight_image.
        weight_image.invertSelf()

        # Write the file to disk:
        galsim.fits.writeMulti(
            [full_image, badpix_image, weight_image, psf_image], file_name)

        t2 = time.time()
        return t2 - t1
Ejemplo n.º 16
0
def test_gaussian_noise():
    """Test Gaussian random number generator
    """
    gSigma = 17.23
    g = galsim.GaussianDeviate(testseed, sigma=gSigma)
    gResult = np.empty((10, 10))
    g.generate(gResult)
    noise = galsim.DeviateNoise(g)

    # Test filling an image
    testimage = galsim.ImageD(10, 10)
    noise.rng.seed(testseed)
    testimage.addNoise(noise)
    np.testing.assert_array_almost_equal(
        testimage.array,
        gResult,
        precision,
        err_msg=
        'Wrong Gaussian random number sequence generated when applied to image.'
    )

    # Test filling a single-precision image
    noise.rng.seed(testseed)
    testimage = galsim.ImageF(10, 10)
    testimage.addNoise(noise)
    np.testing.assert_array_almost_equal(
        testimage.array,
        gResult,
        precisionF,
        err_msg=
        'Wrong Gaussian random number sequence generated when applied to ImageF.'
    )

    # GaussianNoise is equivalent, but no mean allowed.
    gn = galsim.GaussianNoise(galsim.BaseDeviate(testseed), sigma=gSigma)
    testimage = galsim.ImageD(10, 10)
    testimage.addNoise(gn)
    np.testing.assert_array_almost_equal(
        testimage.array,
        gResult,
        precision,
        err_msg=
        "GaussianNoise applied to Images does not reproduce expected sequence")

    # Test filling an image with Fortran ordering
    gn.rng.seed(testseed)
    testimage = galsim.ImageD(np.zeros((10, 10)).T)
    testimage.addNoise(gn)
    np.testing.assert_array_almost_equal(
        testimage.array,
        gResult,
        precision,
        err_msg="Wrong Gaussian noise generated for Fortran-ordered Image")

    # Check GaussianNoise variance:
    np.testing.assert_almost_equal(
        gn.getVariance(),
        gSigma**2,
        precision,
        err_msg="GaussianNoise getVariance returns wrong variance")
    np.testing.assert_almost_equal(
        gn.sigma,
        gSigma,
        precision,
        err_msg="GaussianNoise sigma returns wrong value")

    # Check that the noise model really does produce this variance.
    big_im = galsim.Image(2048, 2048, dtype=float)
    gn.rng.seed(testseed)
    big_im.addNoise(gn)
    var = np.var(big_im.array)
    print('variance = ', var)
    print('getVar = ', gn.getVariance())
    np.testing.assert_almost_equal(
        var,
        gn.getVariance(),
        1,
        err_msg=
        'Realized variance for GaussianNoise did not match getVariance()')

    # Check that GaussianNoise adds to the image, not overwrites the image.
    gal = galsim.Exponential(half_light_radius=2.3, flux=1.e4)
    gal.drawImage(image=big_im)
    gn.rng.seed(testseed)
    big_im.addNoise(gn)
    gal.withFlux(-1.e4).drawImage(image=big_im, add_to_image=True)
    var = np.var(big_im.array)
    np.testing.assert_almost_equal(
        var,
        gn.getVariance(),
        1,
        err_msg='GaussianNoise wrong when already an object drawn on the image'
    )

    # Check that DeviateNoise adds to the image, not overwrites the image.
    gal.drawImage(image=big_im)
    gn.rng.seed(testseed)
    big_im.addNoise(gn)
    gal.withFlux(-1.e4).drawImage(image=big_im, add_to_image=True)
    var = np.var(big_im.array)
    np.testing.assert_almost_equal(
        var,
        gn.getVariance(),
        1,
        err_msg='DeviateNoise wrong when already an object drawn on the image')

    # Check withVariance
    gn = gn.withVariance(9.)
    np.testing.assert_almost_equal(
        gn.getVariance(),
        9,
        precision,
        err_msg="GaussianNoise withVariance results in wrong variance")
    np.testing.assert_almost_equal(
        gn.sigma,
        3.,
        precision,
        err_msg="GaussianNoise withVariance results in wrong sigma")

    # Check withScaledVariance
    gn = gn.withScaledVariance(4.)
    np.testing.assert_almost_equal(
        gn.getVariance(),
        36.,
        precision,
        err_msg="GaussianNoise withScaledVariance results in wrong variance")
    np.testing.assert_almost_equal(
        gn.sigma,
        6.,
        precision,
        err_msg="GaussianNoise withScaledVariance results in wrong sigma")

    # Check arithmetic
    gn = gn.withVariance(0.5)
    gn2 = gn * 3
    np.testing.assert_almost_equal(
        gn2.getVariance(),
        1.5,
        precision,
        err_msg="GaussianNoise gn*3 results in wrong variance")
    np.testing.assert_almost_equal(
        gn.getVariance(),
        0.5,
        precision,
        err_msg="GaussianNoise gn*3 results in wrong variance for original gn")
    gn2 = 5 * gn
    np.testing.assert_almost_equal(
        gn2.getVariance(),
        2.5,
        precision,
        err_msg="GaussianNoise 5*gn results in wrong variance")
    np.testing.assert_almost_equal(
        gn.getVariance(),
        0.5,
        precision,
        err_msg="GaussianNoise 5*gn results in wrong variance for original gn")
    gn2 = gn / 2
    np.testing.assert_almost_equal(
        gn2.getVariance(),
        0.25,
        precision,
        err_msg="GaussianNoise gn/2 results in wrong variance")
    np.testing.assert_almost_equal(
        gn.getVariance(),
        0.5,
        precision,
        err_msg="GaussianNoise 5*gn results in wrong variance for original gn")
    gn *= 3
    np.testing.assert_almost_equal(
        gn.getVariance(),
        1.5,
        precision,
        err_msg="GaussianNoise gn*=3 results in wrong variance")
    gn /= 2
    np.testing.assert_almost_equal(
        gn.getVariance(),
        0.75,
        precision,
        err_msg="GaussianNoise gn/=2 results in wrong variance")

    # Check starting with GaussianNoise()
    gn2 = galsim.GaussianNoise()
    gn2 = gn2.withVariance(9.)
    np.testing.assert_almost_equal(
        gn2.getVariance(),
        9,
        precision,
        err_msg="GaussianNoise().withVariance results in wrong variance")
    np.testing.assert_almost_equal(
        gn2.sigma,
        3.,
        precision,
        err_msg="GaussianNoise().withVariance results in wrong sigma")

    gn2 = galsim.GaussianNoise()
    gn2 = gn2.withScaledVariance(4.)
    np.testing.assert_almost_equal(
        gn2.getVariance(),
        4.,
        precision,
        err_msg="GaussianNoise().withScaledVariance results in wrong variance")
    np.testing.assert_almost_equal(
        gn2.sigma,
        2.,
        precision,
        err_msg="GaussianNoise().withScaledVariance results in wrong sigma")

    # Check picklability
    do_pickle(gn, lambda x: (x.rng.serialize(), x.sigma))
    do_pickle(gn, drawNoise)
    do_pickle(gn)

    # Check copy, eq and ne
    gn = gn.withVariance(gSigma**2)
    gn2 = galsim.GaussianNoise(gn.rng.duplicate(), gSigma)
    gn3 = gn.copy()
    gn4 = gn.copy(rng=galsim.BaseDeviate(11))
    gn5 = galsim.GaussianNoise(gn.rng, 2. * gSigma)
    assert gn == gn2
    assert gn == gn3
    assert gn != gn4
    assert gn != gn5
    assert gn.rng.raw() == gn2.rng.raw()
    assert gn == gn2
    assert gn == gn3
    gn.rng.raw()
    assert gn != gn2
    assert gn == gn3
Ejemplo n.º 17
0
def make_default_input():

    # Set the PSF catalogue values
    moffat_beta = np.zeros(NOBJECTS) + MOFFAT_BETA
    moffat_fwhm = np.zeros(NOBJECTS) + MOFFAT_FWHM
    moffat_e1 = np.zeros(NOBJECTS) + MOFFAT_E1
    moffat_e2 = np.zeros(NOBJECTS) + MOFFAT_E2
    moffat_trunc = np.zeros(NOBJECTS) + MOFFAT_TRUNCATIONFWHM * MOFFAT_FWHM
    # Then set the exponential disc catalogue fixed values
    exponential_hlr = np.zeros(NOBJECTS) + EXPONENTIAL_HLR
    # Then set the dVc bulge catalogue fixed values
    devaucouleurs_hlr = np.zeros(NOBJECTS) + DEVAUCOULEURS_HLR
    # Then set up the Gaussian RNG for making the ellipticity values
    urng = galsim.UniformDeviate(RNG_SEED)
    edist = galsim.GaussianDeviate(urng,
                                   sigma=EXPONENTIAL_DEVAUCOULEURS_SIGMA_E)
    # Slightly hokey way of making vectors of Gaussian deviates, using images... No direct NumPy
    # array-filling with galsim RNGs at the moment.
    #
    # In GREAT08 these galaxy ellipticies were made in rotated pairs to reduce shape noise, but for
    # this illustrative default file we do not do this.
    ime1 = galsim.ImageD(NOBJECTS, 1)
    ime1.addNoise(edist)
    exponential_e1 = ime1.array.flatten()
    ime2 = galsim.ImageD(NOBJECTS, 1)
    ime2.addNoise(edist)
    exponential_e2 = ime2.array.flatten()
    # Make galaxies co-elliptical
    devaucouleurs_e1 = exponential_e1
    devaucouleurs_e2 = exponential_e2

    # Add a centroid shift in drawn uniform randomly from the unit circle around (0., 0.)
    dx = np.empty(NOBJECTS)
    dy = np.empty(NOBJECTS)
    for i in xrange(NOBJECTS):
        # Apply a random centroid shift:
        rsq = 2 * GAL_CENTROID_SHIFT_RADIUS_SQUARED
        while (rsq > GAL_CENTROID_SHIFT_RADIUS_SQUARED):
            dx[i] = (2. * urng() - 1.) * GAL_CENTROID_SHIFT_RADIUS
            dy[i] = (2. * urng() - 1.) * GAL_CENTROID_SHIFT_RADIUS
            rsq = dx[i]**2 + dy[i]**2

    # Then write this to file
    path, modfile = os.path.split(__file__)
    outfile = os.path.join(path, "galsim_default_input.asc")
    # Make a nice header with the default fields described
    header = ("# psf.beta  psf.fwhm  psf.e1  psf.e2  psf.trunc" +
              "  disk.hlr  disk.e1  disk.e2" +
              "  bulge.hlr  bulge.e1  bulge.e2" +
              "  gal.shift.dx  gal.shift.dy \n")
    # Open the file and output the columns in the correct order, row-by-row
    output = open(outfile, "w")
    output.write(
        "#  galsim_default_input.asc : illustrative default input catalog for GalSim\n"
    )
    output.write("#\n")
    output.write(header)
    for i in xrange(NOBJECTS):
        outline = (" %6.2f  %6.2f  %7.3f  %7.3f  %6.2f  %6.2f  %14.7f  %14.7f "+
                   "%6.2f  %14.7f  %14.7f  %14.7f  %14.7f\n") % \
            (moffat_beta[i], moffat_fwhm[i], moffat_e1[i], moffat_e2[i], moffat_trunc[i],
             exponential_hlr[i], exponential_e1[i], exponential_e2[i],
             devaucouleurs_hlr[i], devaucouleurs_e1[i], devaucouleurs_e2[i], dx[i], dy[i])
        output.write(outline)
    output.close()
Ejemplo n.º 18
0
                convGalaxyImg = convGalaxy.draw(dx=pixelScale)

                # More noise realizations?
                for invsnind in range(len(invSN)):
                    print "Beginning inverse S/N of ", invSN[invsnind]
                    if invSN[invsnind] > 0.0:
                        # Choose Gaussian sigma per pixel based on GREAT08-style S/N definition
                        gaussSig = invSN[invsnind] * np.sqrt(
                            np.sum(convGalaxyImg.array**(2.0)))

                        # Add noise the appropriate number of times, and write each one to file
                        for iRealization in range(nRealization[invsnind]):
                            tmpImg = convGalaxyImg.copy()
                            tmpImg.addNoise(
                                galsim.GaussianDeviate(rng,
                                                       mean=0.0,
                                                       sigma=gaussSig))
                            outFile = outDir + ('BT%5.3f.' % bt)
                            outFile += 'bulgeellip%5.3f.' % bell
                            outFile += 'diskellip%5.3f.' % dell
                            outFile += 'diskRe%5.3f.' % diskRe[dreind]
                            outFile += 'invSNR%5.3f.' % invSN[invsnind]
                            outFile += 'image%02d.fits' % iRealization
                            tmpImg.write(outFile, clobber=True)
                            print 'Wrote image to file %s' % outFile
                    else:
                        # Just write to file without adding noise
                        outFile = outDir + 'BT%5.3f.' % bt
                        outFile += 'bulgeellip%5.3f.' % bell
                        outFile += 'diskellip%5.3f.' % dell
                        outFile += 'diskRe%5.3f.' % diskRe[dreind]
Ejemplo n.º 19
0
 def __init__(self, sigma, rng):
     self.ellip_sigma = sigma
     self.ud = rng
     self.gd = galsim.GaussianDeviate(self.ud, sigma=self.ellip_sigma)
Ejemplo n.º 20
0
def test_float_value():
    """Test various ways to generate a float value
    """
    import time
    t1 = time.time()

    config = {
        'input' : { 'catalog' : { 'dir' : 'config_input', 'file_name' : 'catalog.txt' } },

        'val1' : 9.9,
        'val2' : int(400),
        'str1' : '8.73',
        'str2' : '2.33e-9',
        'str3' : '6.e-9', 
        'cat1' : { 'type' : 'InputCatalog' , 'col' : 0 },
        'cat2' : { 'type' : 'InputCatalog' , 'col' : 1 },
        'ran1' : { 'type' : 'Random', 'min' : 0.5, 'max' : 3 },
        'ran2' : { 'type' : 'Random', 'min' : -5, 'max' : 0 },
        'gauss1' : { 'type' : 'RandomGaussian', 'sigma' : 1 },
        'gauss2' : { 'type' : 'RandomGaussian', 'sigma' : 3, 'mean' : 4 },
        'gauss3' : { 'type' : 'RandomGaussian', 'sigma' : 1.5, 'min' : -2, 'max' : 2 },
        'gauss4' : { 'type' : 'RandomGaussian', 'sigma' : 0.5, 'min' : 0, 'max' : 0.8 },
        'gauss5' : { 'type' : 'RandomGaussian',
                     'sigma' : 0.3, 'mean' : 0.5, 'min' : 0, 'max' : 0.5 },
        'dist1' : { 'type' : 'RandomDistribution', 'function' : 'config_input/distribution.txt', 
                    'interpolant' : 'linear' },
        'dist2' : { 'type' : 'RandomDistribution', 'function' : 'config_input/distribution2.txt', 
                    'interpolant' : 'linear' },
        'dist3' : { 'type' : 'RandomDistribution', 'function' : 'x*x', 
                    'x_min' : 0., 'x_max' : 2.0 },
        'seq1' : { 'type' : 'Sequence' },
        'seq2' : { 'type' : 'Sequence', 'step' : 0.1 },
        'seq3' : { 'type' : 'Sequence', 'first' : 1.5, 'step' : 0.5 },
        'seq4' : { 'type' : 'Sequence', 'first' : 10, 'step' : -2 },
        'seq5' : { 'type' : 'Sequence', 'first' : 1, 'last' : 2.1, 'repeat' : 2 },
        'list1' : { 'type' : 'List', 'items' : [ 73, 8.9, 3.14 ] },
        'list2' : { 'type' : 'List',
                    'items' : [ 0.6, 1.8, 2.1, 3.7, 4.3, 5.5, 6.1, 7.0, 8.6, 9.3, 10.8, 11.2 ],
                    'index' : { 'type' : 'Sequence', 'first' : 10, 'step' : -3 } }
    }

    galsim.config.ProcessInput(config)

    # Test direct values
    val1 = galsim.config.ParseValue(config,'val1',config, float)[0]
    np.testing.assert_almost_equal(val1, 9.9)

    val2 = galsim.config.ParseValue(config,'val2',config, float)[0]
    np.testing.assert_almost_equal(val2, 400)

    # Test conversions from strings
    str1 = galsim.config.ParseValue(config,'str1',config, float)[0]
    np.testing.assert_almost_equal(str1, 8.73)

    str2 = galsim.config.ParseValue(config,'str2',config, float)[0]
    np.testing.assert_almost_equal(str2, 2.33e-9)

    str3 = galsim.config.ParseValue(config,'str3',config, float)[0]
    np.testing.assert_almost_equal(str3, 6.0e-9)

    # Test values read from an InputCatalog
    input_cat = galsim.InputCatalog(dir='config_input', file_name='catalog.txt')
    cat1 = []
    cat2 = []
    for k in range(5):
        config['seq_index'] = k
        cat1.append(galsim.config.ParseValue(config,'cat1',config, float)[0])
        cat2.append(galsim.config.ParseValue(config,'cat2',config, float)[0])

    np.testing.assert_array_almost_equal(cat1, [ 1.234, 2.345, 3.456, 1.234, 2.345 ])
    np.testing.assert_array_almost_equal(cat2, [ 4.131, -900, 8000, 4.131, -900 ])

    # Test values generated from a uniform deviate
    rng = galsim.UniformDeviate(1234)
    config['rng'] = galsim.UniformDeviate(1234) # A second copy starting with the same seed.
    for k in range(6):
        ran1 = galsim.config.ParseValue(config,'ran1',config, float)[0]
        np.testing.assert_almost_equal(ran1, rng() * 2.5 + 0.5)

        ran2 = galsim.config.ParseValue(config,'ran2',config, float)[0]
        np.testing.assert_almost_equal(ran2, rng() * 5 - 5)

    # Test values generated from a Gaussian deviate
    gd = galsim.GaussianDeviate(rng)
    for k in range(6):
        gauss1 = galsim.config.ParseValue(config,'gauss1',config, float)[0]
        gd.setMean(0)
        gd.setSigma(1)
        np.testing.assert_almost_equal(gauss1, gd())

        gauss2 = galsim.config.ParseValue(config,'gauss2',config, float)[0]
        gd.setMean(4)
        gd.setSigma(3)
        np.testing.assert_almost_equal(gauss2, gd())

        gauss3 = galsim.config.ParseValue(config,'gauss3',config, float)[0]
        gd.setMean(0)
        gd.setSigma(1.5)
        gd_val = gd()
        while math.fabs(gd_val) > 2:
            gd_val = gd()
        np.testing.assert_almost_equal(gauss3, gd_val)

        gauss4 = galsim.config.ParseValue(config,'gauss4',config, float)[0]
        gd.setMean(0)
        gd.setSigma(0.5)
        gd_val = math.fabs(gd())
        while gd_val > 0.8:
            gd_val = math.fabs(gd())
        np.testing.assert_almost_equal(gauss4, gd_val)

        gauss5 = galsim.config.ParseValue(config,'gauss5',config, float)[0]
        gd.setMean(0.5)
        gd.setSigma(0.3)
        gd_val = gd()
        if gd_val > 0.5: 
            gd_val = 1-gd_val
        while gd_val < 0:
            gd_val = gd()
            if gd_val > 0.5: 
                gd_val = 1-gd_val
        np.testing.assert_almost_equal(gauss5, gd_val)

    # Test values generated from a distribution in a file
    dd=galsim.DistDeviate(rng,function='config_input/distribution.txt',interpolant='linear')
    for k in range(6):
        dist1 = galsim.config.ParseValue(config,'dist1',config, float)[0]
        np.testing.assert_almost_equal(dist1, dd())
    dd=galsim.DistDeviate(rng,function='config_input/distribution2.txt',interpolant='linear')
    for k in range(6):
        dist2 = galsim.config.ParseValue(config,'dist2',config, float)[0]
        np.testing.assert_almost_equal(dist2, dd())
    dd=galsim.DistDeviate(rng,function=lambda x: x*x,x_min=0.,x_max=2.)
    for k in range(6):
        dist3 = galsim.config.ParseValue(config,'dist3',config, float)[0]
        np.testing.assert_almost_equal(dist3, dd())

    # Test values generated from a Sequence
    seq1 = []
    seq2 = []
    seq3 = []
    seq4 = []
    seq5 = []
    for k in range(6):
        config['seq_index'] = k
        seq1.append(galsim.config.ParseValue(config,'seq1',config, float)[0])
        seq2.append(galsim.config.ParseValue(config,'seq2',config, float)[0])
        seq3.append(galsim.config.ParseValue(config,'seq3',config, float)[0])
        seq4.append(galsim.config.ParseValue(config,'seq4',config, float)[0])
        seq5.append(galsim.config.ParseValue(config,'seq5',config, float)[0])

    np.testing.assert_array_almost_equal(seq1, [ 0, 1, 2, 3, 4, 5 ])
    np.testing.assert_array_almost_equal(seq2, [ 0, 0.1, 0.2, 0.3, 0.4, 0.5 ])
    np.testing.assert_array_almost_equal(seq3, [ 1.5, 2, 2.5, 3, 3.5, 4 ])
    np.testing.assert_array_almost_equal(seq4, [ 10, 8, 6, 4, 2, 0 ])
    np.testing.assert_array_almost_equal(seq5, [ 1, 1, 2, 2, 1, 1 ])

    # Test values taken from a List
    list1 = []
    list2 = []
    for k in range(5):
        config['seq_index'] = k
        list1.append(galsim.config.ParseValue(config,'list1',config, float)[0])
        list2.append(galsim.config.ParseValue(config,'list2',config, float)[0])

    np.testing.assert_array_almost_equal(list1, [ 73, 8.9, 3.14, 73, 8.9 ])
    np.testing.assert_array_almost_equal(list2, [ 10.8, 7.0, 4.3, 1.8, 10.8 ])

    t2 = time.time()
    print 'time for %s = %.2f'%(funcname(),t2-t1)
Ejemplo n.º 21
0
gal_g1 = -0.4 + initial_n * 0.016
gal_g2 = -0.45 + initial_n * 0.018
#cat_file_name ='galsim_default_input.asc'
#cat = galsim.Catalog(cat_file_name)
shears1 = []
shears2 = []
numbers = []
ellipticities = []
size = []
flux = []
mag = []
sersic_indices = []
print 'hey'
indices = []

gara = galsim.GaussianDeviate(mean=1., sigma=1)  #random_seed,

############################gasn=galsim.GaussianDeviate(random_seed,mean=25.5,sigma=0.8) #gasn=galsim.GaussianDeviate(random_seed,mean=26,sigma=1.) #Currently draws for magnitudes. #0.5

ref_data = ascii.read(
    '/vol/aibn148/data1/bhernandez/PhD/PSF_HST/tmp.regions_VI3')
goodgal = np.array([ref_data[i][2] for i in range(len(ref_data))])
goodregion = np.array([ref_data[i][1] for i in range(len(ref_data))])
VI = np.array([ref_data[i][5] for i in range(len(ref_data))])
#VI = VI[(goodgal>0)&(goodregion>0)]

#ref_rad_tmp = [ref_data[i][4] for i in range(len(ref_data))]
#ref_rad_tmp = np.array(ref_rad_tmp)
#ref_rad = ref_rad_tmp[(goodgal>0.)&(goodregion>0.)&(VI<0.3)]
ref_sn_tmp = [ref_data[i][3] for i in range(len(ref_data))]
ref_sn_tmp = np.array(ref_sn_tmp)
Ejemplo n.º 22
0
    def __init__(self, image, x_interpolant = None, k_interpolant = None, normalization = 'flux',
                 dx = None, flux = None, pad_factor = 0., noise_pad = 0., rng = None,
                 pad_image = None, calculate_stepk=True, calculate_maxk=True,
                 use_cache=True, use_true_center=True, gsparams=None):

        import numpy as np

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Fix the center to be in the right place.
        # Note the minus sign in front of image.scale, since we want to fix the center in the 
        # opposite sense of what the draw function does.
        if use_true_center:
            prof = self._fix_center(image, -image.scale)
            GSObject.__init__(self, prof.SBProfile)
Ejemplo n.º 23
0
    def __generateDeviates(self):
        # Generate random deviates
        ud = galsim.UniformDeviate(struct.unpack('i', os.urandom(4))[0])
        gd = galsim.GaussianDeviate(ud, sigma=self.galData.ellipRMS)

        return (ud, gd)
Ejemplo n.º 24
0
 def _random_screen(self):
     """Generate a random phase screen with power spectrum given by self._psi**2"""
     gd = galsim.GaussianDeviate(self.rng)
     noise = galsim.utilities.rand_arr(self._psi.shape, gd)
     return galsim.fft.ifft2(galsim.fft.fft2(noise)*self._psi).real
Ejemplo n.º 25
0
def test_uncorr_padding():
    """Test for uncorrelated noise padding of InterpolatedImage."""
    import time
    t1 = time.time()

    # Set up some defaults: use weird image sizes / shapes and noise variances.
    decimal_precise=5
    decimal_coarse=2
    orig_nx = 147
    orig_ny = 174
    noise_var = 1.73
    big_nx = 519
    big_ny = 482
    orig_seed = 151241

    # first, make a noise image
    orig_img = galsim.ImageF(orig_nx, orig_ny, scale=1.)
    gd = galsim.GaussianDeviate(orig_seed, mean=0., sigma=np.sqrt(noise_var))
    orig_img.addNoise(galsim.DeviateNoise(gd))

    # make it into an InterpolatedImage with some zero-padding
    # (note that default is zero-padding, by factors of several)
    int_im = galsim.InterpolatedImage(orig_img)
    # draw into a larger image
    big_img = galsim.ImageF(big_nx, big_ny)
    int_im.draw(big_img, scale=1.)
    # check that variance is diluted by expected amount - should be exact, so check precisely!
    # Note that this only works if the big image has the same even/odd-ness in the two sizes.
    # Otherwise the center of the original image will fall between pixels in the big image.
    # Then the variance will be smoothed somewhat by the interpolant.
    big_var_expected = np.var(orig_img.array)*float(orig_nx*orig_ny)/(big_nx*big_ny)
    np.testing.assert_almost_equal(
        np.var(big_img.array), big_var_expected, decimal=decimal_precise,
        err_msg='Variance not diluted by expected amount when zero-padding')

    # make it into an InterpolatedImage with noise-padding
    int_im = galsim.InterpolatedImage(orig_img, noise_pad=noise_var,
                                      noise_pad_size=max(big_nx,big_ny),
                                      rng = galsim.GaussianDeviate(orig_seed))
    # draw into a larger image
    big_img = galsim.ImageF(big_nx, big_ny)
    int_im.draw(big_img, scale=1.)
    # check that variance is same as original - here, we cannot be too precise because the padded
    # region is not huge and the comparison will be, well, noisy.
    np.testing.assert_almost_equal(
        np.var(big_img.array), noise_var, decimal=decimal_coarse,
        err_msg='Variance not correct after padding image with noise')

    # check that if we pass in a RNG, it is actually used to pad with the same noise field
    # basically, redo all of the above steps and draw into a new image, make sure it's the same as
    # previous.
    int_im = galsim.InterpolatedImage(orig_img, noise_pad=noise_var,
                                      noise_pad_size=max(big_nx,big_ny),
                                      rng = galsim.GaussianDeviate(orig_seed))
    big_img_2 = galsim.ImageF(big_nx, big_ny)
    int_im.draw(big_img_2, scale=1.)
    np.testing.assert_array_almost_equal(
        big_img_2.array, big_img.array, decimal=decimal_precise,
        err_msg='Cannot reproduce noise-padded image with same choice of seed')

    # Finally check inputs: what if we give it an input variance that is neg?  A list?
    try:
        np.testing.assert_raises(ValueError,galsim.InterpolatedImage,orig_img,noise_pad=-1.)
    except ImportError:
        print 'The assert_raises tests require nose'

    t2 = time.time()
    print 'time for %s = %.2f'%(funcname(),t2-t1)
Ejemplo n.º 26
0
import time
import numpy as np
import galsim

# Use a deterministic random number generator so we don't fail tests because of rare flukes
# in the random numbers.
rseed = 12345

smallim_size = 16  # size of image when we test correlated noise properties using small inputs
largeim_size = 12 * smallim_size  # ditto, but when we need a larger image

if __name__ == "__main__":

    t1 = time.time()
    gd = galsim.GaussianDeviate(rseed)
    dx_cosmos = 0.03  # Non-unity, non-default value to be used below
    cn = galsim.getCOSMOSNoise(
        gd,
        '../../../examples/data/acs_I_unrot_sci_20_cf.fits',
        dx_cosmos=dx_cosmos)
    cn.setVariance(1000.)  # Again chosen to be non-unity
    # Define a PSF with which to convolve the noise field, one WITHOUT 2-fold rotational symmetry
    # (see test_autocorrelate in test_SBProfile.py for more info as to why this is relevant)
    # Make a relatively realistic mockup of a GREAT3 target image
    lam_over_diam_cosmos = (814.e-9 /
                            2.4) * (180. / np.pi) * 3600.  # ~lamda/D in arcsec
    lam_over_diam_ground = lam_over_diam_cosmos * 2.4 / 4.  # Generic 4m at same lambda
    psf_cosmos = galsim.Convolve([
        galsim.Airy(lam_over_diam=lam_over_diam_cosmos, obscuration=0.4),
        galsim.Pixel(0.05)
Ejemplo n.º 27
0
def test_corr_padding():
    """Test for correlated noise padding of InterpolatedImage."""
    import time
    t1 = time.time()

    # Set up some defaults for tests.
    decimal_precise=4
    decimal_coarse=2
    imgfile = 'fits_files/blankimg.fits'
    orig_nx = 187
    orig_ny = 164
    big_nx = 319
    big_ny = 322
    orig_seed = 151241

    # Read in some small image of a noise field from HST.
    # Rescale it to have a decently large amplitude for the purpose of doing these tests.
    im = 1.e2*galsim.fits.read(imgfile)
    # Make a CorrrlatedNoise out of it.
    cn = galsim.CorrelatedNoise(im, galsim.BaseDeviate(orig_seed))

    # first, make a noise image
    orig_img = galsim.ImageF(orig_nx, orig_ny, scale=1.)
    orig_img.addNoise(cn)

    # make it into an InterpolatedImage with some zero-padding
    # (note that default is zero-padding, by factors of several)
    int_im = galsim.InterpolatedImage(orig_img)
    # draw into a larger image
    big_img = galsim.ImageF(big_nx, big_ny)
    int_im.draw(big_img, scale=1.)
    # check that variance is diluted by expected amount - should be exact, so check precisely!
    big_var_expected = np.var(orig_img.array)*float(orig_nx*orig_ny)/(big_nx*big_ny)
    np.testing.assert_almost_equal(np.var(big_img.array), big_var_expected, decimal=decimal_precise,
        err_msg='Variance not diluted by expected amount when zero-padding')

    # make it into an InterpolatedImage with noise-padding
    int_im = galsim.InterpolatedImage(orig_img, rng = galsim.GaussianDeviate(orig_seed),
                                      noise_pad = im, noise_pad_size = max(big_nx,big_ny))

    # draw into a larger image
    big_img = galsim.ImageF(big_nx, big_ny)
    int_im.draw(big_img, scale=1.)
    # check that variance is same as original - here, we cannot be too precise because the padded
    # region is not huge and the comparison will be, well, noisy.
    np.testing.assert_almost_equal(np.var(big_img.array), np.var(orig_img.array),
        decimal=decimal_coarse,
        err_msg='Variance not correct after padding image with correlated noise')

    # check that if we pass in a RNG, it is actually used to pad with the same noise field
    # basically, redo all of the above steps and draw into a new image, make sure it's the same as
    # previous.
    int_im = galsim.InterpolatedImage(
        orig_img, rng=galsim.GaussianDeviate(orig_seed), noise_pad=cn,
        noise_pad_size = max(big_nx,big_ny))
    big_img_2 = galsim.ImageF(big_nx, big_ny)
    int_im.draw(big_img_2, scale=1.)
    np.testing.assert_array_almost_equal(big_img_2.array, big_img.array, decimal=decimal_precise,
        err_msg='Cannot reproduce correlated noise-padded image with same choice of seed')

    # Finally, check inputs:
    # what if we give it a screwy way of defining the image padding?
    try:
        np.testing.assert_raises(ValueError,galsim.InterpolatedImage,orig_img,noise_pad=-1.)
    except ImportError:
        print 'The assert_raises tests require nose'
    # also, check that whether we give it a string, image, or cn, it gives the same noise field
    # (given the same random seed)
    infile = 'fits_files/blankimg.fits'
    inimg = galsim.fits.read(infile)
    incf = galsim.CorrelatedNoise(inimg, galsim.GaussianDeviate()) # input RNG will be ignored below
    int_im2 = galsim.InterpolatedImage(orig_img, rng=galsim.GaussianDeviate(orig_seed),
                                       noise_pad=inimg, noise_pad_size = max(big_nx,big_ny))
    int_im3 = galsim.InterpolatedImage(orig_img, rng=galsim.GaussianDeviate(orig_seed),
                                       noise_pad=incf, noise_pad_size = max(big_nx,big_ny))
    big_img2 = galsim.ImageF(big_nx, big_ny)
    big_img3 = galsim.ImageF(big_nx, big_ny)
    int_im2.draw(big_img2, scale=1.)
    int_im3.draw(big_img3, scale=1.)
    np.testing.assert_equal(big_img2.array, big_img3.array,
                            err_msg='Diff ways of specifying correlated noise give diff answers')

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