Exemple #1
0
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))
Exemple #2
0
def test_sum_noise():
    """Test that noise propagation works properly for compound objects.
    """
    obj1 = galsim.Gaussian(sigma=1.7)
    obj2 = galsim.Gaussian(sigma=2.3)
    obj1.noise = galsim.UncorrelatedNoise(variance=0.3, scale=0.2)
    obj2.noise = galsim.UncorrelatedNoise(variance=0.5, scale=0.2)
    obj3 = galsim.Gaussian(sigma=2.9)

    # Sum adds the variance of the components
    sum2 = galsim.Sum([obj1,obj2])
    np.testing.assert_almost_equal(sum2.noise.getVariance(), 0.8,
            err_msg = "Sum of two objects did not add noise varinace")
    sum2 = galsim.Sum([obj1,obj3])
    np.testing.assert_almost_equal(sum2.noise.getVariance(), 0.3,
            err_msg = "Sum of two objects did not add noise varinace")
    sum2 = galsim.Sum([obj2,obj3])
    np.testing.assert_almost_equal(sum2.noise.getVariance(), 0.5,
            err_msg = "Sum of two objects did not add noise varinace")
    sum3 = galsim.Sum([obj1,obj2,obj3])
    np.testing.assert_almost_equal(sum3.noise.getVariance(), 0.8,
            err_msg = "Sum of three objects did not add noise varinace")
    sum3 = obj1 + obj2 + obj3
    np.testing.assert_almost_equal(sum3.noise.getVariance(), 0.8,
            err_msg = "Sum of three objects did not add noise varinace")

    # Adding noise objects with different WCSs will raise a warning.
    obj4 = galsim.Gaussian(sigma=3.3)
    obj4.noise = galsim.UncorrelatedNoise(variance=0.3, scale=0.8)
    try:
        np.testing.assert_warns(galsim.GalSimWarning, galsim.Sum, [obj1, obj4])
    except:
        pass
Exemple #3
0
    def _draw_objects(self):
        """
        this is dumb, drawing into the full image when
        we don't need to
        """

        self.imlist = []

        cdisk = self['pdfs']['disk']
        cbulge = self['pdfs']['bulge']
        cknots = self['pdfs'].get('knots', None)

        for band in range(self['nband']):
            objects = []
            for obj_parts in self.objlist:

                disk = obj_parts['disk'] * cdisk['color'][band]
                bulge = obj_parts['bulge'] * cbulge['color'][band]
                tparts = [disk, bulge]

                if cknots is not None:
                    knots = obj_parts['knots'] * cknots['color'][band]
                    tparts.append(knots)

                obj = galsim.Sum(tparts)
                obj = obj.shift(
                    dx=obj_parts['cen'][0],
                    dy=obj_parts['cen'][1],
                )
                objects.append(obj)

            objects = galsim.Sum(objects)

            shear = self.get('shear', None)
            if shear is not None:
                objects = objects.shear(
                    g1=shear[0],
                    g2=shear[1],
                )

            convolved_objects = galsim.Convolve(objects, self.psf)

            kw = {'scale': self['pixel_scale']}

            dims = self.get('dims', None)
            if dims is not None:
                kw['nx'], kw['ny'] = dims[1], dims[0]

            dims = np.array(self.psf_im.shape)
            image = convolved_objects.drawImage(**kw).array
            self.imlist.append(image)
Exemple #4
0
def get_gal_wldeblend(*, rng, data):
    """Draw a galaxy from the weak lensing deblending package.

    Parameters
    ----------
    rng : np.random.RandomState
        An RNG to use for making galaxies.
    data : WLDeblendData
        Namedtuple with data for making galaxies via the weak lesning
        deblending package.

    Returns
    -------
    gal : galsim Object
        The galaxy as a galsim object.
    """
    rind = rng.choice(data.cat.size)
    angle = rng.uniform() * 360
    pa_angle = rng.uniform() * 360

    data.cat['pa_disk'][rind] = pa_angle
    data.cat['pa_bulge'][rind] = pa_angle

    return galsim.Sum([
        data.builders[band].from_catalog(
            data.cat[rind], 0, 0, data.surveys[band].filter_band).model.rotate(
                angle * galsim.degrees) for band in range(len(data.builders))
    ])
 def _func(x, y):
     if len(psfs) > 1:
         return galsim.Sum([
             psf.getPSF(galsim.PositionD(x=x, y=y)) for psf in psfs
         ]).withFlux(1.0)
     else:
         return psfs[0].getPSF(galsim.PositionD(x=x, y=y))
Exemple #6
0
 def mockCoadd(self, variances, fwhms, psfs):
     weights = 1.0 / (fwhms**2 * variances)
     weights /= weights.sum()
     coadd_psf = galsim.Sum(
         [psf * weight for psf, weight in zip(psfs, weights)])
     coadd_variance = (variances * weights * weights).sum()
     return coadd_variance, coadd_psf
Exemple #7
0
def test_render_sources_for_image():
    image_shape = (64, 64)
    wcs = galsim.PixelScale(0.25)
    draw_method = 'auto'
    src_inds = np.arange(5)

    def src_func(ind):
        obj = galsim.Gaussian(fwhm=ind * 0.1 + 0.9)
        rng = np.random.RandomState(seed=ind + 1)
        image_pos = galsim.PositionD(
            x=rng.uniform(low=20, high=40),
            y=rng.uniform(low=20, high=40),
        )
        return obj, image_pos

    im = render_sources_for_image(image_shape=image_shape,
                                  wcs=wcs,
                                  draw_method=draw_method,
                                  src_inds=src_inds,
                                  src_func=src_func,
                                  n_jobs=1)

    # now render them via direct sum of objects
    objs = []
    for ind in src_inds:
        obj, pos = src_func(ind)
        objs.append(obj.shift(dx=pos.x * 0.25, dy=pos.y * 0.25))
    im_sum = galsim.Sum(objs).drawImage(wcs=wcs, nx=155, ny=155)
    # we set the center to (0, 0) so that the offsets from the center
    # match the coords of the objects
    im_sum.setCenter(0, 0)

    assert np.allclose(im_sum[im.bounds].array, im.array, rtol=0, atol=5e-7)
Exemple #8
0
def test_ne():
    """ Check that inequality works as expected."""
    gsp = galsim.GSParams(maxk_threshold=1.1e-3, folding_threshold=5.1e-3)
    gal1 = galsim.Gaussian(fwhm=1)
    gal2 = galsim.Gaussian(fwhm=2)

    # Sum.  Params are objs to add and potentially gsparams.
    gals = [
        galsim.Sum(gal1),
        galsim.Sum(gal1, gal2),
        galsim.Sum(gal2, gal1),  # Not! commutative.
        galsim.Sum(galsim.Sum(gal1, gal2), gal2),
        galsim.Sum(gal1, galsim.Sum(gal2, gal2)),  # Not! associative.
        galsim.Sum(gal1, gsparams=gsp)
    ]
    all_obj_diff(gals)

    # Convolution.  Params are objs to convolve and potentially gsparams.
    # The following should test unequal
    gals = [
        galsim.Convolution(gal1),
        galsim.Convolution(gal1, gal2),
        galsim.Convolution(gal2, gal1),  # Not! commutative.
        galsim.Convolution(gal1, gal2, real_space=True),
        galsim.Convolution(galsim.Convolution(gal1, gal2), gal2),
        galsim.Convolution(gal1,
                           galsim.Convolution(gal2,
                                              gal2)),  # Not! associative.
        galsim.Convolution(gal1, gsparams=gsp)
    ]
    all_obj_diff(gals)

    # Deconvolution.  Only params here are obj to deconvolve and gsparams.
    gals = [
        galsim.Deconvolution(gal1),
        galsim.Deconvolution(gal2),
        galsim.Deconvolution(gal1, gsparams=gsp)
    ]
    all_obj_diff(gals)

    # AutoConvolution.  Only params here are obj to deconvolve and gsparams.
    gals = [
        galsim.AutoConvolution(gal1),
        galsim.AutoConvolution(gal2),
        galsim.AutoConvolution(gal1, gsparams=gsp)
    ]
    all_obj_diff(gals)

    # AutoCorrelation.  Only params here are obj to deconvolve and gsparams.
    gals = [
        galsim.AutoCorrelation(gal1),
        galsim.AutoCorrelation(gal2),
        galsim.AutoCorrelation(gal1, gsparams=gsp)
    ]
    all_obj_diff(gals)
Exemple #9
0
def test_sum_transform():
    """This test addresses a bug found by Ismael Serrano, #763, wherein some attributes 
    got messed up for a Transform(Sum(Transform())) object.

    The bug was that we didn't bother to make a new SBProfile for a Sum (or Convolve) of
    a single object.  But if that was an SBTransform, then the next Transform operation
    combined the two Transforms, which messed up the repr.
    
    The fix is to always make an SBAdd or SBConvolve object even if the list of things to add
    or convolve only has one element.
    """
    gal0 = galsim.Exponential(scale_radius=0.34, flux=105.).shear(g1=-0.56,
                                                                  g2=0.15)

    for gal1 in [galsim.Sum(gal0), galsim.Convolve(gal0)]:
        gal2 = gal1.dilate(1)

        sgal1 = eval(str(gal1))
        rgal1 = eval(repr(gal1))
        sgal2 = eval(str(gal2))
        rgal2 = eval(repr(gal2))

        print('gal1 = ', repr(gal1))
        print('sgal1 = ', repr(sgal1))
        print('rgal1 = ', repr(rgal1))

        print('gal2 = ', repr(gal2))
        print('sgal2 = ', repr(sgal2))
        print('rgal2 = ', repr(rgal2))

        gal1_im = gal1.drawImage(nx=64, ny=64, scale=0.2)
        sgal1_im = sgal1.drawImage(nx=64, ny=64, scale=0.2)
        rgal1_im = rgal1.drawImage(nx=64, ny=64, scale=0.2)

        gal2_im = gal2.drawImage(nx=64, ny=64, scale=0.2)
        sgal2_im = sgal2.drawImage(nx=64, ny=64, scale=0.2)
        rgal2_im = rgal2.drawImage(nx=64, ny=64, scale=0.2)

        # Check that the objects are equivalent, even if they may be written differently.
        np.testing.assert_almost_equal(gal1_im.array,
                                       sgal1_im.array,
                                       decimal=8)
        np.testing.assert_almost_equal(gal1_im.array,
                                       rgal1_im.array,
                                       decimal=8)

        # These two used to fail.
        np.testing.assert_almost_equal(gal2_im.array,
                                       sgal2_im.array,
                                       decimal=8)
        np.testing.assert_almost_equal(gal2_im.array,
                                       rgal2_im.array,
                                       decimal=8)

        do_pickle(gal0)
        do_pickle(gal1)
        do_pickle(gal2)  # And this.
Exemple #10
0
 def mockCoadd(self, variances, fwhms, psfs):
     weights = 1.0 / variances
     weights /= weights.sum()
     coadd_variance = 1.0 / (1.0 / variances).sum()
     coadd_psf = galsim.FourierSqrt(
         galsim.Sum([
             galsim.AutoCorrelate(psf) * weight
             for psf, weight in zip(psfs, weights)
         ]))
     return coadd_variance, coadd_psf
Exemple #11
0
def test_gsparams():
    """Test withGSParams with some non-default gsparams
    """
    obj1 = galsim.Exponential(half_light_radius=1.7)
    obj2 = galsim.Pixel(scale=0.2)
    gsp = galsim.GSParams(folding_threshold=1.e-4,
                          maxk_threshold=1.e-4,
                          maximum_fft_size=1.e4)
    gsp2 = galsim.GSParams(folding_threshold=1.e-2, maxk_threshold=1.e-2)

    sum = galsim.Sum(obj1, obj2)
    sum1 = sum.withGSParams(gsp)
    assert sum.gsparams == galsim.GSParams()
    assert sum1.gsparams == gsp
    assert sum1.obj_list[0].gsparams == gsp
    assert sum1.obj_list[1].gsparams == gsp

    sum2 = galsim.Sum(obj1.withGSParams(gsp), obj2.withGSParams(gsp))
    sum3 = galsim.Sum(galsim.Exponential(half_light_radius=1.7, gsparams=gsp),
                      galsim.Pixel(scale=0.2))
    sum4 = galsim.Add(obj1, obj2, gsparams=gsp)
    assert sum != sum1
    assert sum1 == sum2
    assert sum1 == sum3
    assert sum1 == sum4
    print('stepk = ', sum.stepk, sum1.stepk)
    assert sum1.stepk < sum.stepk
    print('maxk = ', sum.maxk, sum1.maxk)
    assert sum1.maxk > sum.maxk

    sum5 = galsim.Add(obj1, obj2, gsparams=gsp, propagate_gsparams=False)
    assert sum5 != sum4
    assert sum5.gsparams == gsp
    assert sum5.obj_list[0].gsparams == galsim.GSParams()
    assert sum5.obj_list[1].gsparams == galsim.GSParams()

    sum6 = sum5.withGSParams(gsp2)
    assert sum6 != sum5
    assert sum6.gsparams == gsp2
    assert sum6.obj_list[0].gsparams == galsim.GSParams()
    assert sum6.obj_list[1].gsparams == galsim.GSParams()
Exemple #12
0
def test_ne():
    import time
    t1 = time.time()

    gsp = galsim.GSParams(maxk_threshold=1.1e-3, folding_threshold=5.1e-3)
    gal1 = galsim.Gaussian(fwhm=1)
    gal2 = galsim.Gaussian(fwhm=2)

    # Sum.  Params are objs to add and potentially gsparams.
    gals = [galsim.Sum(gal1),
            galsim.Sum(gal1, gal2),
            galsim.Sum(gal2, gal1),  # Not! commutative.
            galsim.Sum(galsim.Sum(gal1, gal2), gal2),
            galsim.Sum(gal1, galsim.Sum(gal2, gal2)),  # Not! associative.
            galsim.Sum(gal1, gsparams=gsp)]
    all_obj_diff(gals)

    # Convolution.  Params are objs to convolve and potentially gsparams.
    # The following should test unequal
    gals = [galsim.Convolution(gal1),
            galsim.Convolution(gal1, gal2),
            galsim.Convolution(gal2, gal1),  # Not! commutative.
            galsim.Convolution(gal1, gal2, real_space=True),
            galsim.Convolution(galsim.Convolution(gal1, gal2), gal2),
            galsim.Convolution(gal1, galsim.Convolution(gal2, gal2)),  # Not! associative.
            galsim.Convolution(gal1, gsparams=gsp)]
    all_obj_diff(gals)

    # Deconvolution.  Only params here are obj to deconvolve and gsparams.
    gals = [galsim.Deconvolution(gal1),
            galsim.Deconvolution(gal2),
            galsim.Deconvolution(gal1, gsparams=gsp)]
    all_obj_diff(gals)

    # AutoConvolution.  Only params here are obj to deconvolve and gsparams.
    gals = [galsim.AutoConvolution(gal1),
            galsim.AutoConvolution(gal2),
            galsim.AutoConvolution(gal1, gsparams=gsp)]
    all_obj_diff(gals)

    # AutoCorrelation.  Only params here are obj to deconvolve and gsparams.
    gals = [galsim.AutoCorrelation(gal1),
            galsim.AutoCorrelation(gal2),
            galsim.AutoCorrelation(gal1, gsparams=gsp)]
    all_obj_diff(gals)

    t2 = time.time()
    print 'time for %s = %.2f'%(funcname(),t2-t1)
Exemple #13
0
def test_ne():
    """ Check that inequality works as expected."""
    gsp = galsim.GSParams(maxk_threshold=1.1e-3, folding_threshold=5.1e-3)
    gal1 = galsim.Gaussian(fwhm=1)
    gal2 = galsim.Gaussian(fwhm=2)

    # Sum.  Params are objs to add and potentially gsparams.
    gals = [galsim.Sum(gal1),
            galsim.Sum(gal1, gal2),
            galsim.Sum(gal2, gal1),  # Not! commutative.  (but is associative)
            galsim.Sum(galsim.Sum(gal1, gal2), gal2),
            galsim.Sum(gal1, gsparams=gsp),
            galsim.Sum(gal1, gsparams=gsp, propagate_gsparams=False)]
    all_obj_diff(gals)
Exemple #14
0
    def _set_coadded_psf(self):
        """
        set the coadd psf

        wcs of final psf image is that of the *first*, since
        the coadd obs is a copy of that
        """
        coadd_obs = self.coadd_obs
        weights = self.weights

        psf_wcs = coadd_obs.psf.jacobian.get_galsim_wcs()

        coadd_psf = galsim.Sum([psf * w for psf, w in zip(self.psfs, weights)])
        coadd_psf_image = galsim.Image(self.psf_nx, self.psf_ny, wcs=psf_wcs)
        coadd_psf.drawImage(image=coadd_psf_image, method='no_pixel')

        coadd_psf_image = coadd_psf_image.array

        coadd_obs.psf.set_image(coadd_psf_image)
def test_gaussian_smoke():
    obj = [
        galsim.Gaussian(fwhm=GFWHM).shift(-12 - SCALE / 2, SCALE / 2),
        galsim.Gaussian(fwhm=GFWHM).shift(12 + SCALE / 2, SCALE / 2)
    ]

    pobj = [
        galsim.Convolve(obj[0], galsim.Gaussian(fwhm=PSF_FAC)),
        galsim.Convolve(obj[1], galsim.Gaussian(fwhm=1.00))
    ]

    def psf_model(row, col):
        if col >= 160 / 2:
            return galsim.Gaussian(fwhm=1.0).drawImage(scale=SCALE,
                                                       nx=33,
                                                       ny=33).array
        else:
            return galsim.Gaussian(fwhm=PSF_FAC).drawImage(scale=SCALE,
                                                           nx=33,
                                                           ny=33).array

    hpsf = PSFHomogenizer(
        psf_model,
        [160, 160],
    )

    im_orig = galsim.Sum(pobj).drawImage(scale=SCALE, nx=160, ny=160).array
    imh = hpsf.homogenize_image(im_orig)

    def _subtract_mirrored(im, im_true):
        imn = np.zeros_like(im)
        mid = imn.shape[1] // 2
        imn[:, :mid] = im[:, :mid] - im_true[:, mid:][:, ::-1]
        imn[:, mid:] = im[:, mid:] - im_true[:, mid:]
        return imn

    max_diff_hmg = np.max(np.abs(_subtract_mirrored(imh, imh) / imh.max()))
    max_diff_orig = np.max(
        np.abs(_subtract_mirrored(im_orig, im_orig) / im_orig.max()))

    assert max_diff_orig > 1e-2
    assert max_diff_hmg < max_diff_orig / 10
Exemple #16
0
    def _set_coadded_image(self):
        """
        do the actual coadding, with appropriate weights

        wcs of final image is that of the *first*, since
        the coadd obs is a copy of that
        """
        coadd_obs = self.coadd_obs
        weights = self.weights

        wcs = coadd_obs.jacobian.get_galsim_wcs()

        coadd = galsim.Sum(
            [image * w for image, w in zip(self.images, weights)])

        coadd_image = galsim.Image(self.nx, self.ny, wcs=wcs)
        coadd.drawImage(
            image=coadd_image,
            method='no_pixel',
        )

        coadd_obs.set_image(coadd_image.array)
Exemple #17
0
    def _set_coadded_weight_map(self):
        """
        coadd the noise image realizations and take var

        also set the .noise attribute
        """
        coadd_obs = self.coadd_obs
        weights = self.weights

        weight_map = np.zeros((self.ny, self.nx))

        wcs = coadd_obs.jacobian.get_galsim_wcs()

        coadd_noise = galsim.Sum(
            [image * w for image, w in zip(self.noise_images, weights)])
        coadd_noise_image = galsim.Image(self.nx, self.ny, wcs=wcs)
        coadd_noise.drawImage(image=coadd_noise_image, method='no_pixel')

        weight_map[:, :] = 1. / np.var(coadd_noise_image.array)
        coadd_obs.set_weight(weight_map)

        coadd_obs.noise = coadd_noise_image.array
    def _stack_ps_psfs(self, *, x, y, **kwargs):
        if not hasattr(self, '_psfs'):
            self._psfs = [[
                    PowerSpectrumPSF(
                        rng=self.rng,
                        im_width=self.dim,
                        buff=self.dim/2,
                        scale=self.scale,
                        **kwargs)
                    for _ in range(self.n_coadd_psf)]
                for _ in range(self.n_bands)]

            LOGGER.debug('stacking %d power spectrum psfs', self.n_coadd_psf)

        _psf_wcs = self._get_local_jacobian(x=x, y=y)

        test_psfs = []
        for i in range(self.n_bands):
            test_psfs += [
                p.getPSF(galsim.PositionD(x=x, y=y))
                for p in self._psfs[i]]

        psf_dim = self._get_psf_box_size(test_psfs, _psf_wcs)

        psfs = []
        psf_ims = []
        for i in range(self.n_bands):
            psf = galsim.Sum([
                p.getPSF(galsim.PositionD(x=x, y=y))
                for p in self._psfs[i]]).withFlux(1)
            psf_im = psf.drawImage(
                nx=psf_dim, ny=psf_dim, wcs=_psf_wcs).array.copy()
            psf_im /= np.sum(psf_im)

            psfs.append(psf)
            psf_ims.append(psf_im)

        return psfs, psf_ims
Exemple #19
0
    def get_scene(self):
        """
        get a scene with multiple objects
        """
        c = self['scene']
        dims = [int(c['size'] / self['pixel_scale'])] * 2

        halfsize = c['size'] / 2.0

        offset_radius = halfsize - 0.25 * halfsize
        objs = []
        for i in range(c['nobjects']):
            obj = self._get_object()
            dx, dy = self.rng.uniform(
                low=-offset_radius,
                high=offset_radius,
                size=2,
            )
            obj = obj.shift(dx=dx, dy=dy)
            objs.append(obj)

        all_obj = galsim.Sum(objs)
        im = self._get_image(all_obj, dims=dims)
        return im
Exemple #20
0
def test_flip():
    """Test several ways to flip a profile
    """
    # The Shapelet profile has the advantage of being fast and not circularly symmetric, so
    # it is a good test of the actual code for doing the flips (in SBTransform).
    # But since the bug Rachel reported in #645 was actually in SBInterpolatedImage
    # (one calculation implicitly assumed dx > 0), it seems worthwhile to run through all the
    # classes to make sure we hit everything with negative steps for dx and dy.
    prof_list = [
        galsim.Shapelet(sigma=0.17, order=2,
                        bvec=[1.7, 0.01,0.03, 0.29, 0.33, -0.18]),
    ]
    if __name__ == "__main__":
        image_dir = './real_comparison_images'
        catalog_file = 'test_catalog.fits'
        rgc = galsim.RealGalaxyCatalog(catalog_file, dir=image_dir)
        # Some of these are slow, so only do the Shapelet test as part of the normal unit tests.
        prof_list += [
            galsim.Airy(lam_over_diam=0.17, flux=1.7),
            galsim.Airy(lam_over_diam=0.17, obscuration=0.2, flux=1.7),
            # Box gets rendered with real-space convolution.  The default accuracy isn't quite
            # enough to get the flip to match at 6 decimal places.
            galsim.Box(0.17, 0.23, flux=1.7,
                       gsparams=galsim.GSParams(realspace_relerr=1.e-6)),
            # Without being convolved by anything with a reasonable k cutoff, this needs
            # a very large fft.
            galsim.DeVaucouleurs(half_light_radius=0.17, flux=1.7),
            # I don't really understand why this needs a lower maxk_threshold to work, but
            # without it, the k-space tests fail.
            galsim.Exponential(scale_radius=0.17, flux=1.7,
                               gsparams=galsim.GSParams(maxk_threshold=1.e-4)),
            galsim.Gaussian(sigma=0.17, flux=1.7),
            galsim.Kolmogorov(fwhm=0.17, flux=1.7),
            galsim.Moffat(beta=2.5, fwhm=0.17, flux=1.7),
            galsim.Moffat(beta=2.5, fwhm=0.17, flux=1.7, trunc=0.82),
            galsim.OpticalPSF(lam_over_diam=0.17, obscuration=0.2, nstruts=6,
                              coma1=0.2, coma2=0.5, defocus=-0.1, flux=1.7),
            # Like with Box, we need to increase the real-space convolution accuracy.
            # This time lowering both relerr and abserr.
            galsim.Pixel(0.23, flux=1.7,
                         gsparams=galsim.GSParams(realspace_relerr=1.e-6,
                                                  realspace_abserr=1.e-8)),
            # Note: RealGalaxy should not be rendered directly because of the deconvolution.
            # Here we convolve it by a Gaussian that is slightly larger than the original PSF.
            galsim.Convolve([ galsim.RealGalaxy(rgc, index=0, flux=1.7),  # "Real" RealGalaxy
                              galsim.Gaussian(sigma=0.08) ]),
            galsim.Convolve([ galsim.RealGalaxy(rgc, index=1, flux=1.7),  # "Fake" RealGalaxy
                              galsim.Gaussian(sigma=0.08) ]),             # (cf. test_real.py)
            galsim.Spergel(nu=-0.19, half_light_radius=0.17, flux=1.7),
            galsim.Spergel(nu=0., half_light_radius=0.17, flux=1.7),
            galsim.Spergel(nu=0.8, half_light_radius=0.17, flux=1.7),
            galsim.Sersic(n=2.3, half_light_radius=0.17, flux=1.7),
            galsim.Sersic(n=2.3, half_light_radius=0.17, flux=1.7, trunc=0.82),
            # The shifts here caught a bug in how SBTransform handled the recentering.
            # Two of the shifts (0.125 and 0.375) lead back to 0.0 happening on an integer
            # index, which now works correctly.
            galsim.Sum([ galsim.Gaussian(sigma=0.17, flux=1.7).shift(-0.2,0.125),
                         galsim.Exponential(scale_radius=0.23, flux=3.1).shift(0.375,0.23)]),
            galsim.TopHat(0.23, flux=1.7),
            # Box and Pixel use real-space convolution.  Convolve with a Gaussian to get fft.
            galsim.Convolve([ galsim.Box(0.17, 0.23, flux=1.7).shift(-0.2,0.1),
                              galsim.Gaussian(sigma=0.09) ]),
            galsim.Convolve([ galsim.TopHat(0.17, flux=1.7).shift(-0.275,0.125),
                              galsim.Gaussian(sigma=0.09) ]),
            # Test something really crazy with several layers worth of transformations
            galsim.Convolve([
                galsim.Sum([
                    galsim.Gaussian(sigma=0.17, flux=1.7).shear(g1=0.1,g2=0.2).shift(2,3),
                    galsim.Kolmogorov(fwhm=0.33, flux=3.9).transform(0.31,0.19,-0.23,0.33) * 88.,
                    galsim.Box(0.11, 0.44, flux=4).rotate(33 * galsim.degrees) / 1.9
                ]).shift(-0.3,1),
                galsim.AutoConvolve(galsim.TopHat(0.5).shear(g1=0.3,g2=0)).rotate(3*galsim.degrees),
                (galsim.AutoCorrelate(galsim.Box(0.2, 0.3)) * 11).shift(3,2).shift(2,-3) * 0.31
            ]).shift(0,0).transform(0,-1,-1,0).shift(-1,1)
        ]

    s = galsim.Shear(g1=0.11, g2=-0.21)
    s1 = galsim.Shear(g1=0.11, g2=0.21)  # Appropriate for the flips around x and y axes
    s2 = galsim.Shear(g1=-0.11, g2=-0.21)  # Appropriate for the flip around x=y

    # Also use shears with just a g1 to get dx != dy, but dxy, dyx = 0.
    q = galsim.Shear(g1=0.11, g2=0.)
    q1 = galsim.Shear(g1=0.11, g2=0.)  # Appropriate for the flips around x and y axes
    q2 = galsim.Shear(g1=-0.11, g2=0.)  # Appropriate for the flip around x=y

    decimal=6  # Oddly, these aren't as precise as I would have expected.
               # Even when we only go to this many digits of accuracy, the Exponential needed
               # a lower than default value for maxk_threshold.
    im = galsim.ImageD(16,16, scale=0.05)

    for prof in prof_list:
        print('prof = ',prof)

        # Not all profiles are expected to have a max_sb value close to the maximum pixel value,
        # so mark the ones where we don't want to require this to be true.
        close_maxsb = True
        name = str(prof)
        if ('DeVauc' in name or 'Sersic' in name or 'Spergel' in name or
            'Optical' in name or 'shift' in name):
            close_maxsb = False

        # Make sure we hit all 4 fill functions.
        # image_x uses fillXValue with izero, jzero
        # image_x1 uses fillXValue with izero, jzero, and unequal dx,dy
        # image_x2 uses fillXValue with dxy, dyx
        # image_k uses fillKValue with izero, jzero
        # image_k1 uses fillKValue with izero, jzero, and unequal dx,dy
        # image_k2 uses fillKValue with dxy, dyx
        image_x = prof.drawImage(image=im.copy(), method='no_pixel')
        image_x1 = prof.shear(q).drawImage(image=im.copy(), method='no_pixel')
        image_x2 = prof.shear(s).drawImage(image=im.copy(), method='no_pixel')
        image_k = prof.drawImage(image=im.copy())
        image_k1 = prof.shear(q).drawImage(image=im.copy())
        image_k2 = prof.shear(s).drawImage(image=im.copy())

        if close_maxsb:
            np.testing.assert_allclose(
                    image_x.array.max(), prof.max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image_x1.array.max(), prof.shear(q).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image_x2.array.max(), prof.shear(s).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")

        # Flip around y axis (i.e. x -> -x)
        flip1 = prof.transform(-1, 0, 0, 1)
        image2_x = flip1.drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x.array, image2_x.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed x test")
        image2_x1 = flip1.shear(q1).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x1.array, image2_x1.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed x1 test")
        image2_x2 = flip1.shear(s1).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x2.array, image2_x2.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed x2 test")
        image2_k = flip1.drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k.array, image2_k.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed k test")
        image2_k1 = flip1.shear(q1).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k1.array, image2_k1.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed k1 test")
        image2_k2 = flip1.shear(s1).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k2.array, image2_k2.array[:,::-1], decimal=decimal,
            err_msg="Flipping image around y-axis failed k2 test")

        if close_maxsb:
            np.testing.assert_allclose(
                    image2_x.array.max(), flip1.max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x1.array.max(), flip1.shear(q).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x2.array.max(), flip1.shear(s).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")

        # Flip around x axis (i.e. y -> -y)
        flip2 = prof.transform(1, 0, 0, -1)
        image2_x = flip2.drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x.array, image2_x.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed x test")
        image2_x1 = flip2.shear(q1).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x1.array, image2_x1.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed x1 test")
        image2_x2 = flip2.shear(s1).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x2.array, image2_x2.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed x2 test")
        image2_k = flip2.drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k.array, image2_k.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed k test")
        image2_k1 = flip2.shear(q1).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k1.array, image2_k1.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed k1 test")
        image2_k2 = flip2.shear(s1).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k2.array, image2_k2.array[::-1,:], decimal=decimal,
            err_msg="Flipping image around x-axis failed k2 test")

        if close_maxsb:
            np.testing.assert_allclose(
                    image2_x.array.max(), flip2.max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x1.array.max(), flip2.shear(q).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x2.array.max(), flip2.shear(s).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")

        # Flip around x=y (i.e. y -> x, x -> y)
        flip3 = prof.transform(0, 1, 1, 0)
        image2_x = flip3.drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x.array, np.transpose(image2_x.array), decimal=decimal,
            err_msg="Flipping image around x=y failed x test")
        image2_x1 = flip3.shear(q2).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x1.array, np.transpose(image2_x1.array), decimal=decimal,
            err_msg="Flipping image around x=y failed x1 test")
        image2_x2 = flip3.shear(s2).drawImage(image=im.copy(), method='no_pixel')
        np.testing.assert_array_almost_equal(
            image_x2.array, np.transpose(image2_x2.array), decimal=decimal,
            err_msg="Flipping image around x=y failed x2 test")
        image2_k = flip3.drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k.array, np.transpose(image2_k.array), decimal=decimal,
            err_msg="Flipping image around x=y failed k test")
        image2_k1 = flip3.shear(q2).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k1.array, np.transpose(image2_k1.array), decimal=decimal,
            err_msg="Flipping image around x=y failed k1 test")
        image2_k2 = flip3.shear(s2).drawImage(image=im.copy())
        np.testing.assert_array_almost_equal(
            image_k2.array, np.transpose(image2_k2.array), decimal=decimal,
            err_msg="Flipping image around x=y failed k2 test")

        if close_maxsb:
            np.testing.assert_allclose(
                    image2_x.array.max(), flip3.max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x1.array.max(), flip3.shear(q).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")
            np.testing.assert_allclose(
                    image2_x2.array.max(), flip3.shear(s).max_sb*im.scale**2, rtol=0.2,
                    err_msg="max_sb did not match maximum pixel value")

        do_pickle(prof, lambda x: x.drawImage(image=im.copy(), method='no_pixel'))
        do_pickle(flip1, lambda x: x.drawImage(image=im.copy(), method='no_pixel'))
        do_pickle(flip2, lambda x: x.drawImage(image=im.copy(), method='no_pixel'))
        do_pickle(flip3, lambda x: x.drawImage(image=im.copy(), method='no_pixel'))
        do_pickle(prof)
        do_pickle(flip1)
        do_pickle(flip2)
        do_pickle(flip3)
Exemple #21
0
def make_sim_obs(rng, noise, shear, show=False):
    """
    simulate an exponential object with moffat psf

    the hlr of the exponential is drawn from a gaussian
    with mean 0.4 arcseconds and sigma 0.2

    Parameters
    ----------
    rng: np.random.RandomState
        The random number generator
    noise: float
        Noise for the image
    shear: (g1, g2)
        The shear in each component

    Returns
    -------
    ngmix.Observation
    """

    psf_noise = 1.0e-6

    nobj = rng.poisson(NOBJ_MEAN)

    psf_fwhm = 0.9

    psf = galsim.Moffat(
        beta=2.5, fwhm=psf_fwhm,
    ).shear(
        g1=0.02,
        g2=-0.01,
    )

    objs0 = []

    for i in range(nobj):
        dx, dy = rng.uniform(low=-OFFSET_MAX, high=OFFSET_MAX, size=2)
        gal_hlr = rng.normal(loc=0.4, scale=0.2)
        obj0 = galsim.Exponential(
            half_light_radius=gal_hlr,
        ).shear(
            g1=shear[0],
            g2=shear[1],
        ).shift(
            dx=dx,
            dy=dy,
        )
        objs0.append(obj0)

    objs0 = galsim.Sum(objs0)
    objs = galsim.Convolve(psf, objs0)

    psf_im = psf.drawImage(scale=SCALE).array
    im = objs.drawImage(nx=DIM, ny=DIM, scale=SCALE).array

    psf_im += rng.normal(scale=psf_noise, size=psf_im.shape)
    im += rng.normal(scale=noise, size=im.shape)

    cen = (np.array(im.shape)-1.0)/2.0
    psf_cen = (np.array(psf_im.shape)-1.0)/2.0

    jacobian = ngmix.DiagonalJacobian(
        row=cen[0] + dy/SCALE, col=cen[1] + dx/SCALE, scale=SCALE,
    )
    psf_jacobian = ngmix.DiagonalJacobian(
        row=psf_cen[0], col=psf_cen[1], scale=SCALE,
    )

    wt = im*0 + 1.0/noise**2
    psf_wt = psf_im*0 + 1.0/psf_noise**2

    psf_obs = ngmix.Observation(
        psf_im,
        weight=psf_wt,
        jacobian=psf_jacobian,
    )

    obs = ngmix.Observation(
        im,
        weight=wt,
        jacobian=jacobian,
        psf=psf_obs,
    )

    if show:
        from espy import images
        images.view(im)

    return obs
Exemple #22
0
def test_fourier_sqrt():
    """Test that the FourierSqrt operator is the inverse of auto-convolution.
    """
    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 profiles 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")

    check_basic(sqrt1, "FourierSqrt", do_x=False)

    # 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
    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.flux, sqrt.flux)
    np.testing.assert_almost_equal(check.xValue(check.centroid), check.max_sb)
    print('check.max_sb = ', check.max_sb)
    print('sqrt.max_sb = ', sqrt.max_sb)
    # This isn't super accurate...
    np.testing.assert_allclose(check.max_sb, sqrt.max_sb, rtol=0.1)
    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, lambda x: x.drawImage(method='no_pixel'))
    do_pickle(sqrt1)

    # Should raise an exception for invalid arguments
    assert_raises(TypeError, galsim.FourierSqrt)
    assert_raises(TypeError, galsim.FourierSqrt, myImg1)
    assert_raises(TypeError, galsim.FourierSqrt, [psf])
    assert_raises(TypeError, galsim.FourierSqrt, psf, psf)
    assert_raises(TypeError, galsim.FourierSqrt, psf, real_space=False)
    assert_raises(TypeError, galsim.FourierSqrtProfile)
    assert_raises(TypeError, galsim.FourierSqrtProfile, myImg1)
    assert_raises(TypeError, galsim.FourierSqrtProfile, [psf])
    assert_raises(TypeError, galsim.FourierSqrtProfile, psf, psf)
    assert_raises(TypeError, galsim.FourierSqrtProfile, psf, real_space=False)

    assert_raises(NotImplementedError, sqrt1.xValue, galsim.PositionD(0, 0))
    assert_raises(NotImplementedError, sqrt1.drawReal, myImg1)
    assert_raises(NotImplementedError, sqrt1.shoot, 1)
Exemple #23
0
def make_obs(
    *,
    n_grid=6,
    dim=235,
    buff=20,
    scale=0.2,
    psf_fwhm=0.9,
    hlr=0.5,
    nse=1e-7,
    star_dxdy=117,
    star_rad=1,
    n_stars=5,
    seed=10,
    shear=(0.02, 0.0),
    mcal_shear=(0.0, 0.0)
):
    rng = np.random.RandomState(seed=seed)
    n_gals = n_grid**2
    tot_dim = dim + 2*buff
    tot_cen = (tot_dim-1)/2
    gloc = (np.arange(n_grid) + 0.5) * (dim / n_grid) - dim/2
    gloc *= scale
    dx, dy = np.meshgrid(gloc, gloc)
    dx = dx.ravel() + rng.uniform(low=-0.5, high=0.5, size=n_gals) * scale
    dy = dy.ravel() + rng.uniform(low=-0.5, high=0.5, size=n_gals) * scale
    ds = np.arange(n_gals) / (n_gals-1) * 0 + 1
    gals = galsim.Sum([
        galsim.Exponential(
            half_light_radius=hlr * _ds
        ).shift(
            _dx, _dy
        ).shear(
            g1=shear[0], g2=shear[1]
        ).shear(
            g1=mcal_shear[0], g2=mcal_shear[1]
        )
        for _ds, _dx, _dy in zip(ds, dx, dy)
    ])
    psf = galsim.Gaussian(fwhm=psf_fwhm)
    objs = galsim.Convolve([gals, psf])
    im = objs.drawImage(nx=tot_dim, ny=tot_dim, scale=scale).array

    im += rng.normal(size=im.shape, scale=nse)
    nim = rng.normal(size=im.shape, scale=nse)

    psf_dim = 53
    psf_cen = (psf_dim-1)/2
    psf_im = psf.drawImage(nx=psf_dim, ny=psf_dim, scale=scale).array

    # make bmask
    bmask = np.zeros_like(im, dtype=np.int32)
    x, y = np.meshgrid(np.arange(tot_dim), np.arange(tot_dim))
    sdata = []
    for _ in range(n_stars):
        sr2 = np.power(10.0, rng.uniform(low=star_rad, high=star_rad+0.2))**2
        sx = rng.uniform(low=-star_dxdy, high=star_dxdy) + tot_cen
        sy = rng.uniform(low=-star_dxdy, high=star_dxdy) + tot_cen
        dr2 = (x - sx)**2 + (y - sy)**2
        msk = dr2 < sr2
        bmask[msk] |= 2**0
        im[msk] = 0
        sdata.append((sx, sy, np.sqrt(sr2)))

    psf_obs = ngmix.Observation(
        image=psf_im,
        weight=np.ones_like(psf_im) / nse**2,
        jacobian=ngmix.DiagonalJacobian(scale=scale, row=psf_cen, col=psf_cen)
    )
    wgt = np.ones_like(im) / nse**2
    msk = bmask != 0
    wgt[msk] = 0.0
    mfrac = np.zeros_like(im)
    mfrac[msk] = 1.0
    obs = ngmix.Observation(
        image=im,
        noise=nim,
        weight=wgt,
        bmask=bmask,
        ormask=bmask,
        jacobian=ngmix.DiagonalJacobian(scale=scale, row=tot_cen, col=tot_cen),
        psf=psf_obs
    )
    obs.mfrac = mfrac
    mbobs = ngmix.MultiBandObsList()
    obsl = ngmix.ObsList()
    obsl.append(obs)
    mbobs.append(obsl)
    mbobs.meta["sdata"] = sdata
    return mbobs
def test_coadd_image_correct(crazy_wcs, crazy_obj):

    rng = np.random.RandomState(seed=42)

    n_coadd = 10
    psf_dim = 51
    coadd_dim = 53

    coadd_cen = (coadd_dim + 1) / 2

    se_dim = int(np.ceil(coadd_dim * np.sqrt(2)))
    if se_dim % 2 == 0:
        se_dim += 1

    se_cen = (se_dim + 1) / 2
    scale = 0.2
    noise_std = 0.1
    world_origin = galsim.CelestialCoord(0 * galsim.degrees,
                                         0 * galsim.degrees)

    aff = galsim.PixelScale(scale).affine()
    aff = aff.withOrigin(galsim.PositionD(coadd_cen, coadd_cen),
                         galsim.PositionD(0, 0))
    coadd_wcs = galsim.TanWCS(
        aff,
        world_origin,
    )

    def _gen_psf_func(wcs, fwhm):
        def _psf_func(*args, **kargs):
            return galsim.Gaussian(fwhm=fwhm).drawImage(
                nx=101, ny=101,
                wcs=wcs.local(world_pos=world_origin)), galsim.PositionD(0, 0)

        return _psf_func

    wgts = []
    objs = []
    psf_objs = []
    exps = []
    for _ in range(n_coadd):
        if crazy_obj:
            _fwhm = 2.9 * (1.0 + rng.normal() * 0.1)
            _g1 = rng.normal() * 0.3
            _g2 = rng.normal() * 0.3
            obj = galsim.Gaussian(fwhm=_fwhm).shear(g1=_g1, g2=_g2)
        else:
            obj = galsim.Gaussian(fwhm=2.9).shear(g1=-0.1, g2=0.3)

        objs.append(obj)

        if crazy_wcs:
            shear = galsim.Shear(g1=rng.normal() * 0.01,
                                 g2=rng.normal() * 0.01)
            aff = galsim.ShearWCS(scale, shear).affine()
            aff = aff.withOrigin(galsim.PositionD(se_cen, se_cen),
                                 galsim.PositionD(0, 0))
            wcs = galsim.TanWCS(
                aff,
                world_origin,
            )
        else:
            aff = galsim.PixelScale(scale).affine()
            aff = aff.withOrigin(galsim.PositionD(se_cen, se_cen),
                                 galsim.PositionD(0, 0))
            wcs = galsim.TanWCS(
                aff,
                world_origin,
            )

        _noise = noise_std * (1 + (rng.uniform() - 0.5) * 2 * 0.05)
        wgts.append(1.0 / _noise**2)

        bmsk = galsim.ImageI(np.zeros((se_dim, se_dim)))

        img = obj.drawImage(
            nx=se_dim,
            ny=se_dim,
            wcs=wcs.local(world_pos=world_origin),
        )

        if crazy_obj:
            _psf_fwhm = 1.0 * (1.0 + rng.normal() * 0.1)
        else:
            _psf_fwhm = 1.0

        psf = galsim.Gaussian(fwhm=_psf_fwhm)
        psf_objs.append(psf)

        exp = make_exp(
            gsimage=img,
            bmask=bmsk,
            noise=_noise,
            galsim_wcs=wcs,
            galsim_psf=psf,
            psf_dim=psf_dim,
        )
        exps.append(exp)

    coadd_bbox = geom.Box2I(
        geom.IntervalI(min=0, max=coadd_dim - 1),
        geom.IntervalI(min=0, max=coadd_dim - 1),
    )
    coadd, exp_info = make_coadd_obs(
        exps=exps,
        coadd_wcs=make_dm_wcs(coadd_wcs),
        coadd_bbox=coadd_bbox,
        psf_dims=(psf_dim, ) * 2,
        rng=rng,
        remove_poisson=False,
    )

    coadd_img = coadd.image
    coadd_psf = coadd.psf.image

    wgts = np.array(wgts) / np.sum(wgts)
    true_coadd_img = galsim.Sum([
        obj.withFlux(wgt) for obj, wgt in zip(objs, wgts)
    ]).drawImage(nx=coadd_dim,
                 ny=coadd_dim,
                 wcs=coadd_wcs.local(world_pos=world_origin)).array

    true_coadd_psf = galsim.Sum([
        obj.withFlux(wgt) for obj, wgt in zip(psf_objs, wgts)
    ]).drawImage(nx=psf_dim,
                 ny=psf_dim,
                 wcs=coadd_wcs.local(world_pos=world_origin)).array

    if not crazy_wcs:
        rtol = 0
        atol = 5e-7
    else:
        rtol = 0
        atol = 5e-5

    coadd_img_err = np.max(np.abs(coadd_img - true_coadd_img))
    coadd_psf_err = np.max(np.abs(coadd_psf - true_coadd_psf))
    print("image max abs error:", coadd_img_err)
    print("psf max abs error:", coadd_psf_err)

    if not np.allclose(coadd_img, true_coadd_img, rtol=rtol, atol=atol):
        _plot_cmp(coadd_img, true_coadd_img, rtol, atol, crazy_obj, crazy_wcs,
                  "img")

    if not np.allclose(coadd_psf, true_coadd_psf, rtol=rtol, atol=atol):
        _plot_cmp(coadd_psf, true_coadd_psf, rtol, atol, crazy_obj, crazy_wcs,
                  "psf")

    assert np.allclose(coadd_img, true_coadd_img, rtol=rtol, atol=atol)
    assert np.allclose(coadd_psf, true_coadd_psf, rtol=rtol, atol=atol)
    assert np.all(np.isfinite(coadd.noise))
Exemple #25
0
def make_sim(seed=42):
    scale = 0.25
    flux = 10.0**(0.4 * (30 - 18))
    noise = 10
    ngals = 120
    shape = 361
    buff = 60
    inner_shape = (shape - 2*buff)
    im_cen = (shape-1)/2

    rng = np.random.RandomState(seed=seed)
    us = rng.uniform(low=-inner_shape/2, high=inner_shape/2, size=ngals) * scale
    vs = rng.uniform(low=-inner_shape/2, high=inner_shape/2, size=ngals) * scale
    wcs = galsim.PixelScale(scale)
    psf = galsim.Gaussian(fwhm=0.8)
    size_fac = rng.uniform(low=1.0, high=1.5, size=ngals)
    g1s = rng.normal(size=ngals) * 0.2
    g2s = rng.normal(size=ngals) * 0.2
    flux_fac = 10**rng.uniform(low=-2, high=0, size=ngals)

    # PSF image
    psf_img = psf.drawImage(nx=33, ny=33, wcs=wcs).array
    psf_cen = (psf_img.shape[0]-1)/2
    psf_jac = ngmix.jacobian.DiagonalJacobian(
        row=psf_cen,
        col=psf_cen,
        scale=scale,
    )
    target_s2n = 500.0
    target_noise = np.sqrt(np.sum(psf_img ** 2)) / target_s2n
    psf_obs = ngmix.Observation(
        psf_img,
        weight=np.ones_like(psf_img)/target_noise**2,
        jacobian=psf_jac,
    )

    # gals
    gals = []
    for u, v, sf, g1, g2, ff in zip(us, vs, size_fac, g1s, g2s, flux_fac):
        gals.append(galsim.Convolve([
            galsim.Exponential(half_light_radius=0.5 * sf),
            psf,
        ]).shear(g1=g1, g2=g2).withFlux(flux*ff).shift(u, v))
    gals = galsim.Sum(gals)

    img = gals.drawImage(nx=shape, ny=shape, wcs=wcs).array
    img += rng.normal(size=img.shape) * noise
    nse = rng.normal(size=img.shape) * noise
    wgt = img*0 + 1.0/noise**2
    msk = np.zeros(img.shape, dtype='i4')
    im_jac = ngmix.jacobian.DiagonalJacobian(
        row=im_cen,
        col=im_cen,
        scale=scale,
    )
    obs = ngmix.Observation(
        img,
        weight=wgt,
        bmask=msk,
        ormask=msk.copy(),
        jacobian=im_jac,
        psf=psf_obs,
        noise=nse,
    )

    mbobs = ngmix.MultiBandObsList()
    obslist = ngmix.ObsList()
    obslist.append(obs)
    mbobs.append(obslist)

    return mbobs
def test_coadd_psfs(crazy_wcs, crazy_psf):
    n_coadd = 10
    rng = np.random.RandomState(seed=42)

    if crazy_psf:
        psfs = []
        for _ in range(n_coadd):
            _fwhm = 0.9 * (1.0 + rng.normal() * 0.1)
            _g1 = rng.normal() * 0.3
            _g2 = rng.normal() * 0.3
            psfs.append(galsim.Gaussian(fwhm=_fwhm).shear(g1=_g1, g2=_g2))
    else:
        psfs = []
        for _ in range(n_coadd):
            psfs.append(galsim.Gaussian(fwhm=0.9).shear(g1=-0.1, g2=0.3))

    coadd_dim = 225
    coadd_cen = (coadd_dim - 1)/2

    se_dim = int(np.ceil(coadd_dim * np.sqrt(2)))
    if se_dim % 2 == 0:
        se_dim += 1
    se_cen = (se_dim - 1)/2
    scale = 0.27

    psf_dim = 33
    psf_dim_half = (psf_dim - 1)/2

    se_psf_dim = int(np.ceil(psf_dim * np.sqrt(2)))
    if se_psf_dim % 2 == 0:
        se_psf_dim += 1
    se_psf_dim_half = (se_psf_dim - 1)/2

    coadd_offset = coadd_cen - psf_dim_half

    world_origin = galsim.PositionD(
        x=coadd_cen*scale, y=coadd_cen*scale)
    origin = galsim.PositionD(x=se_cen, y=se_cen)

    coadd_wgts = rng.uniform(size=n_coadd)
    coadd_wgts /= np.sum(coadd_wgts)

    se_wcs_objs = []

    for _ in range(n_coadd):
        if crazy_wcs:
            wcs = gen_affine_wcs(
                rng=rng,
                position_angle_range=(0, 360),
                dither_range=(5, 5),
                scale=scale,
                scale_frac_std=0.05,
                shear_std=0.1,
                world_origin=world_origin,
                origin=origin)
        else:
            wcs = gen_affine_wcs(
                rng=rng,
                position_angle_range=(0, 0),
                dither_range=(0, 0),
                scale=scale,
                scale_frac_std=0.0,
                shear_std=0.0,
                world_origin=world_origin,
                origin=origin)

        se_wcs_objs.append(wcs)

    se_psfs = []
    se_offsets = []
    for wcs, psf in zip(se_wcs_objs, psfs):
        pos = wcs.toImage(world_origin)
        xp = int(pos.x + 0.5)
        yp = int(pos.y + 0.5)
        dx = pos.x - xp
        dy = pos.y - yp
        se_offsets.append((xp - se_psf_dim_half, yp - se_psf_dim_half))
        se_psfs.append(psf.drawImage(
            nx=se_psf_dim,
            ny=se_psf_dim,
            wcs=wcs.local(world_pos=world_origin),
            offset=galsim.PositionD(x=dx, y=dy)).array)

    coadd_psf = coadd_psfs(
        se_psfs, se_wcs_objs, coadd_wgts,
        scale, psf_dim, coadd_offset, se_offsets)

    true_coadd_psf = galsim.Sum(
        [psf.withFlux(wgt) for psf, wgt in zip(psfs, coadd_wgts)]
    ).drawImage(
        nx=psf_dim,
        ny=psf_dim,
        scale=scale).array
    true_coadd_psf /= np.sum(true_coadd_psf)

    if not crazy_psf and not crazy_wcs:
        rtol = 0
        atol = 1e-7
    else:
        rtol = 0
        atol = 8e-4

    if not np.allclose(coadd_psf, true_coadd_psf, rtol=rtol, atol=atol):
        import matplotlib.pyplot as plt
        import seaborn as sns
        fig, axs = plt.subplots(nrows=2, ncols=2)
        sns.heatmap(true_coadd_psf, ax=axs[0, 0])
        sns.heatmap(coadd_psf, ax=axs[0, 1])
        sns.heatmap(coadd_psf - true_coadd_psf, ax=axs[1, 0])
        sns.heatmap(
            np.abs(coadd_psf - true_coadd_psf) <
            atol + rtol * np.abs(true_coadd_psf),
            ax=axs[1, 1])
        print(np.max(np.abs(coadd_psf - true_coadd_psf)))

    assert np.allclose(coadd_psf, true_coadd_psf, rtol=rtol, atol=atol)
Exemple #27
0
def test_coadd_psfs(crazy_wcs, crazy_psf):
    n_coadd = 10
    rng = np.random.RandomState(seed=42)

    if crazy_psf:
        psfs = []
        for _ in range(n_coadd):
            _fwhm = 2.9 * (1.0 + rng.normal() * 0.1)
            _g1 = rng.normal() * 0.3
            _g2 = rng.normal() * 0.3
            psfs.append(galsim.Gaussian(fwhm=_fwhm).shear(g1=_g1, g2=_g2))
    else:
        psfs = []
        for _ in range(n_coadd):
            psfs.append(galsim.Gaussian(fwhm=2.9).shear(g1=-0.1, g2=0.3))

    scale = 0.213

    coadd_psf_dim = 103
    coadd_psf_cen = (coadd_psf_dim - 1)/2

    se_psf_dim = 103
    se_psf_cen = (se_psf_dim - 1)/2

    coadd_wgts = rng.uniform(size=n_coadd)
    coadd_wgts /= np.sum(coadd_wgts)

    world_origin = galsim.PositionD(
        x=coadd_psf_cen * scale,
        y=coadd_psf_cen * scale)
    origin = galsim.PositionD(x=se_psf_cen, y=se_psf_cen)

    se_wcs_objs = []
    for _ in range(n_coadd):
        if crazy_wcs:
            wcs = gen_affine_wcs(
                rng=rng,
                position_angle_range=(0, 360),
                dither_range=(5, 5),
                scale=scale,
                scale_frac_std=0.05,
                shear_std=0.1,
                world_origin=world_origin,
                origin=origin)
        else:
            wcs = gen_affine_wcs(
                rng=rng,
                position_angle_range=(0, 0),
                dither_range=(0, 0),
                scale=scale,
                scale_frac_std=0.0,
                shear_std=0.0,
                world_origin=world_origin,
                origin=origin)

        se_wcs_objs.append(wcs)

    se_psfs = []
    for wcs, psf in zip(se_wcs_objs, psfs):
        # we need to offset the PSF images to match the image origin in the
        # stamp
        offset = np.array([
            wcs.x0 - se_psf_cen,
            wcs.y0 - se_psf_cen])
        se_psfs.append(psf.drawImage(
            nx=se_psf_dim,
            ny=se_psf_dim,
            wcs=wcs.local(world_pos=world_origin),
            offset=offset).array)

    coadd_psf = coadd_psfs(
        se_psfs, se_wcs_objs, coadd_wgts,
        scale, coadd_psf_dim)

    true_coadd_psf = galsim.Sum(
        [psf.withFlux(wgt) for psf, wgt in zip(psfs, coadd_wgts)]
    ).drawImage(
        nx=coadd_psf_dim,
        ny=coadd_psf_dim,
        scale=scale).array
    true_coadd_psf /= np.sum(true_coadd_psf)

    if not crazy_wcs:
        rtol = 0
        atol = 5e-8
    else:
        rtol = 0
        atol = 5e-5

    if not np.allclose(coadd_psf, true_coadd_psf, rtol=rtol, atol=atol):
        import matplotlib.pyplot as plt
        import seaborn as sns
        fig, axs = plt.subplots(nrows=2, ncols=2)
        sns.heatmap(true_coadd_psf, ax=axs[0, 0])
        sns.heatmap(coadd_psf, ax=axs[0, 1])
        sns.heatmap(coadd_psf - true_coadd_psf, ax=axs[1, 0])
        sns.heatmap(
            np.abs(coadd_psf - true_coadd_psf) <
            atol + rtol * np.abs(true_coadd_psf),
            ax=axs[1, 1])
        print(np.max(np.abs(coadd_psf - true_coadd_psf)))

    assert np.allclose(coadd_psf, true_coadd_psf, rtol=rtol, atol=atol)
Exemple #28
0
def test_coadd_image_noise_interpfrac(crazy_wcs, crazy_obj):
    n_coadd = 10
    rng = np.random.RandomState(seed=42)

    if crazy_obj:
        objs = []
        for _ in range(n_coadd):
            _fwhm = 2.9 * (1.0 + rng.normal() * 0.1)
            _g1 = rng.normal() * 0.3
            _g2 = rng.normal() * 0.3
            objs.append(galsim.Gaussian(fwhm=_fwhm).shear(g1=_g1, g2=_g2))
    else:
        objs = []
        for _ in range(n_coadd):
            objs.append(galsim.Gaussian(fwhm=2.9).shear(g1=-0.1, g2=0.3))

    coadd_dim = 53
    coadd_cen = (coadd_dim - 1)/2

    se_dim = int(np.ceil(coadd_dim * np.sqrt(2)))
    if se_dim % 2 == 0:
        se_dim += 1
    se_cen = (se_dim - 1)/2
    scale = 0.2

    world_origin = galsim.PositionD(
        x=coadd_cen*scale, y=coadd_cen*scale)
    origin = galsim.PositionD(x=se_cen, y=se_cen)

    coadd_wgts = rng.uniform(size=n_coadd)
    coadd_wgts /= np.sum(coadd_wgts)

    se_wcs_objs = []

    for _ in range(n_coadd):
        if crazy_wcs:
            wcs = gen_affine_wcs(
                rng=rng,
                position_angle_range=(0, 360),
                dither_range=(-5, 5),
                scale=scale,
                scale_frac_std=0.05,
                shear_std=0.1,
                world_origin=world_origin,
                origin=origin)
        else:
            wcs = gen_affine_wcs(
                rng=rng,
                position_angle_range=(0, 0),
                dither_range=(0, 0),
                scale=scale,
                scale_frac_std=0.0,
                shear_std=0.0,
                world_origin=world_origin,
                origin=origin)

        se_wcs_objs.append(wcs)

    se_images = []
    se_noises = []
    se_interp_fracs = []
    for wcs, obj in zip(se_wcs_objs, objs):
        pos = wcs.toImage(world_origin)
        dx = pos.x - se_cen
        dy = pos.y - se_cen
        se_images.append(obj.drawImage(
            nx=se_dim,
            ny=se_dim,
            wcs=wcs.local(world_pos=world_origin),
            offset=galsim.PositionD(x=dx, y=dy)).array)
        se_noises.append(rng.normal(size=(se_dim, se_dim)))
        se_interp_fracs.append(rng.uniform(size=(se_dim, se_dim)))

    coadd_img, coadd_nse, coadd_intp = coadd_image_noise_interpfrac(
        se_images, se_noises, se_interp_fracs, se_wcs_objs,
        coadd_wgts, scale, coadd_dim)

    true_coadd_img = galsim.Sum(
        [obj.withFlux(wgt) for obj, wgt in zip(objs, coadd_wgts)]
    ).drawImage(
        nx=coadd_dim,
        ny=coadd_dim,
        scale=scale).array

    if not crazy_wcs:
        rtol = 0
        atol = 5e-7
    else:
        rtol = 0
        atol = 5e-5

    if not np.allclose(coadd_img, true_coadd_img, rtol=rtol, atol=atol):
        import matplotlib.pyplot as plt
        import seaborn as sns
        fig, axs = plt.subplots(nrows=2, ncols=2)
        sns.heatmap(true_coadd_img, ax=axs[0, 0])
        sns.heatmap(coadd_img, ax=axs[0, 1])
        sns.heatmap(coadd_img - true_coadd_img, ax=axs[1, 0])
        sns.heatmap(
            np.abs(coadd_img - true_coadd_img) <
            atol + rtol * np.abs(true_coadd_img),
            ax=axs[1, 1])
        print(np.max(np.abs(coadd_img - true_coadd_img)))

    assert np.allclose(coadd_img, true_coadd_img, rtol=rtol, atol=atol)
    assert np.all(np.isfinite(coadd_nse))
    assert np.all(np.isfinite(coadd_intp))
    assert np.all((coadd_intp >= 0) & (coadd_intp <= 1))
Exemple #29
0
    def _draw_objects(self):
        """
        this is dumb, drawing into the full image when
        we don't need to
        """

        self.imlist = []

        shear = self.get('shear', None)

        cdisk = self['pdfs']['disk']
        cbulge = self['pdfs'].get('bulge', None)
        cknots = self['pdfs'].get('knots', None)

        dims = self['dims']
        cen = (np.array(dims) - 1.0) / 2.0

        for band in range(self['nband']):
            objects = []
            for iobj, obj_parts in enumerate(self.objlist):

                disk = obj_parts['disk'] * cdisk['color'][band]
                tparts = [disk]

                if cbulge is not None:
                    bulge = obj_parts['bulge'] * cbulge['color'][band]
                    tparts.append(bulge)

                if cknots is not None:
                    knots = obj_parts['knots'] * cknots['color'][band]
                    tparts.append(knots)

                if len(tparts) == 1:
                    obj = tparts[0]
                else:
                    obj = galsim.Sum(tparts)

                obj = obj.shift(
                    dx=obj_parts['cen'][1],
                    dy=obj_parts['cen'][0],
                )

                if shear is not None and not self['shear_all']:
                    obj = obj.shear(
                        g1=shear[0],
                        g2=shear[1],
                    )

                if band == 0:
                    ocen = obj.centroid
                    row = cen[0] + ocen.y / self['pixel_scale']
                    col = cen[1] + ocen.x / self['pixel_scale']
                    self._obj_data['y'][iobj] = row
                    self._obj_data['x'][iobj] = col

                objects.append(obj)

            objects = galsim.Sum(objects)

            if shear is not None and self['shear_all']:
                objects = objects.shear(
                    g1=shear[0],
                    g2=shear[1],
                )

            convolved_objects = galsim.Convolve(objects, self.psf)

            kw = {'scale': self['pixel_scale']}
            kw['method'] = self['draw_method']

            dims = self.get('dims', None)
            if dims is not None:
                kw['nx'], kw['ny'] = dims[1], dims[0]

            image = convolved_objects.drawImage(**kw).array
            self.imlist.append(image)
Exemple #30
0
def test(ntrial=1, dim=2000, show=False):
    import galsim
    import biggles
    import images

    rng = np.random.RandomState()

    nobj_per = 4
    nknots = 100
    knot_flux_frac = 0.001
    nknots_low, nknots_high = 1, 100

    nband = 3
    noises = [0.0005, 0.001, 0.0015]
    scale = 0.263

    psf = galsim.Gaussian(fwhm=0.9)
    dims = 64, 64
    flux_low, flux_high = 0.5, 1.5
    r50_low, r50_high = 0.1, 2.0

    fracdev_low, fracdev_high = 0.001, 0.99

    bulge_colors = np.array([0.5, 1.0, 1.5])
    disk_colors = np.array([1.25, 1.0, 0.75])
    knots_colors = np.array([1.5, 1.0, 0.5])

    sigma = dims[0]/2.0/4.0*scale
    maxrad = dims[0]/2.0/2.0 * scale

    tm0 = time.time()
    nobj_meas = 0

    for trial in range(ntrial):
        print("trial: %d/%d" % (trial+1, ntrial))
        all_band_obj = []
        for i in range(nobj_per):

            nknots = int(rng.uniform(low=nknots_low, high=nknots_high))

            r50 = rng.uniform(low=r50_low, high=r50_high)
            flux = rng.uniform(low=flux_low, high=flux_high)

            dx, dy = rng.normal(scale=sigma, size=2).clip(
                min=-maxrad,
                max=maxrad,
            )

            g1d, g2d = rng.normal(scale=0.2, size=2).clip(max=0.5)
            g1b = 0.5*g1d+rng.normal(scale=0.02)
            g2b = 0.5*g2d+rng.normal(scale=0.02)

            fracdev = rng.uniform(low=fracdev_low, high=fracdev_high)

            flux_bulge = fracdev*flux
            flux_disk = (1-fracdev)*flux
            flux_knots = nknots*knot_flux_frac*flux_disk
            print("fracdev:", fracdev, "nknots:", nknots)

            bulge_obj = galsim.DeVaucouleurs(
                half_light_radius=r50
            ).shear(g1=g1b, g2=g2b)

            disk_obj = galsim.Exponential(
                half_light_radius=r50
            ).shear(g1=g1d, g2=g2d)

            knots_obj = galsim.RandomWalk(
                npoints=nknots,
                profile=disk_obj,
            )  # .shear(g1=g1d, g2=g2d)

            band_objs = []
            for band in range(nband):
                band_disk = disk_obj.withFlux(flux_disk*disk_colors[band])
                band_bulge = bulge_obj.withFlux(flux_bulge*bulge_colors[band])
                band_knots = knots_obj.withFlux(flux_knots*knots_colors[band])

                obj = galsim.Sum(band_disk, band_bulge, band_knots).shift(
                    dx=dx,
                    dy=dy,
                )
                obj = galsim.Convolve(obj, psf)
                band_objs.append(obj)

            all_band_obj.append(band_objs)

        jacob = ngmix.DiagonalJacobian(
            row=0,
            col=0,
            scale=scale,
        )
        wcs = jacob.get_galsim_wcs()
        psfim = psf.drawImage(wcs=wcs).array
        psf_obs = get_psf_obs(psfim, jacob)

        dlist = []
        for band in range(nband):
            band_objects = [o[band] for o in all_band_obj]
            obj = galsim.Sum(band_objects)

            im = obj.drawImage(nx=dims[1], ny=dims[0], wcs=wcs).array
            im = obj.drawImage(nx=dims[1], ny=dims[0], scale=scale).array

            im += rng.normal(scale=noises[band], size=im.shape)
            wt = im*0 + 1.0/noises[band]**2

            dlist.append(
                dict(
                    image=im,
                    weight=wt,
                    wcs=wcs,
                )
            )

        mer = MEDSifier(dlist)

        mg = mer.get_meds(0)
        mr = mer.get_meds(1)
        mi = mer.get_meds(2)
        nobj = mg.size
        print("        found", nobj, "objects")
        nobj_meas += nobj

        list_of_obs = []
        for i in range(nobj):

            gobslist = mg.get_obslist(i, weight_type='uberseg')
            robslist = mr.get_obslist(i, weight_type='uberseg')
            iobslist = mi.get_obslist(i, weight_type='uberseg')
            mbo = ngmix.MultiBandObsList()
            mbo.append(gobslist)
            mbo.append(robslist)
            mbo.append(iobslist)

            list_of_obs.append(mbo)

        for mbo in list_of_obs:
            for obslist in mbo:
                for obs in obslist:
                    obs.set_psf(psf_obs)

        prior = moflib.get_mof_prior(list_of_obs, "bdf", rng)
        mof_fitter = moflib.MOFStamps(
            list_of_obs,
            "bdf",
            prior=prior,
        )
        band = 2
        guess = moflib.get_stamp_guesses(list_of_obs, band, "bdf", rng)
        mof_fitter.go(guess)

        if show:
            # corrected images
            tab = biggles.Table(1, 2)
            rgb = images.get_color_image(
                dlist[2]['image'].transpose(),
                dlist[1]['image'].transpose(),
                dlist[0]['image'].transpose(),
                nonlinear=0.1,
            )
            rgb *= 1.0/rgb.max()

            tab[0, 0] = images.view_mosaic(
                [rgb,
                 mer.seg,
                 mer.detim],
                titles=['image', 'seg', 'detim'],
                show=False,
                # dims=[dim, dim],
            )

            imlist = []
            for iobj, mobs in enumerate(list_of_obs):
                cmobs = mof_fitter.make_corrected_obs(iobj)

                gim = images.make_combined_mosaic(
                    [mobs[0][0].image, cmobs[0][0].image],
                )
                rim = images.make_combined_mosaic(
                    [mobs[1][0].image, cmobs[1][0].image],
                )
                iim = images.make_combined_mosaic(
                    [mobs[2][0].image, cmobs[2][0].image],
                )

                rgb = images.get_color_image(
                    iim.transpose(),
                    rim.transpose(),
                    gim.transpose(),
                    nonlinear=0.1,
                )
                rgb *= 1.0/rgb.max()
                imlist.append(rgb)

            plt = images.view_mosaic(imlist, show=False)
            tab[0, 1] = plt
            tab.show(width=dim*2, height=dim)

            if ntrial > 1:
                if 'q' == input("hit a key: "):
                    return

    total_time = time.time()-tm0
    print("time per group:", total_time/ntrial)
    print("time per object:", total_time/nobj_meas)