def getPSF(self, image_pos, pixel_scale=None, gsparams=None): """Returns the PSF at position image_pos @param image_pos The position in image coordinates at which to build the PSF. @param gsparams (Optional) A GSParams instance to pass to the constructed GSObject. @param pixel_scale A deprecated parameter that is only present for backwards compatibility. If the constructor did not provide an image file or wcs, then this will use the pixel scale for an approximate wcs. @returns the PSF as a GSObject """ # Build an image version of the numpy array im = galsim.Image(self.getPSFArray(image_pos)) # Build the PSF profile in the image coordinate system. psf = galsim.InterpolatedImage(im, scale=self.sample_scale, flux=1, x_interpolant=galsim.Lanczos(3), gsparams=gsparams) # This brings if from image coordinates to world coordinates. if self.wcs: psf = self.wcs.toWorld(psf, image_pos=image_pos) elif pixel_scale: depr( 'pixel_scale', 1.1, 'wcs=PixelScale(pixel_scale) in the constructor for DES_PSFEx') psf = galsim.PixelScale(pixel_scale).toWorld(psf) return psf
def getPSF(self, image_pos, gsparams=None): """Returns the PSF at position ``image_pos``. Parameters: image_pos: The position in image coordinates at which to build the PSF. gsparams: A `GSParams` instance to pass to the constructed `GSObject`. [defualt: None] Returns: the PSF as a `GSObject` """ # Build an image version of the numpy array im = galsim.Image(self.getPSFArray(image_pos)) # Build the PSF profile in the image coordinate system. psf = galsim.InterpolatedImage(im, scale=self.sample_scale, flux=1, x_interpolant=galsim.Lanczos(3), gsparams=gsparams) # This brings if from image coordinates to world coordinates. if self.wcs: psf = self.wcs.toWorld(psf, image_pos=image_pos) return psf
def main(argv): # Try different interpolants! #interp1d = galsim.Linear(); #interp1d = galsim.Delta(); interp1d = galsim.Lanczos(5, conserve_dc=True, tol=1.e-4) #interp1d = galsim.Quintic(); interp2d = galsim.InterpolantXY(interp1d) try: inname = argv[1] outname = argv[2] dxOut = float(argv[3]) dim = int(argv[4]) nPhotons = int(argv[5]) g1 = float(argv[6]) if len(argv) > 6 else 0. g2 = float(argv[7]) if len(argv) > 7 else 0. except Exception as err: print __doc__ raise err galaxyImg = galsim.fits.read(inname) galaxy = galsim.InterpolatedImage(galaxyImg, x_interpolant=interp2d, dx=1.) galaxy.applyShear(g1=g1, g2=g2) rng = galsim.UniformDeviate(1534225) bounds = galsim.BoundsI(-dim / 2, dim / 2 + 1, -dim / 2, dim / 2 + 1) img = galsim.ImageF(bounds, scale=dxOut) galaxy.drawShoot(image=img, n_photons=nPhotons, rng=rng) img.write(outname)
def test_Lanczos7_ref(): """Test use of Lanczos7 interpolant against some reference values """ import time t1 = time.time() interp = galsim.Lanczos(7, conserve_dc=False, tol=1.e-4) testobj = galsim.InterpolatedImage(ref_image.view(), x_interpolant=interp, dx=dx, normalization='sb') testKvals = np.zeros(len(KXVALS)) # Make test kValues for i in xrange(len(KXVALS)): posk = galsim.PositionD(KXVALS[i], KYVALS[i]) testKvals[i] = np.abs(testobj.kValue(posk)) # Compare with saved array refKvals = np.loadtxt(os.path.join(TESTDIR, "absfKLanczos7_test.txt")) print 'ref = ', refKvals print 'test = ', testKvals np.testing.assert_array_almost_equal( refKvals / testKvals, 1., 5, err_msg= "kValues do not match reference values for Lanczos-7 interpolant.") t2 = time.time() print 'time for %s = %.2f' % (funcname(), t2 - t1)
def BuildDES_PSFEx(config, key, base, ignore, gsparams, logger): """@brief Build a RealGalaxy type GSObject from user input. """ opt = {'flux': float, 'num': int} kwargs, safe = galsim.config.GetAllParams(config, key, base, opt=opt, ignore=ignore) if 'des_psfex' not in base: raise ValueError( "No DES_PSFEx instance available for building type = DES_PSFEx") num = kwargs.get('num', 0) if num < 0: raise ValueError("Invalid num < 0 supplied for DES_PSFEx: num = %d" % num) if num >= len(base['des_psfex']): raise ValueError( "Invalid num supplied for DES_PSFEx (too large): num = %d" % num) des_psfex = base['des_psfex'][num] if 'image_pos' not in base: raise ValueError( "DES_PSFEx requested, but no image_pos defined in base.") image_pos = base['image_pos'] # Convert gsparams from a dict to an actual GSParams object if gsparams: gsparams = galsim.GSParams(**gsparams) else: gsparams = None #psf = des_psfex.getPSF(image_pos, gsparams=gsparams) # Because of serialization issues, the above call doesn't work. So we need to # repeat the internals of getPSF here. # Also, this is why we have getSampleScale and getLocalWCS. The multiprocessing.managers # stuff only makes available methods of classes that are proxied, not all the attributes. # So this is the only way to access these attributes. im = galsim.Image(des_psfex.getPSFArray(image_pos)) psf = galsim.InterpolatedImage(im, scale=des_psfex.getSampleScale(), flux=1, x_interpolant=galsim.Lanczos(3), gsparams=gsparams) psf = des_psfex.getLocalWCS(image_pos).toWorld(psf) if 'flux' in kwargs: psf = psf.withFlux(kwargs['flux']) # The second item here is "safe", a boolean that declares whether the returned value is # safe to save and use again for later objects. In this case, we wouldn't want to do # that, since they will be at different positions, so the interpolated PSF will be different. return psf, False
def main(argv): # translation from C++ by Jim; comments after this one are in Gary's voice l3 = galsim.Lanczos(3, True, 1.0E-4) l32d = galsim.InterpolantXY(l3) dxHST = 0.03 dxSDSS = 0.396 g1 = 0.02 g2 = 0.0 psfSky = 1000.0 rootname = argv[1] xshift = float(argv[2]) if len(argv) > 2 else 0. yshift = float(argv[3]) if len(argv) > 3 else 0. s = galsim.Shear(g1=g1, g2=g2) # Rachel is probably using the (1+g, 1-g) form of shear matrix, # which means there is some (de)magnification, by my definition: #e = galsim.Ellipse(s, -(g1*g1+g2*g2), galsim.PositionD(xshift,yshift)); galaxyImg = galsim.fits.read(rootname + "_masknoise.fits") galaxy = galsim.InterpolatedImage(galaxyImg, x_interpolant=l32d, dx=dxHST, flux=0.804 * 1000. * dxSDSS * dxSDSS) psf1Img = galsim.fits.read(rootname + ".psf.fits") psf1 = galsim.InterpolatedImage(psf1Img, x_interpolant=l32d, dx=dxHST, flux=1.) psf2Img = galsim.fits.read(rootname + ".sdsspsf.fits") psf2 = galsim.InterpolatedImage(psf2Img, x_interpolant=l32d, dx=dxSDSS, flux=1.) outImg = galsim.fits.read(rootname + ".g1_0.02.g2_0.00.fits") result = outImg.copy() psfInv = galsim.Deconvolve(psf1) deconv = galsim.Convolve(galaxy, psfInv) sheared = deconv.createTransformed(e) out = galsim.Convolve(sheared, psf2) test_outImg = out.draw(result, dx=dxSDSS) test_outImg.write(rootname + ".gary.fits") result += psfSky result -= test_outImg result.write(rootname + ".diff.fits")
def BuildDES_PSFEx(config, base, ignore, gsparams, logger): """Build a GSObject representing the PSFex model at the correct location in the image in a config-processing context. This is used as object type ``DES_PSFEx`` in a config file. It requires the use of the ``des_psfex`` input field. """ des_psfex = galsim.config.GetInputObj('des_psfex', config, base, 'DES_PSFEx') opt = {'flux': float, 'num': int, 'image_pos': galsim.PositionD} params, safe = galsim.config.GetAllParams(config, base, opt=opt, ignore=ignore) if 'image_pos' in params: image_pos = params['image_pos'] elif 'image_pos' in base: image_pos = base['image_pos'] else: raise galsim.GalSimConfigError( "DES_PSFEx requested, but no image_pos defined in base.") # Convert gsparams from a dict to an actual GSParams object if gsparams: gsparams = galsim.GSParams(**gsparams) else: gsparams = None #psf = des_psfex.getPSF(image_pos, gsparams=gsparams) # Because of serialization issues, the above call doesn't work. So we need to # repeat the internals of getPSF here. # Also, this is why we have getSampleScale and getLocalWCS. The multiprocessing.managers # stuff only makes available methods of classes that are proxied, not all the attributes. # So this is the only way to access these attributes. im = galsim.Image(des_psfex.getPSFArray(image_pos)) psf = galsim.InterpolatedImage(im, scale=des_psfex.getSampleScale(), flux=1, x_interpolant=galsim.Lanczos(3), gsparams=gsparams) psf = des_psfex.getLocalWCS(image_pos).toWorld(psf) if 'flux' in params: psf = psf.withFlux(params['flux']) # The second item here is "safe", a boolean that declares whether the returned value is # safe to save and use again for later objects. In this case, we wouldn't want to do # that, since they will be at different positions, so the interpolated PSF will be different. return psf, False
def test_sbinterpolatedimage(): """Test that we can make SBInterpolatedImages from Images of various types, and convert back. """ import time t1 = time.time() # for each type, try to make an SBInterpolatedImage, and check that when we draw an image from # that SBInterpolatedImage that it is the same as the original lan3 = galsim.Lanczos(3, True, 1.E-4) lan3_2d = galsim.InterpolantXY(lan3) ftypes = [np.float32, np.float64] ref_array = np.array([[0.01, 0.08, 0.07, 0.02], [0.13, 0.38, 0.52, 0.06], [0.09, 0.41, 0.44, 0.09], [0.04, 0.11, 0.10, 0.01]]) for array_type in ftypes: image_in = galsim.ImageView[array_type](ref_array.astype(array_type)) np.testing.assert_array_equal( ref_array.astype(array_type), image_in.array, err_msg= "Array from input Image differs from reference array for type %s" % array_type) sbinterp = galsim.SBInterpolatedImage(image_in, lan3_2d, dx=1.0) test_array = np.zeros(ref_array.shape, dtype=array_type) image_out = galsim.ImageView[array_type](test_array, scale=1.0) sbinterp.draw(image_out.view()) np.testing.assert_array_equal( ref_array.astype(array_type), image_out.array, err_msg= "Array from output Image differs from reference array for type %s" % array_type) # Lanczos doesn't quite get the flux right. Wrong at the 5th decimal place. # Gary says that's expected -- Lanczos isn't technically flux conserving. # He applied the 1st order correction to the flux, but expect to be wrong at around # the 10^-5 level. # Anyway, Quintic seems to be accurate enough. quint = galsim.Quintic(1.e-4) quint_2d = galsim.InterpolantXY(quint) sbinterp = galsim.SBInterpolatedImage(image_in, quint_2d, dx=1.0) sbinterp.setFlux(1.) do_shoot(galsim.GSObject(sbinterp), image_out, "InterpolatedImage") # Test kvalues do_kvalue(galsim.GSObject(sbinterp), "InterpolatedImage") t2 = time.time() print 'time for %s = %.2f' % (funcname(), t2 - t1)
def getPSF(self, pos, pixel_scale, gsparams=None): """Returns the PSF at position pos The PSFEx class does everything in pixel units, so it has no concept of the pixel_scale. For Galsim, we do everything in physical units (i.e. arcsec typically), so the returned psf needs to account for the pixel_scale. @param pos The position in pixel units for which to build the PSF. @param pixel_scale The pixel scale in arcsec/pixel. @param gsparams (Optional) A GSParams instance to pass to the constructed GSObject. @returns an InterpolatedImage instance. """ import numpy xto = self._define_xto((pos.x - self.x_zero) / self.x_scale) yto = self._define_xto((pos.y - self.y_zero) / self.y_scale) order = self.fit_order P = numpy.array([ xto[nx] * yto[ny] for ny in range(order + 1) for nx in range(order + 1 - ny) ]) assert len(P) == self.fit_size ar = numpy.tensordot(P, self.basis, (0, 0)).astype(numpy.float32) # Note: This is equivalent to: # ar = self.basis[0].astype(numpy.float32) # for n in range(1,self.fit_order+1): # for ny in range(n+1): # nx = n-ny # k = nx+ny*(self.fit_order+1)-ny*(ny-1)/2 # ar += xto[nx] * yto[ny] * self.basis[k] # which is pretty much Peter's version of this code. im = galsim.ImageViewF(array=ar) # We need the scale in arcsec/psfex_pixel, which is # (arcsec / image_pixel) * (image_pixel / psfex_pixel) # = pixel_scale * sample_scale im.scale = pixel_scale * self.sample_scale return galsim.InterpolatedImage(im, flux=1, x_interpolant=galsim.Lanczos(3), gsparams=gsparams)
def getPSF(self, image_pos, gsparams=None): """Returns the PSF at position image_pos @param image_pos The position in image coordinates at which to build the PSF. @param gsparams (Optional) A GSParams instance to pass to the constructed GSObject. @returns the PSF as a GSObject """ # Build an image version of the numpy array im = galsim.Image(self.getPSFArray(image_pos)) # Build the PSF profile in the image coordinate system. psf = galsim.InterpolatedImage(im, scale=self.sample_scale, flux=1, x_interpolant=galsim.Lanczos(3), gsparams=gsparams) # This brings if from image coordinates to world coordinates. if self.wcs: psf = self.wcs.toWorld(psf, image_pos=image_pos) return psf
def test_Lanczos7_spline(): """Test the spline tabulation of the k space Lanczos-7 interpolant. """ import time t1 = time.time() interp = galsim.InterpolantXY( galsim.Lanczos(7, conserve_flux=True, tol=1.e-4)) testobj = galsim.SBInterpolatedImage(image.view(), interp, dx=dx) testKvals = np.zeros(len(KXVALS)) # Make test kValues for i in xrange(len(KXVALS)): posk = galsim.PositionD(KXVALS[i], KYVALS[i]) testKvals[i] = np.abs(testobj.kValue(posk)) # Compare with saved array refKvals = np.loadtxt(os.path.join(TESTDIR, "absfKLanczos7_test.txt")) np.testing.assert_array_almost_equal( refKvals, testKvals, DECIMAL, err_msg="Spline-interpolated kValues do not match saved " + "data for k space Lanczos-7 interpolant.") t2 = time.time() print 'time for %s = %.2f' % (funcname(), t2 - t1)
import cPickle import numpy as np import galsim import test_interpolants SERSIC_IMAGE_SIZE = 512 # For initial image of the Sersic at Hubble resolution, make nice and large TEST_IMAGE_SIZE = SERSIC_IMAGE_SIZE # For speed could make this smaller # Dictionary for parsing the test_interpolants.interpolant_list into galsim Interpolants INTERPOLANT_DICT = { "nearest": galsim.Nearest(), "sinc": galsim.SincInterpolant(), "linear": galsim.Linear(), "cubic": galsim.Cubic(), "quintic": galsim.Quintic(), "lanczos3": galsim.Lanczos(3), "lanczos4": galsim.Lanczos(4), "lanczos5": galsim.Lanczos(5), "lanczos7": galsim.Lanczos(7) } # Output filenames DELTA_FILENAME = 'interpolant_test_parametric_output_delta.dat' ORIGINAL_FILENAME = 'interpolant_test_parametric_output_original.dat' NITEMS = 30 # For now, look at a few only LAM_OVER_DIAM_COSMOS = 814.e-9 / 2.4 # All the original images in Melanie's tests were from COSMOS # F814W, so this is a crude approximation to the PSF scale in # radians, ~0.07 arcsec COSMOS_PSF = galsim.Airy(lam_over_diam=LAM_OVER_DIAM_COSMOS * 180. * 3600. /
diskRe = [0.5, 1.0] bulgeRe = [0.25, 0.5] if len(diskRe) is not len(bulgeRe): raise RuntimeError( "Grids in bulge and disk scale lengths do not have same size!") nBulge = 4.0 nDisk = 1.0 pixelScale = 0.03 # we are simulating ACS data totFlux = 1000.0 # total flux for galaxy #### note: the following parameters were not used #### sigmaBulge = 1.0 # dispersion in Sersic n for bulge sigmaDisk = 0.2 # dispersion in Sersic n for disk # read in ePSF and normalize (note: already includes pixel response, don't have to do separately) l3 = galsim.Lanczos(3, True, 1.0E-4) l32d = galsim.InterpolantXY(l3) PSFImage = galsim.fits.read(PSFFile) PSF = galsim.SBInterpolatedImage(PSFImage, l32d, pixelScale, 2.) PSF.setFlux(1.0) # Loop over the various grids: values of bulge-to-total ratio, bulge ellipticity, disk ellipticity, # S/N and number of noise realizations, radii rng = galsim.UniformDeviate() for bt in bulge2Total: print "Beginning bulge-to-total ratio of ", bt for bell in bulgeEllip: print "Beginning bulge ellipticity of ", bell for dell in diskEllip: print "Beginning disk ellipticity of ", dell for dreind in range(len(diskRe)):
def __init__(self, *, rng, im_width, buff, scale, trunc=1, variation_factor=10, fwhm=0.8): self._rng = rng self._im_cen = (im_width - 1) / 2 self._scale = scale self._tot_width = im_width + 2 * buff self._x_scale = 2.0 / self._tot_width / scale self._buff = buff self._variation_factor = variation_factor self._median_seeing = fwhm # set the power spectrum and PSF params # Heymans et al, 2012 found L0 ~= 3 arcmin, given as 180 arcsec here. def _pf(k): return (k**2 + (1. / 180)**2)**(-11. / 6.) * np.exp(-(k * trunc)**2) self._ps = galsim.PowerSpectrum(e_power_function=_pf, b_power_function=_pf) ng = 128 gs = max(self._tot_width * self._scale / ng, 1) self.ng = ng self.gs = gs seed = self._rng.randint(1, 2**30) self._ps.buildGrid(grid_spacing=gs, ngrid=ng, get_convergence=True, variance=(0.01 * variation_factor)**2, rng=galsim.BaseDeviate(seed)) # cache the galsim LookupTable2D objects by hand to speed computations g1_grid, g2_grid, mu_grid = galsim.lensing_ps.theoryToObserved( self._ps.im_g1.array, self._ps.im_g2.array, self._ps.im_kappa.array) self._lut_g1 = galsim.table.LookupTable2D( self._ps.x_grid, self._ps.y_grid, g1_grid.T, edge_mode='wrap', interpolant=galsim.Lanczos(5)) self._lut_g2 = galsim.table.LookupTable2D( self._ps.x_grid, self._ps.y_grid, g2_grid.T, edge_mode='wrap', interpolant=galsim.Lanczos(5)) self._lut_mu = galsim.table.LookupTable2D( self._ps.x_grid, self._ps.y_grid, mu_grid.T - 1, edge_mode='wrap', interpolant=galsim.Lanczos(5)) self._g1_mean = self._rng.normal() * 0.01 * variation_factor self._g2_mean = self._rng.normal() * 0.01 * variation_factor def _getlogmnsigma(mean, sigma): logmean = np.log(mean) - 0.5 * np.log(1 + sigma**2 / mean**2) logvar = np.log(1 + sigma**2 / mean**2) logsigma = np.sqrt(logvar) return logmean, logsigma lm, ls = _getlogmnsigma(self._median_seeing, 0.1) self._fwhm_central = np.exp(self._rng.normal() * ls + lm)
def simReal(real_galaxy, target_PSF, target_pixel_scale, g1=0.0, g2=0.0, rotation_angle=None, rand_rotate=True, rng=None, target_flux=1000.0, image=None): """Function to simulate images (no added noise) from real galaxy training data. This function takes a RealGalaxy from some training set, and manipulates it as needed to simulate a (no-noise-added) image from some lower-resolution telescope. It thus requires a target PSF (which could be an image, or one of our base classes) that represents all PSF components including the pixel response, and a target pixel scale. The default rotation option is to impose a random rotation to make irrelevant any real shears in the galaxy training data (optionally, the RNG can be supplied). This default can be turned off by setting `rand_rotate = False` or by requesting a specific rotation angle using the `rotation_angle` keyword, in which case `rand_rotate` is ignored. Optionally, the user can specify a shear (default 0). Finally, they can specify a flux normalization for the final image, default 1000. @param real_galaxy The RealGalaxy object to use, not modified in generating the simulated image. @param target_PSF The target PSF, either one of our base classes or an ImageView/Image. @param target_pixel_scale The pixel scale for the final image, in arcsec. @param g1 First component of shear to impose (components defined with respect to pixel coordinates), default `g1 = 0.` @param g2 Second component of shear to impose, default `g2 = 0.` @param rotation_angle Angle by which to rotate the galaxy (must be a galsim.Angle instance). @param rand_rotate If `rand_rotate = True` (default) then impose a random rotation on the training galaxy; this is ignored if `rotation_angle` is set. @param rng A random number generator to use for selection of the random rotation angle. (optional, may be any kind of galsim.BaseDeviate or None) @param target_flux The target flux in the output galaxy image, default `target_flux = 1000.` @param image As with the GSObject.draw() function, if an image is provided, then it will be used and returned. If `image=None`, then an appropriately sized image will be created. @return A simulated galaxy image. The input RealGalaxy is unmodified. """ # do some checking of arguments if not isinstance(real_galaxy, galsim.RealGalaxy): raise RuntimeError("Error: simReal requires a RealGalaxy!") for Class in galsim.Image.itervalues(): if isinstance(target_PSF, Class): lan5 = galsim.Lanczos(5, conserve_flux=True, tol=1.e-4) interp2d = galsim.InterpolantXY(lan5) target_PSF = galsim.SBInterpolatedImage(target_PSF.view(), xInterp=interp2d, dx=target_pixel_scale) break for Class in galsim.ImageView.itervalues(): if isinstance(target_PSF, Class): lan5 = galsim.Lanczos(5, conserve_flux=True, tol=1.e-4) interp2d = galsim.InterpolantXY(lan5) target_PSF = galsim.SBInterpolatedImage(target_PSF, xInterp=interp2d, dx=target_pixel_scale) break if isinstance(target_PSF, galsim.GSObject): target_PSF = target_PSF.SBProfile if not isinstance(target_PSF, galsim.SBProfile): raise RuntimeError( "Error: target PSF is not an Image, ImageView, SBProfile, or GSObject!" ) if rotation_angle != None and not isinstance(rotation_angle, galsim.Angle): raise RuntimeError( "Error: specified rotation angle is not an Angle instance!") if (target_pixel_scale < real_galaxy.pixel_scale): import warnings message = "Warning: requested pixel scale is higher resolution than original!" warnings.warn(message) import math # needed for pi, sqrt below g = math.sqrt(g1**2 + g2**2) if g > 1: raise RuntimeError("Error: requested shear is >1!") # make sure target PSF is normalized target_PSF.setFlux(1.0) real_galaxy_copy = real_galaxy.copy() # rotate if rotation_angle != None: real_galaxy_copy.applyRotation(rotation_angle) elif rotation_angle == None and rand_rotate == True: if rng == None: uniform_deviate = galsim.UniformDeviate() elif isinstance(rng, galsim.BaseDeviate): uniform_deviate = galsim.UniformDeviate(rng) else: raise TypeError( "The rng provided to drawShoot is not a BaseDeviate") rand_angle = galsim.Angle(math.pi * uniform_deviate(), galsim.radians) real_galaxy_copy.applyRotation(rand_angle) # set fluxes real_galaxy_copy.setFlux(target_flux) # shear if (g1 != 0.0 or g2 != 0.0): real_galaxy_copy.applyShear(g1=g1, g2=g2) # convolve, resample out_gal = galsim.Convolve([real_galaxy_copy, galsim.GSObject(target_PSF)]) image = out_gal.draw(image=image, dx=target_pixel_scale) # return simulated image return image
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))
def test_interpolated_image(): """Test various ways to build an InterpolatedImage """ imgdir = 'SBProfile_comparison_images' file_name = os.path.join(imgdir,'gauss_smallshear.fits') imgdir2 = 'fits_files' file_name2 = os.path.join(imgdir2,'interpim_hdu_test.fits') config = { 'gal1' : { 'type' : 'InterpolatedImage', 'image' : file_name }, 'gal2' : { 'type' : 'InterpolatedImage', 'image' : file_name, 'x_interpolant' : 'linear' }, 'gal3' : { 'type' : 'InterpolatedImage', 'image' : file_name, 'x_interpolant' : 'cubic', 'normalization' : 'sb', 'flux' : 1.e4 }, 'gal4' : { 'type' : 'InterpolatedImage', 'image' : file_name, 'x_interpolant' : 'lanczos5', 'scale' : 0.7, 'flux' : 1.e5 }, 'gal5' : { 'type' : 'InterpolatedImage', 'image' : file_name, 'noise_pad' : 0.001 }, 'gal6' : { 'type' : 'InterpolatedImage', 'image' : file_name, 'noise_pad' : 'fits_files/blankimg.fits' }, 'gal7' : { 'type' : 'InterpolatedImage', 'image' : file_name, 'pad_image' : 'fits_files/blankimg.fits' }, 'galmulti' : { 'type' : 'InterpolatedImage', 'image' : file_name2, 'hdu' : 2 } } rng = galsim.UniformDeviate(1234) config['rng'] = galsim.UniformDeviate(1234) # A second copy starting with the same seed. gal1a = galsim.config.BuildGSObject(config, 'gal1')[0] im = galsim.fits.read(file_name) gal1b = galsim.InterpolatedImage(im) gsobject_compare(gal1a, gal1b) gal2a = galsim.config.BuildGSObject(config, 'gal2')[0] gal2b = galsim.InterpolatedImage(im, x_interpolant=galsim.Linear()) gsobject_compare(gal2a, gal2b) gal3a = galsim.config.BuildGSObject(config, 'gal3')[0] gal3b = galsim.InterpolatedImage(im, x_interpolant=galsim.Cubic(), normalization='sb', flux=1.e4) gsobject_compare(gal3a, gal3b) gal4a = galsim.config.BuildGSObject(config, 'gal4')[0] interp = galsim.Lanczos(n=5, conserve_dc=True) gal4b = galsim.InterpolatedImage(im, x_interpolant=interp, scale=0.7, flux=1.e5) gsobject_compare(gal4a, gal4b) gal5a = galsim.config.BuildGSObject(config, 'gal5')[0] gal5b = galsim.InterpolatedImage(im, rng=rng, noise_pad=0.001) gsobject_compare(gal5a, gal5b) gal6a = galsim.config.BuildGSObject(config, 'gal6')[0] gal6b = galsim.InterpolatedImage(im, rng=rng, noise_pad='fits_files/blankimg.fits') gsobject_compare(gal6a, gal6b) gal7a = galsim.config.BuildGSObject(config, 'gal7')[0] gal7b = galsim.InterpolatedImage(im, pad_image = 'fits_files/blankimg.fits') gsobject_compare(gal7a, gal7b) # Now test the reading from some particular HDU galmulti = galsim.config.BuildGSObject(config, 'galmulti')[0] im = galmulti.drawImage(scale=0.2, method='no_pixel') test_g2 = im.FindAdaptiveMom().observed_shape.g2 np.testing.assert_almost_equal( test_g2, 0.7, decimal=3, err_msg='Did not get right shape image after reading InterpolatedImage from HDU')
posk = galsim.PositionD(kxvals[i], kyvals[i]) absoutk[i] = np.abs(testobj.kValue(posk)) print absoutk np.savetxt(os.path.join(dir,'absfKCubic_test.txt'), absoutk) # Then make a Quintic interpolant interp = galsim.InterpolantXY(galsim.Quintic(tol=1.e-4)) testobj = galsim.SBInterpolatedImage(image.view(), interp, dx=dx) for i in xrange(len(kxvals)): posk = galsim.PositionD(kxvals[i], kyvals[i]) absoutk[i] = np.abs(testobj.kValue(posk)) print absoutk np.savetxt(os.path.join(dir,'absfKQuintic_test.txt'), absoutk) # Then make a Lanczos5 interpolant interp = galsim.InterpolantXY(galsim.Lanczos(5, conserve_flux=False, tol=1.e-4)) testobj = galsim.SBInterpolatedImage(image.view(), interp, dx=dx) for i in xrange(len(kxvals)): posk = galsim.PositionD(kxvals[i], kyvals[i]) absoutk[i] = np.abs(testobj.kValue(posk)) print absoutk np.savetxt(os.path.join(dir,'absfKLanczos5_test.txt'), absoutk) # Then make a Lanczos7 interpolant interp = galsim.InterpolantXY(galsim.Lanczos(7, conserve_flux=False, tol=1.e-4)) testobj = galsim.SBInterpolatedImage(image.view(), interp, dx=dx) for i in xrange(len(kxvals)): posk = galsim.PositionD(kxvals[i], kyvals[i]) absoutk[i] = np.abs(testobj.kValue(posk)) print absoutk np.savetxt(os.path.join(dir,'absfKLanczos7_test.txt'), absoutk)
def test_conserve_dc(): """Test that the conserve_dc option for Lanczos does so. Note: the idea of conserving flux is a bit of a misnomer. No interpolant does so precisely in general. What we are really testing is that a flat background input image has a relatively flat output image. """ import time t1 = time.time() import numpy im1_size = 40 scale1 = 0.23 init_val = 1. im2_size = 100 scale2 = 0.011 im1 = galsim.ImageF(im1_size, im1_size, scale=scale1, init_value=init_val) # im2 has a much smaller scale, but the same size, so interpolating an "infinite" # constant field. im2 = galsim.ImageF(im2_size, im2_size, scale=scale2) for interp in ['linear', 'cubic', 'quintic']: print 'Testing interpolant ',interp obj = galsim.InterpolatedImage(im1, x_interpolant=interp, normalization='sb') obj.draw(im2, normalization='sb') print 'The maximum error is ',numpy.max(abs(im2.array-init_val)) numpy.testing.assert_array_almost_equal( im2.array,init_val,5, '%s did not preserve a flat input flux using xvals.'%interp) # Convolve with a delta function to force FFT drawing. delta = galsim.Gaussian(sigma=1.e-8) obj2 = galsim.Convolve([obj,delta]) obj2.draw(im2, normalization='sb') print 'The maximum error is ',numpy.max(abs(im2.array-init_val)) numpy.testing.assert_array_almost_equal( im2.array,init_val,5, '%s did not preserve a flat input flux using uvals.'%interp) for n in [3,4,5,6,7,8]: # 8 tests the generic formulae, since not specialized. print 'Testing Lanczos interpolant with n = ',n lan = galsim.Lanczos(n, conserve_dc=True) obj = galsim.InterpolatedImage(im1, x_interpolant=lan, normalization='sb') obj.draw(im2, normalization='sb') print 'The maximum error is ',numpy.max(abs(im2.array-init_val)) numpy.testing.assert_array_almost_equal( im2.array,init_val,5, 'Lanczos %d did not preserve a flat input flux using xvals.'%n) # Convolve with a delta function to force FFT drawing. delta = galsim.Gaussian(sigma=1.e-8) obj2 = galsim.Convolve([obj,delta]) obj2.draw(im2, normalization='sb') print 'The maximum error is ',numpy.max(abs(im2.array-init_val)) numpy.testing.assert_array_almost_equal( im2.array,init_val,5, 'Lanczos %d did not preserve a flat input flux using uvals.'%n) t2 = time.time() print 'time for %s = %.2f'%(funcname(),t2-t1)