def test_compound(): """Check that transformations of transformations work the same whether they are compounded automatically or not. """ gal1 = galsim.Gaussian(fwhm=1.7, flux=2.3) gal2 = gal1.shear(g1=0.21, g2=0.12).rotate(33 * galsim.degrees).shift(0.1,0.4) * 1.1 gal3 = gal2.shear(g1=0.18, g2=0.09).rotate(12 * galsim.degrees).shift(-0.3,0.5) * 8.9 # These should have compounded automatically into a single transformation print('gal3 = ',gal3) print('gal3.original = ',gal3.original) assert gal3.original == gal1 gal4 = gal2 + 0. * gal1 # Equivalent to gal2, but the sum kills the automatic compounding. gal5 = gal4.shear(g1=0.18, g2=0.09).rotate(12 * galsim.degrees).shift(-0.3,0.5) * 8.9 print('gal5 = ',gal5) print('gal5.original = ',gal5.original) assert gal5.original != gal1 assert gal5.original == gal4 # Despite that, the gal3 and gal5 should draw the same in both real and k-space im3_d = galsim.ImageD(8,8) im5_d = galsim.ImageD(8,8) im3_f = galsim.ImageF(8,8) im5_f = galsim.ImageF(8,8) im3_cd = galsim.ImageCD(8,8) im5_cd = galsim.ImageCD(8,8) im3_cf = galsim.ImageCF(8,8) im5_cf = galsim.ImageCF(8,8) # Note: these are not equal. gal5 lost track of the overall transformation and thinks it # needs a bit larger maxk, smaller stepk. ~10% different. print('gal3.stepk = ',gal3.stepk) print('gal5.stepk = ',gal5.stepk) print('gal3.maxk = ',gal3.maxk) print('gal5.maxk = ',gal5.maxk) gal3.drawImage(image=im3_d, method='sb', scale=0.2) gal5.drawImage(image=im5_d, method='sb', scale=0.2) np.testing.assert_almost_equal(im3_d[1,1], gal3.xValue(-0.7,-0.7), decimal=12) np.testing.assert_almost_equal(im5_d[1,1], gal3.xValue(-0.7,-0.7), decimal=12) np.testing.assert_almost_equal(im3_d.array[0,0], gal3.xValue(-0.7,-0.7), decimal=12) np.testing.assert_almost_equal(im5_d.array[0,0], gal3.xValue(-0.7,-0.7), decimal=12) np.testing.assert_array_almost_equal(im3_d.array, im5_d.array, decimal=12) gal3.drawImage(image=im3_f, method='sb', scale=0.2) gal5.drawImage(image=im5_f, method='sb', scale=0.2) np.testing.assert_almost_equal(im3_f[1,1], gal3.xValue(-0.7,-0.7), decimal=4) np.testing.assert_almost_equal(im5_f[1,1], gal3.xValue(-0.7,-0.7), decimal=4) np.testing.assert_almost_equal(im3_f.array, im5_f.array, decimal=4) np.testing.assert_almost_equal(im3_f.array, im3_d.array, decimal=4) np.testing.assert_almost_equal(im5_f.array, im5_d.array, decimal=4) gal3.drawKImage(image=im3_cd, scale=0.5) gal5.drawKImage(image=im5_cd, scale=0.5) np.testing.assert_almost_equal(im3_cd[-4,-4], gal3.kValue(-2.,-2.), decimal=12) np.testing.assert_almost_equal(im5_cd[-4,-4], gal3.kValue(-2.,-2.), decimal=12) np.testing.assert_almost_equal(im3_cd.array[0,0], gal3.kValue(-2.,-2.), decimal=12) np.testing.assert_almost_equal(im5_cd.array[0,0], gal3.kValue(-2.,-2.), decimal=12) np.testing.assert_array_almost_equal(im3_cd.array, im5_cd.array, decimal=12) gal3.drawKImage(image=im3_cf, scale=0.5) gal5.drawKImage(image=im5_cf, scale=0.5) np.testing.assert_almost_equal(im3_cf[-4,-4], gal3.kValue(-2.,-2.), decimal=3) np.testing.assert_almost_equal(im5_cf[-4,-4], gal3.kValue(-2.,-2.), decimal=3) np.testing.assert_array_almost_equal(im3_cf.array, im5_cf.array, decimal=3) np.testing.assert_array_almost_equal(im3_cf.array, im3_cd.array, decimal=3) np.testing.assert_array_almost_equal(im5_cf.array, im5_cd.array, decimal=3)
def draw_and_encode_stamp(gal, psf, stamp_size, pixel_scale, attributes=None): """ Draws the galaxy, psf and noise power spectrum on a postage stamp and encodes it to be exported in a TFRecord. """ # Apply the PSF gal = galsim.Convolve(gal, psf) # Draw the Fourier domain image of the galaxy imC = galsim.ImageCF(stamp_size, stamp_size, scale=2. * np.pi / (pixel_scale * stamp_size)) imCp = galsim.ImageCF(stamp_size, stamp_size, scale=2. * np.pi / (pixel_scale * stamp_size)) gal.drawKImage(image=imC) psf.drawKImage(image=imCp) # Keep track of the pixels with 0 value mask = ~(np.fft.fftshift(imC.array)[:, :(stamp_size) // 2 + 1] == 0) # Inverse Fourier transform of the image # TODO: figure out why we need 2 fftshifts.... im = np.fft.fftshift(np.fft.ifft2(np.fft.fftshift( imC.array))).real.astype('float32') # Transform the psf array into proper format for Theano im_psf = np.fft.fftshift(np.fft.ifft2(np.fft.fftshift( imCp.array))).real.astype('float32') # Compute noise power spectrum ps = gal.noise._get_update_rootps((stamp_size, stamp_size), wcs=galsim.PixelScale(pixel_scale)) # The following comes from correlatednoise.py rt2 = np.sqrt(2.) shape = (stamp_size, stamp_size) ps[0, 0] = rt2 * ps[0, 0] # Then make the changes necessary for even sized arrays if shape[1] % 2 == 0: # x dimension even ps[0, shape[1] // 2] = rt2 * ps[0, shape[1] // 2] if shape[0] % 2 == 0: # y dimension even ps[shape[0] // 2, 0] = rt2 * ps[shape[0] // 2, 0] # Both dimensions even if shape[1] % 2 == 0: ps[shape[0] // 2, shape[1] // 2] = rt2 * \ ps[shape[0] // 2, shape[1] // 2] # Apply mask to power spectrum so that it is very large outside maxk ps = np.where(mask, np.log(ps**2), 10).astype('float32') serialized_output = { "image/encoded": [im.tostring()], "image/format": ["raw"], "psf/encoded": [im_psf.tostring()], "psf/format": ["raw"], "ps/encoded": [ps.tostring()], "ps/format": ["raw"] } # Adding the parameters provided if attributes is not None: for k in attributes: serialized_output['attrs/' + k] = [attributes[k]] return serialized_output
def __init__(self, image): self._gsp = galsim.GSParams(kvalue_accuracy=1.e-5) self._target_image = galsim.ImageCF(image) self._scratch_image = galsim.ImageCF(image)
def _make_galaxy(params): """ Draws the galaxy, psf and noise power spectrum on a postage stamp """ gal, psf, noise_image, in_pixel_scale, var, stamp_size, pixel_scale = params real_params = (galsim.Image(np.ascontiguousarray(gal), scale=in_pixel_scale), galsim.Image(np.ascontiguousarray(psf), scale=in_pixel_scale), galsim.Image(np.ascontiguousarray(noise_image), scale=in_pixel_scale), in_pixel_scale, var) gal = galsim.RealGalaxy(real_params, noise_pad_size=stamp_size * pixel_scale) psf = gal.original_psf gal = galsim.Convolve(gal, gal.original_psf) # Random rotation of the galaxy rotation_angle = galsim.Angle(-np.random.rand() * 2 * np.pi, galsim.radians) g = gal.rotate(rotation_angle) p = psf.rotate(rotation_angle) # Draw the Fourier domain image of the galaxy imC = galsim.ImageCF(stamp_size, stamp_size, scale=2. * np.pi / (pixel_scale * stamp_size)) imCp = galsim.ImageCF(stamp_size, stamp_size, scale=2. * np.pi / (pixel_scale * stamp_size)) g.drawKImage(image=imC) p.drawKImage(image=imCp) # Keep track of the pixels with 0 value mask = ~(np.fft.fftshift(imC.array)[:, :(stamp_size) // 2 + 1] == 0) # Inverse Fourier transform of the image # TODO: figure out why we need 2 fftshifts.... im = np.fft.fftshift(np.fft.ifft2(np.fft.fftshift( imC.array))).real.astype('float32') # Transform the psf array into proper format for Theano im_psf = np.fft.fftshift(imCp.array)[:, :(stamp_size // 2 + 1)].astype('complex64') # Compute noise power spectrum ps = g.noise._get_update_rootps((stamp_size, stamp_size), wcs=galsim.PixelScale(pixel_scale)) # The following comes from correlatednoise.py rt2 = np.sqrt(2.) shape = (stamp_size, stamp_size) ps[0, 0] = rt2 * ps[0, 0] # Then make the changes necessary for even sized arrays if shape[1] % 2 == 0: # x dimension even ps[0, shape[1] // 2] = rt2 * ps[0, shape[1] // 2] if shape[0] % 2 == 0: # y dimension even ps[shape[0] // 2, 0] = rt2 * ps[shape[0] // 2, 0] # Both dimensions even if shape[1] % 2 == 0: ps[shape[0] // 2, shape[1] // 2] = rt2 * \ ps[shape[0] // 2, shape[1] // 2] # Apply mask to power spectrum so that it is very large outside maxk ps = np.where(mask, np.log(ps**2), 10).astype('float32') return im, im_psf, ps