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 test_var(): """Check that the variance estimate in params_var is sane. """ # Here is the true PSF scale = 1.3 g1 = 0.23 g2 = -0.17 du = 0.1 dv = 0.4 flux = 500 wcs = galsim.JacobianWCS(0.26, 0.05, -0.08, -0.29) noise = 0.2 gsobjs = [ galsim.Gaussian(sigma=1.0), galsim.Kolmogorov(half_light_radius=1.0), galsim.Moffat(half_light_radius=1.0, beta=3.0), galsim.Moffat(half_light_radius=1.0, beta=2.5, trunc=3.0) ] # Mix of centered = True/False, # fastfit = True/False, # include_pixel = True/False models = [ piff.Gaussian(fastfit=False, include_pixel=False, centered=False), piff.Kolmogorov(fastfit=True, include_pixel=True, centered=False), piff.Moffat(fastfit=False, beta=4.8, include_pixel=True, centered=True), piff.Moffat(fastfit=True, beta=2.5, trunc=3.0, include_pixel=False, centered=True) ] names = ['Gaussian', 'Kolmogorov', 'Moffat3', 'Moffat2.5'] for gsobj, model, name in zip(gsobjs, models, names): print() print("gsobj = ", gsobj) print() psf = gsobj.dilate(scale).shear(g1=g1, g2=g2).shift(du, dv).withFlux(flux) image = psf.drawImage(nx=64, ny=64, wcs=wcs, method='no_pixel') weight = image.copy() weight.fill(1 / noise**2) # Save this one without noise. image1 = image.copy() image1.addNoise(galsim.GaussianNoise(sigma=noise)) # Make a StarData instance for this image stardata = piff.StarData(image, image.true_center, weight) star = piff.Star(stardata, None) star = model.initialize(star) fit = model.fit(star).fit file_name = 'input/test_%s_var.npz' % name print(file_name) if not os.path.isfile(file_name): num_runs = 1000 all_params = [] for i in range(num_runs): image1 = image.copy() image1.addNoise(galsim.GaussianNoise(sigma=noise)) sd = piff.StarData(image1, image1.true_center, weight) s = piff.Star(sd, None) try: s = model.initialize(s) s = model.fit(s) except RuntimeError as e: # Occasionally hsm fails. print('Caught ', e) continue print(s.fit.params) all_params.append(s.fit.params) var = np.var(all_params, axis=0) np.savez(file_name, var=var) var = np.load(file_name)['var'] print('params = ', fit.params) print('empirical var = ', var) print('piff estimate = ', fit.params_var) print('ratio = ', fit.params_var / var) print('max ratio = ', np.max(fit.params_var / var)) print('min ratio = ', np.min(fit.params_var / var)) print('mean ratio = ', np.mean(fit.params_var / var)) # Note: The fastfit=False estimates are better -- typically better than 10% # The fastfit=True estimates are much rougher. Especially size. Need rtol=0.3. np.testing.assert_allclose(fit.params_var, var, rtol=0.3)
def test_direct(): """ Simple test for directly instantiated Gaussian, Kolmogorov, and Moffat without going through GSObjectModel explicitly. """ # Here is the true PSF scale = 1.3 g1 = 0.23 g2 = -0.17 du = 0.1 dv = 0.4 gsobjs = [ galsim.Gaussian(sigma=1.0), galsim.Kolmogorov(half_light_radius=1.0), galsim.Moffat(half_light_radius=1.0, beta=3.0), galsim.Moffat(half_light_radius=1.0, beta=2.5, trunc=3.0) ] models = [ piff.Gaussian(fastfit=True, include_pixel=False), piff.Kolmogorov(fastfit=True, include_pixel=False), piff.Moffat(fastfit=True, beta=3.0, include_pixel=False), piff.Moffat(fastfit=True, beta=2.5, trunc=3.0, include_pixel=False) ] for gsobj, model in zip(gsobjs, models): print() print("gsobj = ", gsobj) print() psf = gsobj.dilate(scale).shear(g1=g1, g2=g2).shift(du, dv) # Draw the PSF onto an image. Let's go ahead and give it a non-trivial WCS. wcs = galsim.JacobianWCS(0.26, 0.05, -0.08, -0.29) image = galsim.Image(64, 64, wcs=wcs) # This is only going to come out right if we (unphysically) don't convolve by the pixel. psf.drawImage(image, method='no_pixel') # Make a StarData instance for this image stardata = piff.StarData(image, image.true_center) star = piff.Star(stardata, None) star = model.initialize(star) # First try fastfit. print('Fast fit') fit = model.fit(star).fit print('True scale = ', scale, ', model scale = ', fit.params[0]) print('True g1 = ', g1, ', model g1 = ', fit.params[1]) print('True g2 = ', g2, ', model g2 = ', fit.params[2]) print('True du = ', du, ', model du = ', fit.center[0]) print('True dv = ', dv, ', model dv = ', fit.center[1]) # This test is fairly accurate, since we didn't add any noise and didn't convolve by # the pixel, so the image is very accurately a sheared GSObject. # These tests are more strict above. The truncated Moffat included here but not there # doesn't work quite as well. np.testing.assert_allclose(fit.params[0], scale, rtol=1e-4) np.testing.assert_allclose(fit.params[1], g1, rtol=0, atol=1e-5) np.testing.assert_allclose(fit.params[2], g2, rtol=0, atol=1e-5) np.testing.assert_allclose(fit.center[0], du, rtol=0, atol=1e-5) np.testing.assert_allclose(fit.center[1], dv, rtol=0, atol=1e-5) # Also need to test ability to serialize outfile = os.path.join('output', 'gsobject_direct_test.fits') with fitsio.FITS(outfile, 'rw', clobber=True) as f: model.write(f, 'psf_model') with fitsio.FITS(outfile, 'r') as f: roundtrip_model = piff.GSObjectModel.read(f, 'psf_model') assert model.__dict__ == roundtrip_model.__dict__ # repeat with fastfit=False models = [ piff.Gaussian(fastfit=False, include_pixel=False), piff.Kolmogorov(fastfit=False, include_pixel=False), piff.Moffat(fastfit=False, beta=3.0, include_pixel=False), piff.Moffat(fastfit=False, beta=2.5, trunc=3.0, include_pixel=False) ] for gsobj, model in zip(gsobjs, models): print() print("gsobj = ", gsobj) print() psf = gsobj.dilate(scale).shear(g1=g1, g2=g2).shift(du, dv) # Draw the PSF onto an image. Let's go ahead and give it a non-trivial WCS. wcs = galsim.JacobianWCS(0.26, 0.05, -0.08, -0.29) image = galsim.Image(64, 64, wcs=wcs) # This is only going to come out right if we (unphysically) don't convolve by the pixel. psf.drawImage(image, method='no_pixel') # Make a StarData instance for this image stardata = piff.StarData(image, image.true_center) star = piff.Star(stardata, None) star = model.initialize(star) print('Slow fit') fit = model.fit(star).fit print('True scale = ', scale, ', model scale = ', fit.params[0]) print('True g1 = ', g1, ', model g1 = ', fit.params[1]) print('True g2 = ', g2, ', model g2 = ', fit.params[2]) print('True du = ', du, ', model du = ', fit.center[0]) print('True dv = ', dv, ', model dv = ', fit.center[1]) # This test is fairly accurate, since we didn't add any noise and didn't convolve by # the pixel, so the image is very accurately a sheared GSObject. np.testing.assert_allclose(fit.params[0], scale, rtol=1e-5) np.testing.assert_allclose(fit.params[1], g1, rtol=0, atol=1e-5) np.testing.assert_allclose(fit.params[2], g2, rtol=0, atol=1e-5) np.testing.assert_allclose(fit.center[0], du, rtol=0, atol=1e-5) np.testing.assert_allclose(fit.center[1], dv, rtol=0, atol=1e-5) # Also need to test ability to serialize outfile = os.path.join('output', 'gsobject_direct_test.fits') with fitsio.FITS(outfile, 'rw', clobber=True) as f: model.write(f, 'psf_model') with fitsio.FITS(outfile, 'r') as f: roundtrip_model = piff.GSObjectModel.read(f, 'psf_model') assert model.__dict__ == roundtrip_model.__dict__