Example #1
0
def test_poly_mean():
    # Zero'th order polynomial fitting should be pretty trivial, just
    # the same as the mean fitting. So much of this code is just taken from
    # the mean testing in test_simple
    N = 0
    nparam = 5
    interp = piff.Polynomial(N)
    nstars = 100

    # Choose some random values of star parameters
    np_rng = np.random.RandomState(1234)
    vectors = [np_rng.random_sample(size=nparam) for i in range(nstars)]

    # take the mean of them. Our curve fit should be able to reproduce this.
    mean = np.mean(vectors, axis=0)

    # Choose some random positions in the field.
    data = [
        piff.Star.makeTarget(u=np_rng.random_sample() * 10,
                             v=np_rng.random_sample() * 10).data
        for i in range(nstars)
    ]
    fit = [piff.StarFit(v) for v in vectors]
    stars = [piff.Star(d, f) for d, f in zip(data, fit)]

    # Run our solver.
    interp.solve(stars)

    # we expect one set of coefficients per object
    assert len(interp.coeffs) == 5

    # We should have very close values (not necessarily identical) since
    # we calculate these in numerically different ways.
    for mu, val in zip(mean, interp.coeffs):
        assert np.isclose(mu, val[0, 0])

    # We also expect that if we interpolate to any point we just
    # get the mean as well
    for i in range(30):
        target = piff.Star.makeTarget(u=np_rng.random_sample() * 10,
                                      v=np_rng.random_sample() * 10)
        target = interp.interpolate(target)
        np.testing.assert_almost_equal(target.fit.params, mean)

    # Now test running it via the config parser
    config = {
        'interp': {
            'type': 'Polynomial',
            'order': 0,
        }
    }
    logger = piff.config.setup_logger()
    interp = piff.Interp.process(config['interp'], logger)
    interp.solve(stars)

    # Same tests
    assert len(interp.coeffs) == 5
    for mu, val in zip(mean, interp.coeffs):
        assert np.isclose(mu, val[0, 0])
    np.testing.assert_almost_equal(target.fit.params, mean)
Example #2
0
def test_twodstats():
    """Make sure we can execute and print a readout of the plot
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(2)
    else:
        logger = None

    model = piff.Gaussian(fastfit=True)
    interp = piff.Polynomial(order=1)  # should find that order=1 is better
    # create background model
    stars, true_model = generate_starlist(100)
    psf = piff.SimplePSF(model, interp)
    psf.fit(stars, None, None)

    # check the coeffs of sigma and g2, which are actually linear fits
    # skip g1 since it is actually a 2d parabola
    # factor of 0.263 is to account for going from pixel xy to wcs uv
    np.testing.assert_almost_equal(psf.interp.coeffs[0].flatten(),
                                   np.array([0.4, 0, 1. / (0.263 * 2048), 0]), decimal=4)
    np.testing.assert_almost_equal(psf.interp.coeffs[2].flatten(),
                                   np.array([-0.1 * 1000 / 2048, 0, 0.1 / (0.263 * 2048), 0]),
                                   decimal=4)

    stats = piff.TwoDHistStats(number_bins_u=5, number_bins_v=5, reducing_function='np.mean')
    stats.compute(psf, stars, logger=logger)
    # check the twodhists
    # get the average value in the bin
    u_i = 3
    v_i = 3
    icen = stats.twodhists['u'][v_i, u_i] / 0.263
    jcen = stats.twodhists['v'][v_i, u_i] / 0.263
    print('icen = ',icen)
    print('jcen = ',jcen)
    icenter = 1000
    jcenter = 2000
    # the average value in the bin should match up with the model for the average coordinates
    sigma, g1, g2 = psf_model(icen, jcen, icenter, jcenter)
    sigma_average = stats.twodhists['T'][v_i, u_i]
    g1_average = stats.twodhists['g1'][v_i, u_i]
    g2_average = stats.twodhists['g2'][v_i, u_i]
    # assert equal to 4th decimal
    print('sigma, g1, g2 = ',[sigma,g1,g2])
    print('av sigma, g1, g2 = ',[sigma_average,g1_average,g2_average])
    np.testing.assert_almost_equal([sigma, g1, g2], [sigma_average, g1_average, g2_average],
                                   decimal=2)

    # Test the plotting and writing
    twodstats_file = os.path.join('output','twodstats.pdf')
    stats.write(twodstats_file)

    # repeat for whisker
    stats = piff.WhiskerStats(number_bins_u=21, number_bins_v=21, reducing_function='np.mean')
    stats.compute(psf, stars)
    # Test the plotting and writing
    twodstats_file = os.path.join('output','whiskerstats.pdf')
    stats.write(twodstats_file)
Example #3
0
def test_poly_indexing():
    # Some indexing tests for a polynomial up to order 3
    N = 3
    interp = piff.Polynomial(orders=[N])
    interp._setup_indices(1)

    # We expect there to be these coefficients:
    # x^0 y^0   1

    # x^0 y^1   2
    # x^1 y^0   3

    # x^0 y^2   4
    # x^1 y^1   5
    # x^2 y^0   6

    # x^0 y^3   7
    # x^1 y^2   8
    # x^2 y^1   9
    # x^3 y^0   10

    # Check that we have the indices we expect
    assert interp.indices[0] == [(0, 0), (0, 1), (1, 0), (0, 2), (1, 1),
                                 (2, 0), (0, 3), (1, 2), (2, 1), (3, 0)]
    assert interp.nvariables[0] == 10

    # check the packing then unpacking a
    np_rng = np.random.RandomState(1234)
    packed = np_rng.uniform(size=interp.nvariables[0])
    unpacked = interp._unpack_coefficients(0, packed)
    packed_test = interp._pack_coefficients(0, unpacked)

    # Check that the shape is 4*4 in the unpacked (because we
    # want space for all the terms), and that we can unpack and
    # repack successfully.
    np.testing.assert_array_equal(packed, packed_test)
    assert unpacked.shape == (N + 1, N + 1)

    unpacked_test = np.zeros_like(unpacked)

    # check that we have zeros for the terms that should be zero in the matrix.
    # We don't want any terms with total exponent > N.
    # The variabled "unpacked" was created above by unpacking a random vector.
    # it should be zero where i+j>3 and have the random valus below that.
    for i in range(N + 1):
        for j in range(N + 1):
            if i + j > N:
                #Note we have two arrays, unpacked and unpacked_test
                assert unpacked[i, j] == 0.0
                unpacked_test[i, j] = 0.0

    # Now do the test the other way around, checking that
    # we can pack and then unpack
    packed_test_2 = interp._pack_coefficients(0, unpacked_test)
    unpacked_test_2 = interp._unpack_coefficients(0, packed_test_2)
    np.testing.assert_array_equal(unpacked_test_2, unpacked_test)
Example #4
0
def sub_poly_linear(type1):
    # Now lets do something more interesting - test a linear model.
    # with no noise this should fit really well, though again not
    # numerically perfectly.
    np_rng = np.random.RandomState(1234)
    nparam = 3
    N = 1
    nstars = 50
    orders = [N for i in range(nparam)]
    interp = piff.Polynomial(orders=orders, poly_type=type1)
    X = 10.0  # size of the field
    Y = 10.0

    pos = [(np_rng.random_sample() * X, np_rng.random_sample() * Y)
           for i in range(nstars)]

    # Let's make a function that is linear just as a function of one parameter
    # These are the linear fit parameters for each parameter in turn
    m1 = np_rng.uniform(size=nparam)
    m2 = np_rng.uniform(size=nparam)
    c = np_rng.uniform(size=nparam)

    def linear_func(pos):
        u = pos[0]
        v = pos[1]
        r = m1 * u + m2 * v + c
        return r

    # Simulate the vectors under this model
    vectors = [linear_func(p) for p in pos]

    # Fit them. Linear fitting is quite easy so this should be okay
    data = [piff.Star.makeTarget(u=p[0], v=p[1]).data for p in pos]
    fit = [piff.StarFit(v) for v in vectors]
    stars = [piff.Star(d, f) for d, f in zip(data, fit)]
    interp.solve(stars)

    # Check that the interpolation recovers the desired function
    for i in range(30):
        p = (np_rng.random_sample() * X, np_rng.random_sample() * Y)
        target = piff.Star.makeTarget(u=p[0], v=p[1])
        target = interp.interpolate(target)
        np.testing.assert_almost_equal(linear_func(p), target.fit.params)

    # Now test running it via the config parser
    config = {
        'interp': {
            'type': 'Polynomial',
            'order': 1,
        }
    }
    logger = piff.config.setup_logger()
    interp = piff.Interp.process(config['interp'], logger)
    interp.solve(stars)
    np.testing.assert_almost_equal(linear_func(p), target.fit.params)
Example #5
0
def sub_poly_quadratic(type1):
    # This is basically the same as linear but with
    # quadratic variation
    np_rng = np.random.RandomState(1234)
    nparam = 3
    N = 2
    nstars = 50
    orders = [N for i in range(nparam)]
    interp = piff.Polynomial(N, poly_type=type1)
    X = 10.0  # size of the field
    Y = 10.0

    pos = [(np_rng.random_sample() * X, np_rng.random_sample() * Y)
           for i in range(nstars)]

    # Let's make a function that is linear just as a function of one parameter
    # These are the linear fit parameters for each parameter in turn
    m1 = np_rng.uniform(size=nparam)
    m2 = np_rng.uniform(size=nparam)
    q1 = np_rng.uniform(size=nparam)
    c = np_rng.uniform(size=nparam)

    def quadratic_func(pos):
        u = pos[0]
        v = pos[1]
        r = q1 * u * v + m1 * u + m2 * v + c
        return r

    # Simulate the vectors under this model
    vectors = [quadratic_func(p) for p in pos]

    # Fit them.
    data = [piff.Star.makeTarget(u=p[0], v=p[1]).data for p in pos]
    fit = [piff.StarFit(v) for v in vectors]
    stars = [piff.Star(d, f) for d, f in zip(data, fit)]
    interp.solve(stars)

    # Check that the interpolation recovers the desired function
    for i in range(30):
        p = (np_rng.random_sample() * X, np_rng.random_sample() * Y)
        target = piff.Star.makeTarget(u=p[0], v=p[1])
        target = interp.interpolate(target)
        np.testing.assert_almost_equal(quadratic_func(p), target.fit.params)

    # Now test running it via the config parser
    config = {
        'interp': {
            'type': 'Polynomial',
            'order': 2,
        }
    }
    logger = piff.config.setup_logger()
    interp = piff.Interp.process(config['interp'], logger)
    interp.solve(stars)
    np.testing.assert_almost_equal(quadratic_func(p), target.fit.params)
Example #6
0
def test_poly_raise():
    # Test that we can serialize and deserialize a polynomial
    # interpolator correctly.  Copying all this stuff from above:

    np_rng = np.random.RandomState(1234)
    nparam = 3
    nstars = 50

    # Use three different sizes to test everything
    orders = [1, 2, 3]
    interp = piff.Polynomial(orders=orders)
    pos = [(np_rng.random_sample() * 10, np_rng.random_sample() * 10)
           for i in range(nstars)]
    #use the wrong number of parameters here so that we raise an error
    vectors = [np_rng.random_sample(size=nparam + 1) for i in range(nstars)]
    data = [piff.Star.makeTarget(u=p[0], v=p[1]).data for p in pos]
    fit = [piff.StarFit(v) for v in vectors]
    stars = [piff.Star(d, f) for d, f in zip(data, fit)]
    try:
        np.testing.assert_raises(ValueError, interp.solve, stars)
    except ImportError:
        pass
Example #7
0
def test_poly_guess():
    # test that our initial guess gives us a flat function given
    # by the mean
    np_rng = np.random.RandomState(1234)
    N = 2
    X = 10.0
    Y = 10.0
    nstars = 50
    nparam = 10
    interp = piff.Polynomial(N)
    pos = [(np_rng.random_sample() * X, np_rng.random_sample() * Y)
           for i in range(nstars)]

    interp._setup_indices(nparam)
    for i in range(nparam):
        param = np_rng.random_sample(size=nstars)
        p0 = interp._initialGuess(pos, param, i)
        mu = param.mean()
        assert np.isclose(p0[0, 0], mu)

        np.testing.assert_array_equal(p0[0, 1:], 0.0)
        np.testing.assert_array_equal(p0[1, 0], 0.0)
        np.testing.assert_array_equal(p0[1:, 1:], 0.0)
        np.testing.assert_almost_equal(interp._interpolationModel(pos, p0), mu)
Example #8
0
def test_poly_raise():
    # Test that we can serialize and deserialize a polynomial
    # interpolator correctly.  Copying all this stuff from above:

    np_rng = np.random.RandomState(1234)
    nparam = 3
    nstars = 50

    # Use three different sizes to test everything
    orders = [1, 2, 3]
    interp = piff.Polynomial(orders=orders)
    pos = [(np_rng.random_sample() * 10, np_rng.random_sample() * 10)
           for i in range(nstars)]
    #use the wrong number of parameters here so that we raise an error
    vectors = [np_rng.random_sample(size=nparam + 1) for i in range(nstars)]
    data = [piff.Star.makeTarget(u=p[0], v=p[1]).data for p in pos]
    fit = [piff.StarFit(v) for v in vectors]
    stars = [piff.Star(d, f) for d, f in zip(data, fit)]
    np.testing.assert_raises(ValueError, interp.solve, stars)

    # Invalid construction
    np.testing.assert_raises(TypeError, piff.Polynomial)
    np.testing.assert_raises(TypeError,
                             piff.Polynomial,
                             order=3,
                             orders=[1, 2, 3])
    np.testing.assert_raises(ValueError,
                             piff.Polynomial,
                             order=3,
                             poly_type='invalid')

    # Cannot write before running fit.
    filename = 'output/test_invalid.fits'
    with fitsio.FITS(filename, 'rw', clobber=True) as f:
        with np.testing.assert_raises(RuntimeError):
            interp.write(f, extname='junk')
Example #9
0
def test_missing():
    """Next: fit mean PSF to multiple images, with missing pixels.
    """
    if __name__ == '__main__':
        fiducial_list = [
            fiducial_gaussian, fiducial_kolmogorov, fiducial_moffat
        ]
    else:
        fiducial_list = [fiducial_moffat]
    for fiducial in fiducial_list:
        print()
        print("fiducial = ", fiducial)
        print()
        mod = piff.GSObjectModel(fiducial, include_pixel=False)
        g1 = g2 = u0 = v0 = 0.0

        # Draw stars on a 2d grid of "focal plane" with 0<=u,v<=1
        positions = np.linspace(0., 1., 4)
        influx = 150.
        stars = []
        np_rng = np.random.RandomState(1234)
        rng = galsim.BaseDeviate(1234)
        for u in positions:
            for v in positions:
                # Draw stars in focal plane positions around a unit ring
                s = make_data(fiducial,
                              1.0,
                              g1,
                              g2,
                              u0,
                              v0,
                              influx,
                              noise=0.1,
                              pix_scale=0.5,
                              fpu=u,
                              fpv=v,
                              rng=rng,
                              include_pixel=False)
                s = mod.initialize(s)
                # Kill 10% of each star's pixels
                bad = np_rng.rand(*s.image.array.shape) < 0.1
                s.weight.array[bad] = 0.
                s.image.array[bad] = -999.
                s = mod.reflux(s,
                               fit_center=False)  # Start with a sensible flux
                stars.append(s)

        # Also store away a noiseless copy of the PSF, origin of focal plane
        s0 = make_data(fiducial,
                       1.0,
                       g1,
                       g2,
                       u0,
                       v0,
                       influx,
                       pix_scale=0.5,
                       include_pixel=False)
        s0 = mod.initialize(s0)

        interp = piff.Polynomial(order=0)
        interp.initialize(stars)

        oldchisq = 0.
        # Iterate solution using interpolator
        for iteration in range(40):
            # Refit PSFs star by star:
            for i, s in enumerate(stars):
                stars[i] = mod.fit(s)
            # Run the interpolator
            interp.solve(stars)
            # Install interpolator solution into each
            # star, recalculate flux, report chisq
            chisq = 0.
            dof = 0
            for i, s in enumerate(stars):
                s = interp.interpolate(s)
                s = mod.reflux(s)
                chisq += s.fit.chisq
                dof += s.fit.dof
                stars[i] = s
                ###print('   chisq=',s.fit.chisq, 'dof=',s.fit.dof)
            print('iteration', iteration, 'chisq=', chisq, 'dof=', dof)
            if oldchisq > 0 and chisq < oldchisq and oldchisq - chisq < dof / 10.:
                break
            else:
                oldchisq = chisq

        # Now use the interpolator to produce a noiseless rendering
        s1 = interp.interpolate(s0)
        s1 = mod.reflux(s1)
        print('Flux, ctr after interpolation: ', s1.fit.flux, s1.fit.center,
              s1.fit.chisq)
        # Less than 2 dp of accuracy here!
        np.testing.assert_almost_equal(s1.fit.flux / influx, 1.0, decimal=3)

        s1 = mod.draw(s1)
        print('max image abs diff = ',
              np.max(np.abs(s1.image.array - s0.image.array)))
        print('max image abs value = ', np.max(np.abs(s0.image.array)))
        peak = np.max(np.abs(s0.image.array))
        np.testing.assert_almost_equal(s1.image.array / peak,
                                       s0.image.array / peak,
                                       decimal=3)
Example #10
0
def test_gradient_center():
    """Next: fit spatially-varying PSF, with spatially-varying centers to multiple images.
    """
    if __name__ == '__main__':
        fiducial_list = [
            fiducial_gaussian, fiducial_kolmogorov, fiducial_moffat
        ]
    else:
        fiducial_list = [fiducial_moffat]
    for fiducial in fiducial_list:
        print()
        print("fiducial = ", fiducial)
        print()
        mod = piff.GSObjectModel(fiducial, include_pixel=False)

        # Interpolator will be linear
        interp = piff.Polynomial(order=1)

        # Draw stars on a 2d grid of "focal plane" with 0<=u,v<=1
        positions = np.linspace(0., 1., 4)
        influx = 150.
        stars = []
        rng = galsim.BaseDeviate(1234)
        for u in positions:
            # Put gradient in pixel size
            for v in positions:
                # Draw stars in focal plane positions around a unit ring
                # spatially-varying fwhm, g1, g2.
                s = make_data(fiducial,
                              1.0 + u * 0.1 + 0.1 * v,
                              0.1 * u,
                              0.1 * v,
                              0.5 * u,
                              0.5 * v,
                              influx,
                              noise=0.1,
                              pix_scale=0.5,
                              fpu=u,
                              fpv=v,
                              rng=rng,
                              include_pixel=False)
                s = mod.initialize(s)
                stars.append(s)

        # import matplotlib.pyplot as plt
        # fig, axes = plt.subplots(4, 4)
        # for star, ax in zip(stars, axes.ravel()):
        #     ax.imshow(star.data.image.array)
        # plt.show()

        # Also store away a noiseless copy of the PSF, origin of focal plane
        s0 = make_data(fiducial,
                       1.0,
                       0.,
                       0.,
                       0.,
                       0.,
                       influx,
                       pix_scale=0.5,
                       include_pixel=False)
        s0 = mod.initialize(s0)

        # Polynomial doesn't need this, but it should work nonetheless.
        interp.initialize(stars)

        oldchisq = 0.
        # Iterate solution using interpolator
        for iteration in range(40):
            # Refit PSFs star by star:
            for i, s in enumerate(stars):
                stars[i] = mod.fit(s)
            # Run the interpolator
            interp.solve(stars)
            # Install interpolator solution into each
            # star, recalculate flux, report chisq
            chisq = 0.
            dof = 0
            for i, s in enumerate(stars):
                s = interp.interpolate(s)
                s = mod.reflux(s)
                chisq += s.fit.chisq
                dof += s.fit.dof
                stars[i] = s
                ###print('   chisq=',s.fit.chisq, 'dof=',s.fit.dof)
            print('iteration', iteration, 'chisq=', chisq, 'dof=', dof)
            if oldchisq > 0 and np.abs(oldchisq - chisq) < dof / 10.:
                break
            else:
                oldchisq = chisq

        for i, s in enumerate(stars):
            print(i, s.fit.center, s.fit.params[0:2])

        # Now use the interpolator to produce a noiseless rendering
        s1 = interp.interpolate(s0)
        s1 = mod.reflux(s1)
        print('Flux, ctr, chisq after interpolation: ', s1.fit.flux,
              s1.fit.center, s1.fit.chisq)
        # Less than 2 dp of accuracy here!
        np.testing.assert_almost_equal(s1.fit.flux / influx, 1.0, decimal=2)

        s1 = mod.draw(s1)
        print('max image abs diff = ',
              np.max(np.abs(s1.image.array - s0.image.array)))
        print('max image abs value = ', np.max(np.abs(s0.image.array)))
        peak = np.max(np.abs(s0.image.array))
        np.testing.assert_almost_equal(s1.image.array / peak,
                                       s0.image.array / peak,
                                       decimal=2)
Example #11
0
def test_twodstats():
    """Make sure we can execute and print a readout of the plot
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(2)
    else:
        logger = None

    model = piff.Gaussian(fastfit=True)
    interp = piff.Polynomial(order=1)  # should find that order=1 is better
    # create background model
    stars, true_model = generate_starlist(100)
    psf = piff.SimplePSF(model, interp)
    psf.fit(stars, None, None)
    stars = psf.stars  # These have the right fit parameters

    # check the coeffs of sigma and g2, which are actually linear fits
    # skip g1 since it is actually a 2d parabola
    # factor of 0.263 is to account for going from pixel xy to wcs uv
    np.testing.assert_almost_equal(psf.interp.coeffs[0].flatten(),
                                   np.array([0.4, 0, 1. / (0.263 * 2048), 0]),
                                   decimal=4)
    np.testing.assert_almost_equal(
        psf.interp.coeffs[2].flatten(),
        np.array([-0.1 * 1000 / 2048, 0, 0.1 / (0.263 * 2048), 0]),
        decimal=4)

    stats = piff.TwoDHistStats(nbins_u=5, nbins_v=5)  # implicitly np.median
    stats.compute(psf, stars, logger=logger)
    # check the twodhists
    # get the average value in the bin
    u_i = 3
    v_i = 3
    icen = stats.twodhists['u'][v_i, u_i] / 0.263
    jcen = stats.twodhists['v'][v_i, u_i] / 0.263
    print('icen = ', icen)
    print('jcen = ', jcen)
    icenter = 1000
    jcenter = 2000
    # the average value in the bin should match up with the model for the average coordinates
    sigma, g1, g2 = psf_model(icen, jcen, icenter, jcenter)
    sigma_average = stats.twodhists['T'][v_i, u_i]
    g1_average = stats.twodhists['g1'][v_i, u_i]
    g2_average = stats.twodhists['g2'][v_i, u_i]
    # assert equal to 4th decimal
    print('sigma, g1, g2 = ', [sigma, g1, g2])
    print('av sigma, g1, g2 = ', [sigma_average, g1_average, g2_average])
    np.testing.assert_almost_equal([sigma, g1, g2],
                                   [sigma_average, g1_average, g2_average],
                                   decimal=2)

    # Test the plotting and writing
    twodstats_file = os.path.join('output', 'twodstats.pdf')
    stats.write(twodstats_file)

    with np.testing.assert_raises(ValueError):
        stats.write()  # If not given in constructor, must give file name here.

    # repeat for whisker
    stats = piff.WhiskerStats(nbins_u=21,
                              nbins_v=21,
                              reducing_function='np.mean')
    stats.compute(psf, stars)
    # Test the plotting and writing
    whisker_file = os.path.join('output', 'whiskerstats.pdf')
    stats.write(whisker_file)
    with np.testing.assert_raises(ValueError):
        stats.write()

    # With large number of bins, many will have no objects.  This is ok.
    # Also, can use other np functions like max, std, instead to get different stats
    # Not sure when these would be useful, but they are allowed.
    # And, check usage where file_name is given in init.
    twodstats_file2 = os.path.join('output', 'twodstats.pdf')
    stats2 = piff.TwoDHistStats(nbins_u=50,
                                nbins_v=50,
                                reducing_function='np.std',
                                file_name=twodstats_file2)
    with np.testing.assert_raises(RuntimeError):
        stats2.write()  # Cannot write before compute
    stats2.compute(psf, stars, logger=logger)
    stats2.write()

    whisker_file2 = os.path.join('output', 'whiskerstats.pdf')
    stats2 = piff.WhiskerStats(nbins_u=100,
                               nbins_v=100,
                               reducing_function='np.max',
                               file_name=whisker_file2)
    with np.testing.assert_raises(RuntimeError):
        stats2.write()  # Cannot write before compute
    stats2.compute(psf, stars)
    stats2.write()
Example #12
0
def test_interp():
    """First test of use with interpolator.  Make a bunch of noisy
    versions of the same PSF, interpolate them with constant interp
    to get an average PSF
    """
    influx = 150.
    if __name__ == '__main__':
        fiducial_list = [
            fiducial_gaussian, fiducial_kolmogorov, fiducial_moffat
        ]
        niter = 3
        npos = 10
    else:
        fiducial_list = [fiducial_moffat]
        niter = 1  # Not actually any need for interating in this case.
        npos = 4
    for fiducial in fiducial_list:
        print()
        print("fiducial = ", fiducial)
        print()
        mod = piff.GSObjectModel(fiducial, include_pixel=False)
        g1 = g2 = u0 = v0 = 0.0

        # Interpolator will be simple mean
        interp = piff.Polynomial(order=0)

        # Draw stars on a 2d grid of "focal plane" with 0<=u,v<=1
        positions = np.linspace(0., 1., npos)
        stars = []
        rng = galsim.BaseDeviate(1234)
        for u in positions:
            for v in positions:
                s = make_data(fiducial,
                              1.0,
                              g1,
                              g2,
                              u0,
                              v0,
                              influx,
                              noise=0.1,
                              pix_scale=0.5,
                              fpu=u,
                              fpv=v,
                              rng=rng,
                              include_pixel=False)
                s = mod.initialize(s)
                stars.append(s)

        # Also store away a noiseless copy of the PSF, origin of focal plane
        s0 = make_data(fiducial,
                       1.0,
                       g1,
                       g2,
                       u0,
                       v0,
                       influx,
                       pix_scale=0.5,
                       include_pixel=False)
        s0 = mod.initialize(s0)

        # Polynomial doesn't need this, but it should work nonetheless.
        interp.initialize(stars)

        # Iterate solution using interpolator
        for iteration in range(niter):
            # Refit PSFs star by star:
            for i, s in enumerate(stars):
                stars[i] = mod.fit(s)
            # Run the interpolator
            interp.solve(stars)
            # Install interpolator solution into each
            # star, recalculate flux, report chisq
            chisq = 0.
            dof = 0
            for i, s in enumerate(stars):
                s = interp.interpolate(s)
                s = mod.reflux(s)
                chisq += s.fit.chisq
                dof += s.fit.dof
                stars[i] = s
            print('iteration', iteration, 'chisq=', chisq, 'dof=', dof)

        # Now use the interpolator to produce a noiseless rendering
        s1 = interp.interpolate(s0)
        s1 = mod.reflux(s1)
        print('Flux, ctr, chisq after interpolation: ', s1.fit.flux,
              s1.fit.center, s1.fit.chisq)
        np.testing.assert_almost_equal(s1.fit.flux / influx, 1.0, decimal=3)

        s1 = mod.draw(s1)
        print('max image abs diff = ',
              np.max(np.abs(s1.image.array - s0.image.array)))
        print('max image abs value = ', np.max(np.abs(s0.image.array)))
        peak = np.max(np.abs(s0.image.array))
        np.testing.assert_almost_equal(s1.image.array / peak,
                                       s0.image.array / peak,
                                       decimal=3)
Example #13
0
def test_missing():
    """Next: fit mean PSF to multiple images, with missing pixels.
    """
    # Pixelized model with Lanczos 3 interpolation, slightly smaller than data
    # than the data
    pixinterp = piff.Lanczos(3)
    mod = piff.PixelGrid(0.5,
                         25,
                         pixinterp,
                         start_sigma=1.5,
                         force_model_center=False)

    # Draw stars on a 2d grid of "focal plane" with 0<=u,v<=1
    positions = np.linspace(0., 1., 4)
    influx = 150.
    stars = []
    np_rng = np.random.RandomState(1234)
    rng = galsim.BaseDeviate(1234)
    for u in positions:
        for v in positions:
            # Draw stars in focal plane positions around a unit ring
            s = make_gaussian_data(1.0,
                                   0.,
                                   0.,
                                   influx,
                                   noise=0.1,
                                   du=0.5,
                                   fpu=u,
                                   fpv=v,
                                   rng=rng)
            s = mod.initialize(s)
            # Kill 10% of each star's pixels
            bad = np_rng.rand(*s.image.array.shape) < 0.1
            s.weight.array[bad] = 0.
            s.image.array[bad] = -999.
            s = mod.reflux(s, fit_center=False)  # Start with a sensible flux
            stars.append(s)

    # Also store away a noiseless copy of the PSF, origin of focal plane
    s0 = make_gaussian_data(1.0, 0., 0., influx, du=0.5)
    s0 = mod.initialize(s0)

    if __name__ == "__main__":
        interps = [piff.Polynomial(order=0), piff.BasisPolynomial(order=0)]
    else:
        # The Polynomial interpolator works, but it's slow.  For the nosetests runs, skip it.
        interps = [piff.BasisPolynomial(order=0)]

    for interp in interps:
        # Interpolator will be simple mean
        interp = piff.Polynomial(order=0)
        interp.initialize(stars)

        oldchisq = 0.
        # Iterate solution using interpolator
        for iteration in range(40):
            # Refit PSFs star by star:
            for i, s in enumerate(stars):
                stars[i] = mod.fit(s)
            # Run the interpolator
            interp.solve(stars)
            # Install interpolator solution into each
            # star, recalculate flux, report chisq
            chisq = 0.
            dof = 0
            for i, s in enumerate(stars):
                s = interp.interpolate(s)
                s = mod.reflux(s)
                chisq += s.fit.chisq
                dof += s.fit.dof
                stars[i] = s
                ###print('   chisq=',s.fit.chisq, 'dof=',s.fit.dof)
            print('iteration', iteration, 'chisq=', chisq, 'dof=', dof)
            if oldchisq > 0 and chisq < oldchisq and oldchisq - chisq < dof / 10.:
                break
            else:
                oldchisq = chisq

        # Now use the interpolator to produce a noiseless rendering
        s1 = interp.interpolate(s0)
        s1 = mod.reflux(s1)
        print('Flux, ctr after interpolation: ', s1.fit.flux, s1.fit.center,
              s1.fit.chisq)
        # Less than 2 dp of accuracy here!
        np.testing.assert_almost_equal(s1.fit.flux / influx, 1.0, decimal=1)

        s1 = mod.draw(s1)
        print('max image abs diff = ',
              np.max(np.abs(s1.image.array - s0.image.array)))
        print('max image abs value = ', np.max(np.abs(s0.image.array)))
        peak = np.max(np.abs(s0.image.array))
        np.testing.assert_almost_equal(s1.image.array / peak,
                                       s0.image.array / peak,
                                       decimal=1)
Example #14
0
def test_gradient():
    """Next: fit spatially-varying PSF to multiple images.
    """
    # Pixelized model with Lanczos 3 interpolation, slightly smaller than data
    # than the data
    pixinterp = piff.Lanczos(3)
    mod = piff.PixelGrid(0.5,
                         25,
                         pixinterp,
                         start_sigma=1.5,
                         degenerate=False,
                         force_model_center=False)

    # Interpolator will be linear
    interp = piff.Polynomial(order=1)

    # Draw stars on a 2d grid of "focal plane" with 0<=u,v<=1
    positions = np.linspace(0., 1., 4)
    influx = 150.
    stars = []
    rng = galsim.BaseDeviate(1234)
    for u in positions:
        # Put gradient in pixel size
        for v in positions:
            # Draw stars in focal plane positions around a unit ring
            s = make_gaussian_data(1.0 + u * 0.1,
                                   0.,
                                   0.,
                                   influx,
                                   noise=0.1,
                                   du=0.5,
                                   fpu=u,
                                   fpv=v,
                                   rng=rng)
            s = mod.initialize(s)
            stars.append(s)

    # Also store away a noiseless copy of the PSF, origin of focal plane
    s0 = make_gaussian_data(1.0, 0., 0., influx, du=0.5)
    s0 = mod.initialize(s0)

    # Polynomial doesn't need this, but it should work nonetheless.
    interp.initialize(stars)

    oldchisq = 0.
    # Iterate solution using interpolator
    for iteration in range(40):
        # Refit PSFs star by star:
        for i, s in enumerate(stars):
            stars[i] = mod.fit(s)
        # Run the interpolator
        interp.solve(stars)
        # Install interpolator solution into each
        # star, recalculate flux, report chisq
        chisq = 0.
        dof = 0
        for i, s in enumerate(stars):
            s = interp.interpolate(s)
            s = mod.reflux(s)
            chisq += s.fit.chisq
            dof += s.fit.dof
            stars[i] = s
            ###print('   chisq=',s.fit.chisq, 'dof=',s.fit.dof)
        print('iteration', iteration, 'chisq=', chisq, 'dof=', dof)
        if oldchisq > 0 and np.abs(oldchisq - chisq) < dof / 10.:
            break
        else:
            oldchisq = chisq

    # Now use the interpolator to produce a noiseless rendering
    s1 = interp.interpolate(s0)
    s1 = mod.reflux(s1)
    print('Flux, ctr after interpolation: ', s1.fit.flux, s1.fit.center,
          s1.fit.chisq)
    # Less than 2 dp of accuracy here!
    np.testing.assert_almost_equal(s1.fit.flux / influx, 1.0, decimal=1)

    s1 = mod.draw(s1)
    print('max image abs diff = ',
          np.max(np.abs(s1.image.array - s0.image.array)))
    print('max image abs value = ', np.max(np.abs(s0.image.array)))
    peak = np.max(np.abs(s0.image.array))
    np.testing.assert_almost_equal(s1.image.array / peak,
                                   s0.image.array / peak,
                                   decimal=1)
Example #15
0
def poly_load_save_sub(type1, type2, fname):
    # Test that we can serialize and deserialize a polynomial
    # interpolator correctly.  Copying all this stuff from above:

    np_rng = np.random.RandomState(1234)
    nparam = 3
    nstars = 50
    # Use three different sizes to test everything
    orders = [1, 2, 3]
    interp = piff.Polynomial(orders=orders, poly_type=type1)
    X = 10.0  # size of the field
    Y = 10.0

    pos = [(np_rng.random_sample() * X, np_rng.random_sample() * Y)
           for i in range(nstars)]

    # Let's make a function that is linear just as a function of one parameter
    # These are the linear fit parameters for each parameter in turn
    m1 = np_rng.uniform(size=nparam)
    m2 = np_rng.uniform(size=nparam)
    q1 = np_rng.uniform(size=nparam)
    c = np_rng.uniform(size=nparam)

    def quadratic_func(pos):
        u = pos[0]
        v = pos[1]
        r = q1 * u * v + m1 * u + m2 * v + c
        return r

    # Simulate the vectors under this model
    vectors = [quadratic_func(p) for p in pos]

    # Fit them!
    data = [piff.Star.makeTarget(u=p[0], v=p[1]).data for p in pos]
    fit = [piff.StarFit(v) for v in vectors]
    stars = [piff.Star(d, f) for d, f in zip(data, fit)]
    interp.solve(stars)

    import tempfile
    import os
    import fitsio
    extname = "interp"
    dirname = 'output'
    filename = os.path.join(dirname, fname)
    with fitsio.FITS(filename, 'rw', clobber=True) as f:
        interp.write(f, extname=extname)
    with fitsio.FITS(filename, "r") as f2:
        interp2 = piff.Polynomial.read(f2, extname=extname)

    # The type and other parameters should now have been overwritten and updated
    assert interp2.poly_type == interp.poly_type
    assert interp2.order == interp.order
    np.testing.assert_array_equal(interp2.orders, interp.orders)
    assert interp2.nvariables == interp.nvariables
    np.testing.assert_array_equal(interp2.indices, interp.indices)

    # Check that the old and new interpolators generate the same
    # value
    for i in range(30):
        p = (np_rng.random_sample() * X, np_rng.random_sample() * Y)
        target = piff.Star.makeTarget(u=p[0], v=p[1])
        target1 = interp.interpolate(target)
        target2 = interp.interpolate(target)
        np.testing.assert_almost_equal(target1.fit.params, target2.fit.params)
Example #16
0
def test_interp():
    """First test of use with interpolator.  Make a bunch of noisy
    versions of the same PSF, interpolate them with constant interp
    to get an average PSF
    """
    # Pixelized model with Lanczos 3 interpolation, slightly smaller than data
    # than the data
    pixinterp = piff.Lanczos(3)
    mod = piff.PixelGrid(0.5, 25, pixinterp, start_sigma=1.5, degenerate=False)

    # Interpolator will be simple mean
    interp = piff.Polynomial(order=0)

    # Draw stars on a 2d grid of "focal plane" with 0<=u,v<=1
    positions = np.linspace(0., 1., 10.)
    influx = 150.
    stars = []
    rng = galsim.BaseDeviate(1234)
    for u in positions:
        for v in positions:
            # Draw stars in focal plane positions around a unit ring
            s = make_gaussian_data(1.0,
                                   0.,
                                   0.,
                                   influx,
                                   noise=0.1,
                                   du=0.5,
                                   fpu=u,
                                   fpv=v,
                                   rng=rng)
            s = mod.initialize(s)
            stars.append(s)

    # Also store away a noiseless copy of the PSF, origin of focal plane
    s0 = make_gaussian_data(1.0, 0., 0., influx, du=0.5)
    s0 = mod.initialize(s0)

    # Polynomial doesn't need this, but it should work nonetheless.
    interp.initialize(stars)

    # Iterate solution using interpolator
    for iteration in range(3):
        # Refit PSFs star by star:
        for i, s in enumerate(stars):
            stars[i] = mod.fit(s)
        # Run the interpolator
        interp.solve(stars)
        # Install interpolator solution into each
        # star, recalculate flux, report chisq
        chisq = 0.
        dof = 0
        for i, s in enumerate(stars):
            s = interp.interpolate(s)
            s = mod.reflux(s)
            chisq += s.fit.chisq
            dof += s.fit.dof
            stars[i] = s
        print('iteration', iteration, 'chisq=', chisq, 'dof=', dof)

    # Now use the interpolator to produce a noiseless rendering
    s1 = interp.interpolate(s0)
    s1 = mod.reflux(s1)
    print('Flux, ctr after interpolation: ', s1.fit.flux, s1.fit.center,
          s1.fit.chisq)
    np.testing.assert_almost_equal(s1.fit.flux / influx, 1.0, decimal=2)

    s1 = mod.draw(s1)
    print('max image abs diff = ',
          np.max(np.abs(s1.image.array - s0.image.array)))
    print('max image abs value = ', np.max(np.abs(s0.image.array)))
    peak = np.max(np.abs(s0.image.array))
    np.testing.assert_almost_equal(s1.image.array / peak,
                                   s0.image.array / peak,
                                   decimal=2)
Example #17
0
def test_undersamp():
    """Next: fit PSF to undersampled, dithered data with fixed centroids
    ***Doesn't work well! Need to work on the SV pruning***
    """
    # Pixelized model with Lanczos 3 interpolation, slightly smaller than data
    # than the data
    pixinterp = piff.Lanczos(3)
    du = 0.5
    mod = piff.PixelGrid(0.25, 25, pixinterp, start_sigma=1.01)
    ##,force_model_center=True)

    # Interpolator will be constant
    interp = piff.Polynomial(order=0)

    # Draw stars on a 2d grid of "focal plane" with 0<=u,v<=1
    positions = np.linspace(0., 1., 4)
    influx = 150.
    stars = []
    np_rng = np.random.RandomState(1234)
    rng = galsim.BaseDeviate(1234)
    for u in positions:
        for v in positions:
            # Dither centers by 1 pixel
            phase = (0.5 - np_rng.rand(2)) * du
            if u == 0. and v == 0.:
                phase = (0., 0.)
            s = make_gaussian_data(1.0,
                                   0.,
                                   0.,
                                   influx,
                                   noise=0.1,
                                   du=du,
                                   fpu=u,
                                   fpv=v,
                                   nom_u0=phase[0],
                                   nom_v0=phase[1],
                                   rng=rng)
            s = mod.initialize(s)
            print("phase:", phase, 'flux', s.fit.flux)
            stars.append(s)

    # Also store away a noiseless copy of the PSF, origin of focal plane
    s0 = make_gaussian_data(1.0, 0., 0., influx, du=0.5)
    s0 = mod.initialize(s0)

    # Polynomial doesn't need this, but it should work nonetheless.
    interp.initialize(stars)

    oldchisq = 0.
    # Iterate solution using interpolator
    for iteration in range(1):  ###
        # Refit PSFs star by star:
        stars = [mod.fit(s) for s in stars]
        # Run the interpolator
        interp.solve(stars)
        # Install interpolator solution into each
        # star, recalculate flux, report chisq
        chisq = 0.
        dof = 0
        for i, s in enumerate(stars):
            s = interp.interpolate(s)
            s = mod.reflux(s)
            chisq += s.fit.chisq
            dof += s.fit.dof
            stars[i] = s
            print('   chisq=', s.fit.chisq, 'dof=', s.fit.dof, 'flux=',
                  s.fit.flux)
        print('iteration', iteration, 'chisq=', chisq, 'dof=', dof)
        if oldchisq > 0 and np.abs(oldchisq - chisq) < dof / 10.:
            break
        else:
            oldchisq = chisq

    # Now use the interpolator to produce a noiseless rendering
    s1 = interp.interpolate(s0)
    s1 = mod.reflux(s1)
    print('Flux, ctr after interpolation: ', s1.fit.flux, s1.fit.center,
          s1.fit.chisq)
    # Less than 2 dp of accuracy here!
    np.testing.assert_almost_equal(s1.fit.flux / influx, 1.0, decimal=1)

    s1 = mod.draw(s1)
    print('max image abs diff = ',
          np.max(np.abs(s1.image.array - s0.image.array)))
    print('max image abs value = ', np.max(np.abs(s0.image.array)))
    peak = np.max(np.abs(s0.image.array))
    np.testing.assert_almost_equal(s1.image.array / peak,
                                   s0.image.array / peak,
                                   decimal=1)