def test_wcs(): """Reproduce an error Erin found and reported in #834. This was never an error in a released version, just temporarily on master, but the mistake hadn't been caught by any of our unit tests, so this test catches the error. """ wcs = galsim.JacobianWCS(0.01, -0.26, -0.28, -0.03) gal = galsim.Exponential(half_light_radius=1.1, flux=237) psf = galsim.Moffat(beta=3.5, half_light_radius=0.9) obs = galsim.Convolve(gal, psf) obs_im = obs.drawImage(nx=32, ny=32, offset=(0.3, -0.2), wcs=wcs) psf_im = psf.drawImage(nx=32, ny=32, wcs=wcs) ii = galsim.InterpolatedImage(obs_im) psf_ii = galsim.InterpolatedImage(psf_im) psf_inv = galsim.Deconvolve(psf_ii) ii_nopsf = galsim.Convolve(ii, psf_inv) newpsf = galsim.Moffat(beta=3.5, half_light_radius=0.95) newpsf = newpsf.dilate(1.02) new_ii = ii_nopsf.shear(g1=0.01, g2=0.0) new_ii = galsim.Convolve(new_ii, newpsf) new_im = new_ii.drawImage(image=obs_im.copy(), method='no_pixel') np.testing.assert_almost_equal(new_im.array.sum() / 237, obs_im.array.sum() / 237, decimal=1)
def test_fourier_sqrt(): """Test that the FourierSqrt operator is the inverse of auto-convolution. """ import time t1 = time.time() dx = 0.4 myImg1 = galsim.ImageF(80, 80, scale=dx) myImg1.setCenter(0, 0) myImg2 = galsim.ImageF(80, 80, scale=dx) myImg2.setCenter(0, 0) # Test trivial case, where we could (but don't) analytically collapse the # chain of SBProfiles by recognizing that FourierSqrt is the inverse of # AutoConvolve. psf = galsim.Moffat(beta=3.8, fwhm=1.3, flux=5) psf.drawImage(myImg1, method='no_pixel') sqrt1 = galsim.FourierSqrt(psf) psf2 = galsim.AutoConvolve(sqrt1) np.testing.assert_almost_equal(psf.stepK(), psf2.stepK()) psf2.drawImage(myImg2, method='no_pixel') printval(myImg1, myImg2) np.testing.assert_array_almost_equal( myImg1.array, myImg2.array, 4, err_msg="Moffat sqrt convolved with self disagrees with original") # Test non-trivial case where we compare (in Fourier space) sqrt(a*a + b*b + 2*a*b) against (a + b) a = galsim.Moffat(beta=3.8, fwhm=1.3, flux=5) a.shift(dx=0.5, dy=-0.3) # need nonzero centroid to test centroid() b = galsim.Moffat(beta=2.5, fwhm=1.6, flux=3) check = galsim.Sum([a, b]) sqrt = galsim.FourierSqrt( galsim.Sum([ galsim.AutoConvolve(a), galsim.AutoConvolve(b), 2 * galsim.Convolve([a, b]) ])) np.testing.assert_almost_equal(check.stepK(), sqrt.stepK()) check.drawImage(myImg1, method='no_pixel') sqrt.drawImage(myImg2, method='no_pixel') np.testing.assert_almost_equal(check.centroid().x, sqrt.centroid().x) np.testing.assert_almost_equal(check.centroid().y, sqrt.centroid().y) np.testing.assert_almost_equal(check.getFlux(), sqrt.getFlux()) printval(myImg1, myImg2) np.testing.assert_array_almost_equal( myImg1.array, myImg2.array, 4, err_msg="Fourier square root of expanded square disagrees with original" ) # Check picklability do_pickle(sqrt1.SBProfile, lambda x: (repr(x.getObj()), x.getGSParams())) do_pickle(sqrt1, lambda x: x.drawImage(method='no_pixel')) do_pickle(sqrt1) do_pickle(sqrt1.SBProfile) t2 = time.time() print('time for %s = %.2f' % (funcname(), t2 - t1))
def test_moffat_shoot(): """Test Moffat with photon shooting. Particularly the flux of the final image. """ rng = galsim.BaseDeviate(1234) obj = galsim.Moffat(fwhm=3.5, beta=4.7, flux=1.e4) im = galsim.Image(500,500, scale=1) im.setCenter(0,0) added_flux, photons = obj.drawPhot(im, poisson_flux=False, rng=rng.duplicate()) print('obj.flux = ',obj.flux) print('added_flux = ',added_flux) print('photon fluxes = ',photons.flux.min(),'..',photons.flux.max()) print('image flux = ',im.array.sum()) assert np.isclose(added_flux, obj.flux) assert np.isclose(im.array.sum(), obj.flux) photons2 = obj.makePhot(poisson_flux=False, rng=rng) assert photons2 == photons, "Moffat makePhot not equivalent to drawPhot" # Note: low beta has large wings, so don't go too low. Also, reduce fwhm a bit. obj = galsim.Moffat(fwhm=1.5, beta=1.9, flux=1.e4) added_flux, photons = obj.drawPhot(im, poisson_flux=False, rng=rng.duplicate()) print('obj.flux = ',obj.flux) print('added_flux = ',added_flux) print('photon fluxes = ',photons.flux.min(),'..',photons.flux.max()) print('image flux = ',im.array.sum()) assert np.isclose(added_flux, obj.flux) assert np.isclose(im.array.sum(), obj.flux) photons2 = obj.makePhot(poisson_flux=False, rng=rng) assert photons2 == photons, "Moffat makePhot not equivalent to drawPhot"
def make_psf(rng, iprof=None, scale=None, g1=None, g2=None, flux=10000): np_rng = np.random.default_rng(rng.raw()) # Pick from one of several plausible PSF profiles. psf_profs = [ galsim.Gaussian(fwhm=1.), galsim.Moffat(beta=1.5, fwhm=1.), galsim.Moffat(beta=4.5, fwhm=1.), galsim.Kolmogorov(fwhm=1.), galsim.Airy(lam=700, diam=4), galsim.Airy(lam=1200, diam=6.5, obscuration=0.6), galsim.OpticalPSF(lam=700, diam=4, obscuration=0.6, defocus=0.2, coma1=0.2, coma2=-0.2, astig1=-0.1, astig2=0.1), galsim.OpticalPSF(lam=900, diam=2.1, obscuration=0.2, aberrations=[ 0, 0, 0, 0, -0.1, 0.2, -0.15, -0.1, 0.15, 0.1, 0.15, -0.2 ]), galsim.OpticalPSF(lam=1200, diam=6.5, obscuration=0.3, aberrations=[ 0, 0, 0, 0, 0.2, 0.1, 0.15, -0.1, -0.15, -0.2, 0.1, 0.15 ]), ] # The last 5 need an atmospheric part, or else they don't much resemble the kinds of # PSF profiles we actually care about. psf_profs[-5:] = [ galsim.Convolve(galsim.Kolmogorov(fwhm=0.6), p) for p in psf_profs[-5:] ] if iprof is None: psf = np_rng.choice(psf_profs) else: psf = psf_profs[iprof] # Choose a random size and shape within reasonable ranges. if g1 is None: g1 = np_rng.uniform(-0.03, 0.03) if g2 is None: g2 = np_rng.uniform(-0.03, 0.03) if scale is None: # Note: Don't go too small, since hsm fails more often for size close to pixel_scale. scale = np.exp(np_rng.uniform(-0.3, 1.0)) psf = psf.dilate(scale).shear(g1=g1, g2=g2).withFlux(flux) return psf
def get_profile(self, params): if 'psf_fwhm' in params: return galsim.Moffat(beta=params['psf_beta'], fwhm=params['psf_fwhm'], flux=params['psf_flux']) elif 'psf_hlr' in params: return galsim.Moffat(beta=params['psf_beta'], half_light_radius=params['psf_hlr'], flux=params['psf_flux'])
def test_moffat_flux_scaling(): """Test flux scaling for Moffat. """ # decimal point to go to for parameter value comparisons param_decimal = 12 test_scale = 1.8 test_flux = 17.9 for test_beta in [ 1.5, 2., 2.5, 3., 3.8 ]: for test_trunc in [ 0., 8.5 ]: # init with scale_radius only (should be ok given last tests) obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj *= 2. np.testing.assert_almost_equal( obj.flux, test_flux * 2., decimal=param_decimal, err_msg="Flux param inconsistent after __imul__.") obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj /= 2. np.testing.assert_almost_equal( obj.flux, test_flux / 2., decimal=param_decimal, err_msg="Flux param inconsistent after __idiv__.") obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj2 = obj * 2. # First test that original obj is unharmed... np.testing.assert_almost_equal( obj.flux, test_flux, decimal=param_decimal, err_msg="Flux param inconsistent after __rmul__ (original).") # Then test new obj2 flux np.testing.assert_almost_equal( obj2.flux, test_flux * 2., decimal=param_decimal, err_msg="Flux param inconsistent after __rmul__ (result).") obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj2 = 2. * obj # First test that original obj is unharmed... np.testing.assert_almost_equal( obj.flux, test_flux, decimal=param_decimal, err_msg="Flux param inconsistent after __mul__ (original).") # Then test new obj2 flux np.testing.assert_almost_equal( obj2.flux, test_flux * 2., decimal=param_decimal, err_msg="Flux param inconsistent after __mul__ (result).") obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj2 = obj / 2. # First test that original obj is unharmed... np.testing.assert_almost_equal( obj.flux, test_flux, decimal=param_decimal, err_msg="Flux param inconsistent after __div__ (original).") # Then test new obj2 flux np.testing.assert_almost_equal( obj2.flux, test_flux / 2., decimal=param_decimal, err_msg="Flux param inconsistent after __div__ (result).")
def test_moffat_properties(): """Test some basic properties of the Moffat profile. """ # Code was formerly: # psf = galsim.Moffat(beta=2.0, truncationFWHM=2, flux=test_flux, half_light_radius=1) # # ...but this is no longer quite so simple since we changed the handling of trunc to be in # physical units. However, the same profile can be constructed using # fwhm=1.4686232496771867, # as calculated by interval bisection in devutils/external/calculate_moffat_radii.py test_flux = 1.8 fwhm_backwards_compatible = 1.4686232496771867 psf = galsim.Moffat(beta=2.0, fwhm=fwhm_backwards_compatible, trunc=2 * fwhm_backwards_compatible, flux=test_flux) # Check that we are centered on (0, 0) cen = galsim.PositionD(0, 0) np.testing.assert_equal(psf.centroid, cen) # Check Fourier properties np.testing.assert_almost_equal(psf.maxk, 11.613036117918105) np.testing.assert_almost_equal(psf.stepk, 0.62831853071795873) np.testing.assert_almost_equal(psf.kValue(cen), test_flux + 0j) np.testing.assert_almost_equal(psf.half_light_radius, 1.0) np.testing.assert_almost_equal(psf.fwhm, fwhm_backwards_compatible) np.testing.assert_almost_equal(psf.xValue(cen), 0.50654651638242509) np.testing.assert_almost_equal(psf.kValue(cen), (1 + 0j) * test_flux) np.testing.assert_almost_equal(psf.flux, test_flux) np.testing.assert_almost_equal(psf.xValue(cen), psf.max_sb) # Now create the same profile using the half_light_radius: psf = galsim.Moffat(beta=2.0, half_light_radius=1., trunc=2 * fwhm_backwards_compatible, flux=test_flux) np.testing.assert_equal(psf.centroid, cen) np.testing.assert_almost_equal(psf.maxk, 11.613036112206663) np.testing.assert_almost_equal(psf.stepk, 0.62831853071795862) np.testing.assert_almost_equal(psf.kValue(cen), test_flux + 0j) np.testing.assert_almost_equal(psf.half_light_radius, 1.0) np.testing.assert_almost_equal(psf.fwhm, fwhm_backwards_compatible) np.testing.assert_almost_equal(psf.xValue(cen), 0.50654651638242509) np.testing.assert_almost_equal(psf.kValue(cen), (1 + 0j) * test_flux) np.testing.assert_almost_equal(psf.flux, test_flux) np.testing.assert_almost_equal(psf.xValue(cen), psf.max_sb) # Check input flux vs output flux for inFlux in np.logspace(-2, 2, 10): psfFlux = galsim.Moffat(2.0, fwhm=fwhm_backwards_compatible, trunc=2 * fwhm_backwards_compatible, flux=inFlux) outFlux = psfFlux.flux np.testing.assert_almost_equal(outFlux, inFlux)
def test_moffat_flux_scaling(): """Test flux scaling for Moffat. """ import time t1 = time.time() # init with scale_radius only (should be ok given last tests) obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj *= 2. np.testing.assert_almost_equal( obj.getFlux(), test_flux * 2., decimal=param_decimal, err_msg="Flux param inconsistent after __imul__.") obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj /= 2. np.testing.assert_almost_equal( obj.getFlux(), test_flux / 2., decimal=param_decimal, err_msg="Flux param inconsistent after __idiv__.") obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj2 = obj * 2. # First test that original obj is unharmed... (also tests that .copy() is working) np.testing.assert_almost_equal( obj.getFlux(), test_flux, decimal=param_decimal, err_msg="Flux param inconsistent after __rmul__ (original).") # Then test new obj2 flux np.testing.assert_almost_equal( obj2.getFlux(), test_flux * 2., decimal=param_decimal, err_msg="Flux param inconsistent after __rmul__ (result).") obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj2 = 2. * obj # First test that original obj is unharmed... (also tests that .copy() is working) np.testing.assert_almost_equal( obj.getFlux(), test_flux, decimal=param_decimal, err_msg="Flux param inconsistent after __mul__ (original).") # Then test new obj2 flux np.testing.assert_almost_equal( obj2.getFlux(), test_flux * 2., decimal=param_decimal, err_msg="Flux param inconsistent after __mul__ (result).") obj = galsim.Moffat(scale_radius=test_scale, beta=test_beta, trunc=test_trunc, flux=test_flux) obj2 = obj / 2. # First test that original obj is unharmed... (also tests that .copy() is working) np.testing.assert_almost_equal( obj.getFlux(), test_flux, decimal=param_decimal, err_msg="Flux param inconsistent after __div__ (original).") # Then test new obj2 flux np.testing.assert_almost_equal( obj2.getFlux(), test_flux / 2., decimal=param_decimal, err_msg="Flux param inconsistent after __div__ (result).") t2 = time.time() print 'time for %s = %.2f'%(funcname(),t2-t1)
def time_moffat_shoot(): """Shoot photons through a Moffat profile recording times for comparison between USE_COS_SIN method in SBProfile.cpp and the unit circle rejection method. """ logger = logging.getLogger("time_moffat") # Initialize the random number generator we will be using. rng = galsim.UniformDeviate(RANDOM_SEED) # Build the image for drawing the galaxy into image = galsim.ImageF(IMAGE_XMAX, IMAGE_YMAX, PIXEL_SCALE) # Start the timer t1 = time.time() for i in range(NIMAGES): # Build the galaxy gal = galsim.Moffat(beta=MOFFAT_BETA, scale_radius=MOFFAT_SCALE_RADIUS) # Build the image for drawing the galaxy into image = galsim.ImageF(IMAGE_XMAX, IMAGE_YMAX) # Shoot the galaxy gal.drawShoot(image, NPHOTONS) # Get the time t2 = time.time() logger.info( 'time_moffat_shoot: NIMAGES = %d, NPHOTONS = %d, total time = %f sec', NIMAGES, NPHOTONS, t2-t1 )
def test_realspace_distorted_convolve(): """ The same as above, but both the Moffat and the Box are sheared, rotated and shifted to stress test the code that deals with this for real-space convolutions that wouldn't be tested otherwise. """ import time t1 = time.time() dx = 0.2 saved_img = galsim.fits.read(os.path.join(imgdir, "moffat_pixel_distorted.fits")) img = galsim.ImageF(saved_img.bounds, scale=dx) img.setCenter(0,0) fwhm_backwards_compatible = 1.0927449310213702 psf = galsim.Moffat(beta=1.5, half_light_radius=1, trunc=4*fwhm_backwards_compatible, flux=1) #psf = galsim.Moffat(beta=1.5, fwhm=fwhm_backwards_compatible, #trunc=4*fwhm_backwards_compatible, flux=1) psf = psf.shear(g1=0.11,g2=0.17).rotate(13 * galsim.degrees) pixel = galsim.Pixel(scale=dx, flux=1.) pixel = pixel.shear(g1=0.2,g2=0.0).rotate(80 * galsim.degrees).shift(0.13,0.27) # NB: real-space is chosen automatically conv = galsim.Convolve([psf,pixel]) conv.drawImage(img,scale=dx, method="sb", use_true_center=False) np.testing.assert_array_almost_equal( img.array, saved_img.array, 5, err_msg="Using Convolve([psf,pixel]) (distorted) disagrees with expected result") # Check with default_params conv = galsim.Convolve([psf,pixel],gsparams=default_params) conv.drawImage(img,scale=dx, method="sb", use_true_center=False) np.testing.assert_array_almost_equal( img.array, saved_img.array, 5, err_msg="Using Convolve([psf,pixel]) (distorted) with default_params disagrees with " "expected result") conv = galsim.Convolve([psf,pixel],gsparams=galsim.GSParams()) conv.drawImage(img,scale=dx, method="sb", use_true_center=False) np.testing.assert_array_almost_equal( img.array, saved_img.array, 5, err_msg="Using Convolve([psf,pixel]) (distorted) with GSParams() disagrees with " "expected result") # Other ways to do the convolution: conv = galsim.Convolve(psf,pixel) conv.drawImage(img,scale=dx, method="sb", use_true_center=False) np.testing.assert_array_almost_equal( img.array, saved_img.array, 5, err_msg="Using Convolve(psf,pixel) (distorted) disagrees with expected result") # The real-space convolution algorithm is not (trivially) independent of the order of # the two things being convolved. So check the opposite order. conv = galsim.Convolve([pixel,psf]) conv.drawImage(img,scale=dx, method="sb", use_true_center=False) np.testing.assert_array_almost_equal( img.array, saved_img.array, 5, err_msg="Using Convolve([pixel,psf]) (distorted) disagrees with expected result") t2 = time.time() print 'time for %s = %.2f'%(funcname(),t2-t1)
def test_comparison_object(np): logging.basicConfig(level=logging.WARNING, stream=sys.stdout) logger = logging.getLogger("test_comparison_object") logger.info("Running basic tests of comparison scripts using objects") # Build a trial galaxy gal = galsim.Sersic(galn, half_light_radius=galhlr) gal.applyShear(g1=g1gal, g2=g2gal) # And an example PSF psf = galsim.Moffat(beta=psfbeta, fwhm=psffwhm) psf.applyShear(g1=g1psf, g2=g2psf) # Try a single core run print "Starting tests using config file with N_PHOTONS = " + str(np) res1 = galsim.utilities.compare_dft_vs_photon_object( gal, psf_object=psf, rng=galsim.BaseDeviate(rseed), size=imsize, pixel_scale=dx, abs_tol_ellip=tol_ellip, abs_tol_size=tol_size, n_photons_per_trial=np) print res1 return
def _get_atm(self, x, y): xs = (x + 1 - self._im_cen) * self._scale ys = (y + 1 - self._im_cen) * self._scale g1, g2, mu = self._get_lensing((xs, ys)) if g1 * g1 + g2 * g2 >= 1.0: norm = np.sqrt(g1 * g1 + g2 * g2) / 0.5 g1 /= norm g2 /= norm fwhm = self._fwhm_central / np.power(mu, 0.75) psf = galsim.Moffat(beta=2.5, fwhm=fwhm).shear(g1=g1 + self._g1_mean, g2=g2 + self._g2_mean) gs_config = {} gs_config["type"] = "Moffat" gs_config["fwhm"] = fwhm gs_config["beta"] = 2.5 gs_config["shear"] = { "type": "G1G2", "g1": g1 + self._g1_mean, "g2": g2 + self._g2_mean, } return psf, gs_config
def makeStars(nstar, beta, size=None, g1=None, g2=None, seed=12345): rng = galsim.BaseDeviate(seed) np_rng = np.random.default_rng(seed) flux = 1.e6 sky_level = 200.0 # For noise # Use a random DECam CCD for the wcs decaminfo = piff.des.DECamInfo() wcs = decaminfo.get_nominal_wcs(chipnum=10) # pick random size, shape if not given if size is None: size = np_rng.uniform(0.5, 0.9, nstar) else: size = np.array([size] * nstar) if g1 is None: g1 = np_rng.uniform(-0.1, 0.1, nstar) else: g1 = np.array([g1] * nstar) if g2 is None: g2 = np_rng.uniform(-0.1, 0.1, nstar) else: g2 = np.array([g2] * nstar) noiseless_stars = [] noisy_stars = [] for i in range(nstar): # Use Moffat profile prof = galsim.Moffat(half_light_radius=size[i], beta=beta).shear(g1=g1[i], g2=g2[i]) # make the star with no noise. noiseless_star = piff.Star.makeTarget(x=0, y=0, wcs=wcs, stamp_size=19) prof = prof.shift(noiseless_star.fit.center).withFlux(flux) im = noiseless_star.image prof.drawImage(image=im, center=noiseless_star.image_pos) noiseless_stars.append(noiseless_star) # Generate a Poisson noise model, with some foreground (assumes that this foreground # was already subtracted) poisson_noise = galsim.PoissonNoise(rng, sky_level=sky_level) im = im.copy() im.addNoise(poisson_noise) # adds in place # get new weight in photo-electrons (not an array) inverse_weight = im + sky_level weight = 1.0 / inverse_weight # make new noisy star by resetting data in the noiseless star noisy_star = copy.deepcopy(noiseless_star) noisy_star.data.image = im noisy_star.data.weight = weight noisy_stars.append(noisy_star) return noiseless_stars, noisy_stars
def hlr_root_fwhm(fwhm, beta=2., truncationFWHM=2., flux=1., half_light_radius=1.): m = galsim.Moffat(beta=beta, fwhm=fwhm, flux=flux, trunc=truncationFWHM * fwhm) return (m.getHalfLightRadius() - half_light_radius)
def __init__(self, beta, trunc=0., fastfit=False, centered=True, include_pixel=True, scipy_kwargs=None, logger=None): gsobj = galsim.Moffat(half_light_radius=1.0, beta=beta, trunc=trunc) GSObjectModel.__init__(self, gsobj, fastfit, centered, include_pixel, scipy_kwargs, logger) # We'd need self.kwargs['gsobj'] if we were reconstituting via the GSObjectModel # constructor, but since config['type'] for this will be Moffat, it gets reconstituted # here, where there is no `gsobj` argument. So remove `gsobj` from kwargs. del self.kwargs['gsobj'] # Need to add `beta` and `trunc` though. self.kwargs.update(dict(beta=beta, trunc=trunc))
def test_fail(): # Some vv noisy images that result in errors in the fit to check the error reporting. scale = 1.3 g1 = 0.33 g2 = -0.27 flux = 15 noise = 2. seed = 1234 psf = galsim.Moffat(half_light_radius=1.0, beta=2.5, trunc=3.0) psf = psf.dilate(scale).shear(g1=g1, g2=g2).withFlux(flux) image = psf.drawImage(nx=64, ny=64, scale=0.3) weight = image.copy() weight.fill(1 / noise**2) noisy_image = image.copy() rng = galsim.BaseDeviate(seed) noisy_image.addNoise(galsim.GaussianNoise(sigma=noise, rng=rng)) star1 = piff.Star(piff.StarData(image, image.true_center, weight), None) star2 = piff.Star(piff.StarData(noisy_image, image.true_center, weight), None) model1 = piff.Moffat(fastfit=True, beta=2.5) with np.testing.assert_raises(RuntimeError): model1.initialize(star2) with np.testing.assert_raises(RuntimeError): model1.fit(star2) star3 = model1.initialize(star1) star3 = model1.fit(star3) star3 = piff.Star(star2.data, star3.fit) with np.testing.assert_raises(RuntimeError): model1.fit(star3) # This is contrived to hit the fit failure for the reference. # I'm not sure what realistic use case would actually hit it, but at least it's # theoretically possible to fail there. model2 = piff.GSObjectModel(galsim.InterpolatedImage(noisy_image), fastfit=True) with np.testing.assert_raises(RuntimeError): model2.initialize(star1) model3 = piff.Moffat(fastfit=False, beta=2.5, scipy_kwargs={'max_nfev': 10}) with np.testing.assert_raises(RuntimeError): model3.initialize(star2) with np.testing.assert_raises(RuntimeError): model3.fit(star2).fit star3 = model3.initialize(star1) star3 = model3.fit(star3) star3 = piff.Star(star2.data, star3.fit) with np.testing.assert_raises(RuntimeError): model3.fit(star3)
def sample(args, do_series=False): """ Generate MCMC (emcee) samples from arguments specified in args. @param series Boolean controlling whether or not to use series approx. @returns post-sampling emcee sampler object. """ # 3 random number generators to seed bd = galsim.BaseDeviate(args.image_seed) # for GalSim rstate = np.random.mtrand.RandomState(args.sample_seed + args.jmax).get_state() # for emcee np.random.seed(args.sample_seed + args.jmax) # for numpy functions called outside of emcee nwalkers = args.nwalkers nsteps = args.nsteps ndim = 6 p_initial = [args.x0, args.y0, args.HLR, args.flux, args.e1, args.e2] # x0, y0, HLR, flux, e1, e2 p_std = [0.01, 0.01, 0.01, args.flux * 0.01, 0.01, 0.01] x0, y0, HLR, flux, e1, e2 = p_initial psf = galsim.Moffat(beta=3, fwhm=args.PSF_FWHM) gal = galsim.Spergel(nu=args.nu, half_light_radius=args.HLR, flux=args.flux) gal = gal.shear(e1=args.e1, e2=args.e2) gal = gal.shift(args.x0, args.y0) final = galsim.Convolve(gal, psf) target_image = final.drawImage(nx=args.nx, ny=args.ny, scale=args.scale) noise = galsim.GaussianNoise(rng=bd) if args.noisy_image: noisevar = target_image.addNoiseSNR(noise, args.SNR, preserve_flux=True) else: dummy_image = target_image.copy() noisevar = dummy_image.addNoiseSNR(noise, args.SNR, preserve_flux=True) p0 = np.empty((nwalkers, ndim), dtype=float) todo = np.ones(nwalkers, dtype=bool) lnp_args = [target_image, noisevar, args, do_series] while len(todo) > 0: p0[todo] = [ p_initial + p_std * np.random.normal(size=ndim) for i in range(len(todo)) ] todo = np.nonzero([not np.isfinite(lnprob(p, *lnp_args)) for p in p0])[0] sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob, args=lnp_args) sampler.run_mcmc(p0, nsteps, rstate0=rstate) return sampler
def generate_core(self): """ Generate Galsim PSF of core. """ gamma, beta = self.gamma, self.beta self.fwhm = fwhm = gamma * 2. * math.sqrt(2**(1. / beta) - 1) psf_core = galsim.Moffat(beta=beta, fwhm=fwhm, flux=1., gsparams=self.gsparams) # in arcsec self.psf_core = psf_core return psf_core
def _create_psf(self, g1, g2, fwhm=0.65): """Create Moffat """ beta = 4.765 # Value from https://arxiv.org/pdf/astro-ph/0109067.pdf psf = galsim.Moffat(beta=beta, fwhm=fwhm).withFlux(1) psf = psf.shear(g1=g1, g2=g2) return psf
def _set_psf(self): import galsim model = self['psf']['model'] assert model in ['gauss', 'moffat'] if model == 'gauss': self.psf = galsim.Gaussian(fwhm=self['psf']['fwhm'], ) elif model == 'moffat': self.psf = galsim.Moffat( self['psf']['beta'], fwhm=self['psf']['fwhm'], )
def test_moffat_shoot(): """Test Moffat with photon shooting. Particularly the flux of the final image. """ rng = galsim.BaseDeviate(1234) obj = galsim.Moffat(fwhm=3.5, beta=4.7, flux=1.e4) im = galsim.Image(500, 500, scale=1) im.setCenter(0, 0) added_flux, photons = obj.drawPhot(im, poisson_flux=False, rng=rng.duplicate()) print('obj.flux = ', obj.flux) print('added_flux = ', added_flux) print('photon fluxes = ', photons.flux.min(), '..', photons.flux.max()) print('image flux = ', im.array.sum()) assert np.isclose(added_flux, obj.flux) assert np.isclose(im.array.sum(), obj.flux) photons2 = obj.makePhot(poisson_flux=False, rng=rng) assert photons2 == photons, "Moffat makePhot not equivalent to drawPhot" # Note: low beta has large wings, so don't go too low. Also, reduce fwhm a bit. obj = galsim.Moffat(fwhm=1.5, beta=1.9, flux=1.e4) added_flux, photons = obj.drawPhot(im, poisson_flux=False, rng=rng.duplicate()) print('obj.flux = ', obj.flux) print('added_flux = ', added_flux) print('photon fluxes = ', photons.flux.min(), '..', photons.flux.max()) print('image flux = ', im.array.sum()) assert np.isclose(added_flux, obj.flux) assert np.isclose(im.array.sum(), obj.flux) photons2 = obj.makePhot(poisson_flux=False, rng=rng.duplicate()) assert photons2 == photons, "Moffat makePhot not equivalent to drawPhot" # Can treat the profile as a convolution of a delta function and put it in a photon_ops list. delta = galsim.DeltaFunction(flux=1.e4) psf = galsim.Moffat(fwhm=1.5, beta=1.9) photons3 = delta.makePhot(poisson_flux=False, rng=rng.duplicate(), photon_ops=[psf]) assert photons3 == photons, "Using Moffat in photon_ops not equivalent to drawPhot"
def test_op(rw, op): print(op) rw1 = eval('rw.' + op) rw2 = eval('super(galsim.RandomKnots,rw).' + op) # Need to convolve by a psf to get reasonable results for fft drawing. psf = galsim.Moffat(beta=1.5, fwhm=0.9) conv1 = galsim.Convolve(rw1, psf) conv2 = galsim.Convolve(rw2, psf) im1 = conv1.drawImage(nx=16, ny=16, scale=0.3) im2 = conv2.drawImage(nx=16, ny=16, scale=0.3) np.testing.assert_almost_equal(im1.array, im2.array, decimal=3, err_msg='RandomKnots with op '+op)
def makeFinal(data, fluxRatio, bulge, disk): totalFlux = 4.8 psf_FWHM, psf_beta = 0.6, 2.5 bulgeMultiplier = fluxRatio * totalFlux diskMultiplier = (1 - fluxRatio) * totalFlux bdgal = 1.1 * (bulgeMultiplier * bulge + diskMultiplier * disk) PSF = galsim.Moffat(fwhm=psf_FWHM, beta=psf_beta) #PSF = galsim.Gaussian(fwhm=psf_FWHM) img = galsim.ImageF(data.imageSize, data.imageSize, scale=data.pixel_scale) psfImage = PSF.drawImage(image=img) psfImage.write("PSF.fits") bdfinal = galsim.Convolve([bdgal, PSF]) return bdfinal
def test_shapelet_fit(): """Test fitting a Shapelet decomposition of an image """ import time t1 = time.time() for method, norm in [('no_pixel','f'), ('sb','sb')]: # We fit a shapelet approximation of a distorted Moffat profile: flux = 20 psf = galsim.Moffat(beta=3.4, half_light_radius=1.2, flux=flux) psf = psf.shear(g1=0.11,g2=0.07).shift(0.03,0.04) scale = 0.2 pixel = galsim.Pixel(scale) conv = galsim.Convolve([psf,pixel]) im1 = conv.drawImage(scale=scale, method=method) sigma = 1.2 # Match half-light-radius as a decent first approximation. shapelet = galsim.FitShapelet(sigma, 10, im1, normalization=norm) print 'fitted shapelet coefficients = ',shapelet.bvec # Check flux print 'flux = ',shapelet.getFlux(),' cf. ',flux np.testing.assert_almost_equal(shapelet.getFlux() / flux, 1., 1, err_msg="Fitted shapelet has the wrong flux") # Test centroid print 'centroid = ',shapelet.centroid(),' cf. ',conv.centroid() np.testing.assert_almost_equal(shapelet.centroid().x, conv.centroid().x, 2, err_msg="Fitted shapelet has the wrong centroid (x)") np.testing.assert_almost_equal(shapelet.centroid().y, conv.centroid().y, 2, err_msg="Fitted shapelet has the wrong centroid (y)") # Test drawing image from shapelet im2 = im1.copy() shapelet.drawImage(im2, method=method) # Check that images are close to the same: print 'norm(diff) = ',np.sum((im1.array-im2.array)**2) print 'norm(im) = ',np.sum(im1.array**2) assert np.sum((im1.array-im2.array)**2) < 1.e-3 * np.sum(im1.array**2) # Remeasure -- should now be very close to the same. shapelet2 = galsim.FitShapelet(sigma, 10, im2, normalization=norm) np.testing.assert_equal(shapelet.sigma, shapelet2.sigma, err_msg="Second fitted shapelet has the wrong sigma") np.testing.assert_equal(shapelet.order, shapelet2.order, err_msg="Second fitted shapelet has the wrong order") np.testing.assert_almost_equal(shapelet.bvec, shapelet2.bvec, 6, err_msg="Second fitted shapelet coefficients do not match original") t2 = time.time() print 'time for %s = %.2f'%(funcname(),t2-t1)
def _set_psf(self, obs, psf_in): if isinstance(psf_in, dict): assert psf_in['model'] == 'moffat' pars = psf_in['pars'] psf_obj = galsim.Moffat( beta=pars['beta'], fwhm=pars['fwhm'], #flux=float(flux), ) else: psf_obj = psf_in self.psf_obj = psf_obj
def __generatePSF(self, eMin, eMax): # Define the PSF profile self.psf = galsim.Moffat(beta=self.psfData.beta, fwhm=self.psfData.fwhm, trunc=self.psfData.trunc) e1 = self.psfData.e1 e2 = self.psfData.e2 re = self.psf.half_light_radius if self.randomShear: e1 = self.randomFloat(eMin, eMax) e2 = self.randomFloat(eMin, eMax) self.psf = self.psf.shear(e1 = e1, e2 = e2) return (e1, e2, re)
def test_ne(): """Test base.py GSObjects for not-equals.""" # Define some universal gsps gsp = galsim.GSParams(maxk_threshold=1.1e-3, folding_threshold=5.1e-3) # Moffat. Params include beta, scale_radius, half_light_radius, fwhm, trunc, flux and gsparams. # The following should all test unequal: gals = [galsim.Moffat(beta=3.0, scale_radius=1.0), galsim.Moffat(beta=3.1, scale_radius=1.1), galsim.Moffat(beta=3.0, scale_radius=1.1), galsim.Moffat(beta=3.0, half_light_radius=1.2), galsim.Moffat(beta=3.0, fwhm=1.3), galsim.Moffat(beta=3.0, scale_radius=1.1, trunc=2.0), galsim.Moffat(beta=3.0, scale_radius=1.0, flux=1.1), galsim.Moffat(beta=3.0, scale_radius=1.0, gsparams=gsp)] all_obj_diff(gals)
def test_moffat(): """Test various ways to build a Moffat """ config = { 'gal1' : { 'type' : 'Moffat' , 'beta' : 1.4, 'scale_radius' : 2 }, 'gal2' : { 'type' : 'Moffat' , 'beta' : 3.5, 'fwhm' : 2, 'trunc' : 5, 'flux' : 100 }, 'gal3' : { 'type' : 'Moffat' , 'beta' : 2.2, 'half_light_radius' : 2, 'flux' : 1.e6, 'ellip' : { 'type' : 'QBeta' , 'q' : 0.6, 'beta' : 0.39 * galsim.radians } }, 'gal4' : { 'type' : 'Moffat' , 'beta' : 1.7, 'fwhm' : 1, 'flux' : 50, 'dilate' : 3, 'ellip' : galsim.Shear(e1=0.3), 'rotate' : 12 * galsim.degrees, 'magnify' : 1.03, 'shear' : galsim.Shear(g1=0.03, g2=-0.05), 'shift' : { 'type' : 'XY', 'x' : 0.7, 'y' : -1.2 } }, 'gal5' : { 'type' : 'Moffat' , 'beta' : 2.8, 'flux' : 22, 'fwhm' : 0.2, 'trunc' : 0.7, 'shear' : galsim.Shear(g1=-0.15, g2=0.2), 'gsparams' : { 'maxk_threshold' : 1.e-2 } }, } gal1a = galsim.config.BuildGSObject(config, 'gal1')[0] gal1b = galsim.Moffat(beta = 1.4, scale_radius = 2) gsobject_compare(gal1a, gal1b) gal2a = galsim.config.BuildGSObject(config, 'gal2')[0] gal2b = galsim.Moffat(beta = 3.5, fwhm = 2, trunc = 5, flux = 100) gsobject_compare(gal2a, gal2b) gal3a = galsim.config.BuildGSObject(config, 'gal3')[0] gal3b = galsim.Moffat(beta = 2.2, half_light_radius = 2, flux = 1.e6) gal3b = gal3b.shear(q = 0.6, beta = 0.39 * galsim.radians) gsobject_compare(gal3a, gal3b) gal4a = galsim.config.BuildGSObject(config, 'gal4')[0] gal4b = galsim.Moffat(beta = 1.7, fwhm = 1, flux = 50) gal4b = gal4b.dilate(3).shear(e1 = 0.3).rotate(12 * galsim.degrees).magnify(1.03) gal4b = gal4b.shear(g1 = 0.03, g2 = -0.05).shift(dx = 0.7, dy = -1.2) gsobject_compare(gal4a, gal4b) gal5a = galsim.config.BuildGSObject(config, 'gal5')[0] # Note: this needs to be rather small otherwise maxk_threshold is obviated by other # adjustments we make to the parameters in SBProfile.cpp gsparams = galsim.GSParams(maxk_threshold=1.e-2) gal5b = galsim.Moffat(beta=2.8, fwhm=0.2, flux=22, trunc=0.7, gsparams=gsparams) gal5b = gal5b.shear(g1=-0.15, g2=0.2) # convolve to test the k-space gsparams (with an even smaller profile) gsobject_compare(gal5a, gal5b, conv=galsim.Gaussian(sigma=0.01)) try: # Make sure they don't match when using the default GSParams gal5c = galsim.Moffat(beta=2.8, fwhm=0.3, flux=22, trunc=0.7) gal5c = gal5c.shear(g1=-0.15, g2=0.2) np.testing.assert_raises(AssertionError,gsobject_compare, gal5a, gal5c, conv=galsim.Gaussian(sigma=0.01)) except ImportError: print('The assert_raises tests require nose')
def _set_psf(self, obs, psf_in): if isinstance(psf_in, dict): if psf_in['model'] == 'gauss': psf_obj = galsim.Gaussian(fwhm=psf_in['pars']['fwhm'], ) elif psf_in['model'] == 'moffat': psf_obj = galsim.Moffat( beta=psf_in['pars']['beta'], fwhm=psf_in['pars']['fwhm'], ) else: raise ValueError("bad psf: %s" % psf_in['model']) else: psf_obj = psf_in self.psf_obj = psf_obj
def test_ml_fitting_galsim_moffat_smoke(): rng = np.random.RandomState(seed=2312) scale = 0.263 fwhm = 0.9 beta = 2.5 image_size = 33 flux = 1.0 noise = 1.0e-5 moff = galsim.Moffat(fwhm=fwhm, beta=beta, flux=flux) im = moff.drawImage( nx=image_size, ny=image_size, scale=scale, ).array im += rng.normal(scale=noise, size=im.shape) weight = im * 0 + 1.0 / noise**2 cen = (image_size - 1.0) / 2.0 jac = ngmix.DiagonalJacobian( y=cen, x=cen, scale=scale, ) obs = ngmix.Observation( image=im, weight=weight, jacobian=jac, ) fitter = ngmix.fitting.GalsimMoffatFitter() guess = np.zeros(7) guess[0] = rng.uniform(low=-0.1, high=0.1) guess[1] = rng.uniform(low=-0.1, high=0.1) guess[2] = rng.uniform(low=-0.1, high=0.1) guess[3] = rng.uniform(low=-0.1, high=0.1) guess[4] = moff.half_light_radius * rng.uniform(low=0.9, high=1.1) guess[5] = rng.uniform(low=1.5, high=3) guess[6] = flux * rng.uniform(low=0.9, high=1.1) res = fitter.go(obs=obs, guess=guess) assert res['flags'] == 0