Exemple #1
0
def test_twodstats_config():
    """Test running stats through a config file.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(
            log_file='output/test_twodstats_config.log')

    image_file = os.path.join('output', 'test_stats_image.fits')
    cat_file = os.path.join('output', 'test_stats_cat.fits')
    psf_file = os.path.join('output', 'test_twodstats.fits')
    twodhist_file = os.path.join('output', 'test_twodhiststats.pdf')
    twodhist_std_file = os.path.join('output', 'test_twodhiststats_std.pdf')
    config = {
        'input': {
            'image_file_name': image_file,
            'cat_file_name': cat_file,
            'stamp_size': 48
        },
        'psf': {
            'model': {
                'type': 'Gaussian',
                'fastfit': True,
                'include_pixel': False
            },
            'interp': {
                'type': 'Mean'
            },
        },
        'output': {
            'file_name':
            psf_file,
            'stats': [
                {
                    'type': 'TwoDHist',
                    'file_name': twodhist_file,
                    'nbins_u': 3,
                    'nbins_v': 3,
                },
                {
                    'type': 'TwoDHist',
                    'file_name': twodhist_std_file,
                    'reducing_function': 'np.std',
                    'nbins_u': 3,
                    'nbins_v': 3,
                },
            ]
        }
    }
    piff.piffify(config, logger)
    assert os.path.isfile(twodhist_file)
    assert os.path.isfile(twodhist_std_file)

    # repeat with plotify function
    os.remove(twodhist_file)
    os.remove(twodhist_std_file)
    piff.plotify(config, logger)
    assert os.path.isfile(twodhist_file)
    assert os.path.isfile(twodhist_std_file)
Exemple #2
0
def test_sizemag_plot():
    """Check a size-magnitude plot.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(2)
    else:
        logger = piff.config.setup_logger(
            log_file='output/test_sizemag_plot.log')

    config = piff.config.read_config('sizemag.yaml')
    file_name = os.path.join('output',
                             config['output']['stats'][0]['file_name'])

    # Some modifications to speed it up a bit.
    config['select'] = {
        'type': 'Properties',
        'where': '(CLASS_STAR > 0.9) & (MAG_AUTO < 13)',
        'hsm_size_reject': 4,
        'min_snr': 50,
    }
    config['psf']['interp'] = {'type': 'Mean'}
    config['psf']['outliers']['nsigma'] = 10
    del config['output']['stats'][1:]

    # Run via piffify
    piff.piffify(config, logger)
    assert os.path.isfile(file_name)

    # repeat with plotify function
    os.remove(file_name)
    piff.plotify(config, logger)
    assert os.path.isfile(file_name)
Exemple #3
0
def test_shapestats_config():
    """Test running stats through a config file.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(log_file='output/test_shapestats_config.log')

    image_file = os.path.join('output','test_stats_image.fits')
    cat_file = os.path.join('output','test_stats_cat.fits')
    psf_file = os.path.join('output','test_shapestats.fits')
    shape_file = os.path.join('output','test_shapestats.pdf')
    config = {
        'input' : {
            'image_file_name' : image_file,
            'cat_file_name' : cat_file,
            'stamp_size' : 48
        },
        'psf' : {
            'model' : { 'type' : 'Gaussian',
                        'fastfit': True,
                        'include_pixel': False },
            'interp' : { 'type' : 'Mean' },
        },
        'output' : {
            'file_name' : psf_file,
            'stats' : [
                {
                    'type': 'ShapeHistograms',
                    'file_name': shape_file
                },
            ]
        },
    }
    piff.piffify(config, logger)
    assert os.path.isfile(shape_file)

    # repeat with plotify function
    os.remove(shape_file)
    piff.plotify(config, logger)
    assert os.path.isfile(shape_file)

    # Test ShapeHistogramStats directly
    psf = piff.read(psf_file)
    shapeStats = piff.ShapeHistogramsStats()
    orig_stars, wcs, pointing = piff.Input.process(config['input'], logger)
    shapeStats.compute(psf, orig_stars)

    # test their characteristics
    sigma = 1.3  # (copied from setup())
    g1 = 0.23
    g2 = -0.17
    np.testing.assert_array_almost_equal(sigma, shapeStats.T, decimal=4)
    np.testing.assert_array_almost_equal(sigma, shapeStats.T_model, decimal=3)
    np.testing.assert_array_almost_equal(g1, shapeStats.g1, decimal=4)
    np.testing.assert_array_almost_equal(g1, shapeStats.g1_model, decimal=3)
    np.testing.assert_array_almost_equal(g2, shapeStats.g2, decimal=4)
    np.testing.assert_array_almost_equal(g2, shapeStats.g2_model, decimal=3)
Exemple #4
0
def test_invalid_config():
    # Test a few invalid uses of the config parsing.
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(log_file='output/test_invalid_config.log')
    image_file = os.path.join('output','simple_image.fits')
    cat_file = os.path.join('output','simple_cat.fits')
    psf_file = os.path.join('output','simple_psf.fits')
    config = {
        'input' : {
            'image_file_name' : image_file,
            'cat_file_name' : cat_file,
            'flag_col' : 'flag',
            'use_flag' : 1,
            'skip_flag' : 4,
        },
        'psf' : {
            'model' : { 'type' : 'Gaussian',
                        'fastfit': True,
                        'include_pixel': False},
            'interp' : { 'type' : 'Mean' },
            'max_iter' : 10,
            'chisq_thresh' : 0.2,
        },
        'output' : { 'file_name' : psf_file },
    }
    # Invalid variable specification
    with np.testing.assert_raises(ValueError):
        piff.parse_variables(config, ['verbose:0'], logger=logger)
    # process needs both input and psf
    with np.testing.assert_raises(ValueError):
        piff.process(config={'input':config['input']}, logger=logger)
    with np.testing.assert_raises(ValueError):
        piff.process(config={'psf':config['psf']}, logger=logger)
    # piffify also needs output
    with np.testing.assert_raises(ValueError):
        piff.piffify(config={'input':config['input']}, logger=logger)
    with np.testing.assert_raises(ValueError):
        piff.piffify(config={'psf':config['psf']}, logger=logger)
    with np.testing.assert_raises(ValueError):
        piff.piffify(config={'input':config['input'], 'psf':config['psf']}, logger=logger)
    # plotify doesn't need psf, but needs a 'file_name' in output
    with np.testing.assert_raises(ValueError):
        piff.plotify(config={'input':config['input']}, logger=logger)
    with np.testing.assert_raises(ValueError):
        piff.plotify(config={'input':config['input'], 'output':{}}, logger=logger)

    # Error if missing either model or interp
    config2 = copy.deepcopy(config)
    del config2['psf']['model']
    with np.testing.assert_raises(ValueError):
        piff.piffify(config2, logger)
    config2['psf']['model'] = config['psf']['model']
    del config2['psf']['interp']
    with np.testing.assert_raises(ValueError):
        piff.piffify(config2, logger)
Exemple #5
0
def test_twodstats_config():
    """Test running stats through a config file.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(log_file='output/test_twodstats_config.log')

    image_file = os.path.join('output','test_stats_image.fits')
    cat_file = os.path.join('output','test_stats_cat.fits')
    psf_file = os.path.join('output','test_twodstats.fits')
    twodhist_file = os.path.join('output','test_twodhiststats.pdf')
    twodhist_std_file = os.path.join('output','test_twodhiststats_std.pdf')
    config = {
        'input' : {
            'image_file_name' : image_file,
            'cat_file_name' : cat_file,
            'stamp_size' : 48
        },
        'psf' : {
            'model' : { 'type' : 'Gaussian',
                        'fastfit': True,
                        'include_pixel': False },
            'interp' : { 'type' : 'Mean' },
        },
        'output' : {
            'file_name' : psf_file,
            'stats' : [
                {
                    'type': 'TwoDHist',
                    'file_name': twodhist_file,
                    'number_bins_u': 3,
                    'number_bins_v': 3,
                },
                {
                    'type': 'TwoDHist',
                    'file_name': twodhist_std_file,
                    'reducing_function': 'np.std',
                    'number_bins_u': 3,
                    'number_bins_v': 3,
                },
            ]
        }
    }
    piff.piffify(config, logger)
    assert os.path.isfile(twodhist_file)
    assert os.path.isfile(twodhist_std_file)

    # repeat with plotify function
    os.remove(twodhist_file)
    os.remove(twodhist_std_file)
    piff.plotify(config, logger)
    assert os.path.isfile(twodhist_file)
    assert os.path.isfile(twodhist_std_file)
Exemple #6
0
def test_single_image():
    """Test the whole process with a single image.

    Note: This test is based heavily on test_single_image in test_simple.py.
    """
    import os
    import fitsio
    np_rng = np.random.RandomState(1234)

    # Make the image
    image = galsim.Image(2048, 2048, scale=0.2)

    # The (x,y) values will be on a grid 5 x 5 stars with a random sub-pixel offset.
    xvals = np.linspace(50., 1950., 5)
    yvals = np.linspace(50., 1950., 5)
    x_list, y_list = np.meshgrid(xvals, yvals)
    x_list = x_list.flatten()
    y_list = y_list.flatten()
    x_list = x_list + (np_rng.rand(len(x_list)) - 0.5)
    y_list = y_list + (np_rng.rand(len(x_list)) - 0.5)
    print('x_list = ',x_list)
    print('y_list = ',y_list)
    # Range of fluxes from 100 to 15000
    flux_list = 100. * np.exp(5. * np_rng.rand(len(x_list)))
    print('fluxes range from ',np.min(flux_list),np.max(flux_list))

    # Draw a Moffat PSF at each location on the image.
    # Have the truth values vary quadratically across the image.
    beta_fn = lambda x,y: 3.5 - 0.1*(x/1000) + 0.08*(y/1000)**2
    fwhm_fn = lambda x,y: 0.9 + 0.05*(x/1000) - 0.03*(y/1000) + 0.02*(x/1000)*(y/1000)
    e1_fn = lambda x,y: 0.02 - 0.01*(x/1000)
    e2_fn = lambda x,y: -0.03 + 0.02*(x/1000)**2 - 0.01*(y/1000)*2

    for x,y,flux in zip(x_list, y_list, flux_list):
        beta = beta_fn(x,y)
        fwhm = fwhm_fn(x,y)
        e1 = e1_fn(x,y)
        e2 = e2_fn(x,y)
        print(x,y,beta,fwhm,e1,e2)
        moffat = galsim.Moffat(fwhm=fwhm, beta=beta, flux=flux).shear(e1=e1, e2=e2)
        bounds = galsim.BoundsI(int(x-31), int(x+32), int(y-31), int(y+32))
        offset = galsim.PositionD( x-int(x)-0.5 , y-int(y)-0.5 )
        moffat.drawImage(image=image[bounds], offset=offset, method='no_pixel')
    print('drew image')

    # Add sky level and noise
    sky_level = 1000
    noise_sigma = 0.1  # Not much noise to keep this an easy test.
    image += sky_level
    image.addNoise(galsim.GaussianNoise(sigma=noise_sigma))

    # Write out the image to a file
    image_file = os.path.join('output','pixel_moffat_image.fits')
    image.write(image_file)
    print('wrote image')

    # Write out the catalog to a file
    dtype = [ ('x','f8'), ('y','f8') ]
    data = np.empty(len(x_list), dtype=dtype)
    data['x'] = x_list
    data['y'] = y_list
    cat_file = os.path.join('output','pixel_moffat_cat.fits')
    fitsio.write(cat_file, data, clobber=True)
    print('wrote catalog')

    # Use InputFiles to read these back in
    config = { 'image_file_name': image_file,
               'cat_file_name': cat_file,
               'stamp_size': 32,
               'noise' : noise_sigma**2,
               'sky' : sky_level,
             }
    input = piff.InputFiles(config)
    assert input.image_file_name == [image_file]
    assert input.cat_file_name == [cat_file]

    # Check image
    assert len(input.images) == 1
    np.testing.assert_equal(input.images[0].array, image.array)

    # Check catalog
    assert len(input.image_pos) == 1
    assert len(input.image_pos[0]) == len(x_list)
    np.testing.assert_equal([pos.x for pos in input.image_pos[0]], x_list)
    np.testing.assert_equal([pos.y for pos in input.image_pos[0]], y_list)

    # Make stars
    orig_stars = input.makeStars()
    assert len(orig_stars) == len(x_list)
    assert orig_stars[0].image.array.shape == (32,32)

    # Make a test star, not at the location of any of the model stars to use for each of the
    # below tests.
    x0 = 1024  # Some random position, not where a star was originally.
    y0 = 133
    beta = beta_fn(x0,y0)
    fwhm = fwhm_fn(x0,y0)
    e1 = e1_fn(x0,y0)
    e2 = e2_fn(x0,y0)
    moffat = galsim.Moffat(fwhm=fwhm, beta=beta).shear(e1=e1, e2=e2)
    target_star = piff.Star.makeTarget(x=x0, y=y0, scale=image.scale)
    test_im = galsim.ImageD(bounds=target_star.image.bounds, scale=image.scale)
    moffat.drawImage(image=test_im, method='no_pixel', use_true_center=False)
    print('made test star')

    if __name__ == '__main__':
        logger = piff.config.setup_logger(2)
        order = 2
    else:
        logger = None
        order = 1

    # These tests are slow, and it's really just doing the same thing three times, so
    # only do the first one when running via nosetests.
    psf_file = os.path.join('output','pixel_psf.fits')
    if __name__ == '__main__':
        # Process the star data
        model = piff.PixelGrid(0.2, 16, start_sigma=0.9/2.355)
        interp = piff.BasisPolynomial(order=order)
        pointing = None     # wcs is not Celestial here, so pointing needs to be None.
        psf = piff.SimplePSF(model, interp)
        psf.fit(orig_stars, {0:input.images[0].wcs}, pointing, logger=logger)

        # Check that the interpolation is what it should be
        print('target.flux = ',target_star.fit.flux)
        test_star = psf.drawStar(target_star)
        print('flux = ', test_im.array.sum(), test_star.image.array.sum())
        print('max diff = ',np.max(np.abs(test_star.image.array-test_im.array)))
        np.testing.assert_almost_equal(test_star.image.array/2, test_im.array/2, decimal=3)

        # Check the convenience function that an end user would typically use
        image = psf.draw(x=x0, y=y0)
        np.testing.assert_almost_equal(image.array/2, test_im.array/2, decimal=3)

        # Round trip through a file
        psf.write(psf_file, logger)
        psf = piff.read(psf_file, logger)
        assert type(psf.model) is piff.PixelGrid
        assert type(psf.interp) is piff.BasisPolynomial
        test_star = psf.drawStar(target_star)
        np.testing.assert_almost_equal(test_star.image.array/2, test_im.array/2, decimal=3)

        # Check the convenience function that an end user would typically use
        image = psf.draw(x=x0, y=y0)
        np.testing.assert_almost_equal(image.array/2., test_im.array/2., decimal=3)

    # Do the whole thing with the config parser
    config = {
        'input' : {
            'image_file_name' : image_file,
            'cat_file_name' : cat_file,
            'x_col' : 'x',
            'y_col' : 'y',
            'noise' : noise_sigma**2,
            'sky' : sky_level,
            'stamp_size' : 48  # Bigger than we drew, but should still work.
        },
        'output' : {
            'file_name' : psf_file
        },
        'psf' : {
            'model' : {
                'type' : 'PixelGrid',
                'scale' : 0.2,
                'size' : 16,  # Much smaller than the input stamps, but this is plenty here.
                'start_sigma' : 0.9/2.355
            },
            'interp' : {
                'type' : 'BasisPolynomial',
                'order' : order
            },
        },
    }
    if __name__ == '__main__':
        config['verbose'] = 2
    else:
        config['verbose'] = 0

    print("Running piffify function")
    piff.piffify(config)
    psf = piff.read(psf_file)
    test_star = psf.drawStar(target_star)
    print("Max abs diff = ",np.max(np.abs(test_star.image.array - test_im.array)))
    np.testing.assert_almost_equal(test_star.image.array/2., test_im.array/2., decimal=3)

    # Test using the piffify executable
    with open('pixel_moffat.yaml','w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    if __name__ == '__main__':
        print("Running piffify executable")
        if os.path.exists(psf_file):
            os.remove(psf_file)
        piffify_exe = get_script_name('piffify')
        p = subprocess.Popen( [piffify_exe, 'pixel_moffat.yaml'] )
        p.communicate()
        psf = piff.read(psf_file)
        test_star = psf.drawStar(target_star)
        np.testing.assert_almost_equal(test_star.image.array/2., test_im.array/2., decimal=3)

    # test copy_image property of drawStar and draw
    for draw in [psf.drawStar, psf.model.draw]:
        target_star_copy = psf.interp.interpolate(piff.Star(target_star.data.copy(), target_star.fit.copy()))  # interp is so that when we do psf.model.draw we have fit.params to work with

        test_star_copy = draw(target_star_copy, copy_image=True)
        test_star_nocopy = draw(target_star_copy, copy_image=False)
        # if we modify target_star_copy, then test_star_nocopy should be modified, but not test_star_copy
        target_star_copy.image.array[0,0] = 23456
        assert test_star_nocopy.image.array[0,0] == target_star_copy.image.array[0,0]
        assert test_star_copy.image.array[0,0] != target_star_copy.image.array[0,0]
        # however the other pixels SHOULD still be all the same value
        assert test_star_nocopy.image.array[1,1] == target_star_copy.image.array[1,1]
        assert test_star_copy.image.array[1,1] == target_star_copy.image.array[1,1]

    # check that drawing onto an image does not return a copy
    image = psf.draw(x=x0, y=y0)
    image_reference = psf.draw(x=x0, y=y0, image=image)
    image_reference.array[0,0] = 123456
    assert image.array[0,0] == image_reference.array[0,0]
Exemple #7
0
def test_bad_hsm():
    """Test that stats don't break when all stars end up being flagged with hsm errors.
    """
    image_file = os.path.join('input','DECam_00241238_01.fits.fz')
    cat_file = os.path.join('input',
                            'DECam_00241238_01_psfcat_tb_maxmag_17.0_magcut_3.0_findstars.fits')
    psf_file = os.path.join('output','bad_hsm.fits')

    twodhist_file = os.path.join('output','bad_hsm_twod.pdf')
    whisker_file = os.path.join('output','bad_hsm_whisk.pdf')
    rho_file = os.path.join('output','bad_hsm_rho.pdf')
    shape_file = os.path.join('output','bad_hsm_shape.pdf')
    star_file = os.path.join('output','bad_hsm_star.pdf')
    hsm_file = os.path.join('output','bad_hsm_hsm.fits')
    sizemag_file = os.path.join('output','bad_hsm_sizemag.png')

    stamp_size = 25

    # The configuration dict with the right input fields for the file we're using.
    config = {
        'input' : {
            'nstars': 8,
            'image_file_name' : image_file,
            'image_hdu' : 1,
            'weight_hdu' : 3,
            'badpix_hdu' : 2,
            'cat_file_name' : cat_file,
            'cat_hdu' : 2,
            # These next two are intentionally backwards.  The PixelGrid will find some kind
            # of solution, but it will be complex garbage, and hsm will fail for them.
            'x_col' : 'YWIN_IMAGE',
            'y_col' : 'XWIN_IMAGE',
            'sky_col' : 'BACKGROUND',
            'stamp_size' : stamp_size,
            'ra' : 'TELRA',
            'dec' : 'TELDEC',
            'gain' : 'GAINA',
        },
        'output' : {
            'file_name' : psf_file,
            'stats' : [
                {
                    'type': 'TwoDHist',
                    'file_name': twodhist_file,
                },
                {
                    'type': 'Whisker',
                    'file_name': whisker_file,
                },
                {  # Note: stats doesn't have to be a list.
                    'type': 'Rho',
                    'file_name': rho_file
                },
                {
                    'type': 'ShapeHist',
                    'file_name': shape_file,
                },
                {
                    'type': 'Star',
                    'file_name': star_file,
                },
                {
                    'type': 'SizeMag',
                    'file_name': sizemag_file,
                },
                {
                    'type': 'HSMCatalog',
                    'file_name': hsm_file,
                },
            ],
        },
        'psf' : {
            'model' : {
                'type' : 'PixelGrid',
                'scale' : 0.3,
                'size' : 10,
            },
            'interp' : { 'type' : 'Mean' },
            'outliers' : {
                'type' : 'Chisq',
                'nsigma' : 0.05   # This will throw out all but 1, which adds an additional
                                  # test of Star stats when nstars < nplot
            }
        },
    }
    if __name__ == '__main__':
        logger = piff.config.setup_logger(1)
    else:
        config['verbose'] = 0
        logger = None

    for f in [twodhist_file, rho_file, shape_file, star_file, hsm_file]:
        if os.path.exists(f):
            os.remove(f)

    piff.piffify(config, logger=logger)

    # Confirm that all but one star was rejected, since that was part of the intent of this test.
    psf = piff.read(psf_file)
    print('stars = ',psf.stars)
    print('nremoved = ',psf.nremoved)
    assert len(psf.stars) == 1
    assert psf.nremoved == 7    # There were 8 to start.

    for f in [twodhist_file, rho_file, shape_file, star_file, sizemag_file, hsm_file]:
        assert os.path.exists(f)

    # Check hsm file with bad measurements
    # The one star that was left still fails hsm measurement here.
    data = fitsio.read(hsm_file)
    for col in ['ra', 'dec', 'x', 'y', 'u', 'v',
                'T_data', 'g1_data', 'g2_data',
                'T_model', 'g1_model', 'g2_model',
                'flux', 'reserve', 'flag_truth', 'flag_model']:
        assert len(data[col]) == 1
    print('flag_truth = ',data['flag_truth'])
    print('flag_model = ',data['flag_model'])
    np.testing.assert_array_equal(data['flag_truth'], 7)
    np.testing.assert_array_equal(data['flag_model'], 7)
Exemple #8
0
def test_reserve():
    """Test the reserve_frac option.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(
            log_file='output/test_single_reserve.log')

    # Make the image
    image = galsim.Image(2048, 2048, scale=0.26)

    # Where to put the stars.
    x_list = [
        123.12, 345.98, 567.25, 1094.94, 924.15, 1532.74, 1743.11, 888.39,
        1033.29, 1409.31
    ]
    y_list = [
        345.43, 567.45, 1094.32, 924.29, 1532.92, 1743.83, 888.83, 1033.19,
        1409.20, 123.11
    ]

    # Draw a Gaussian PSF at each location on the image.
    sigma = 1.3
    g1 = 0.23
    g2 = -0.17
    true_params = [sigma, g1, g2]
    psf = galsim.Gaussian(sigma=sigma).shear(g1=g1, g2=g2)
    for x, y in zip(x_list, y_list):
        bounds = galsim.BoundsI(int(x - 31), int(x + 32), int(y - 31),
                                int(y + 32))
        psf.drawImage(image[bounds],
                      center=galsim.PositionD(x, y),
                      method='no_pixel')
    image.addNoise(
        galsim.GaussianNoise(rng=galsim.BaseDeviate(1234), sigma=1e-6))

    # Write out the image to a file
    image_file = os.path.join('output', 'test_simple_reserve_image.fits')
    image.write(image_file)

    # Write out the catalog to a file
    dtype = [('x', 'f8'), ('y', 'f8')]
    data = np.empty(len(x_list), dtype=dtype)
    data['x'] = x_list
    data['y'] = y_list
    cat_file = os.path.join('output', 'test_simple_reserve_cat.fits')
    fitsio.write(cat_file, data, clobber=True)

    psf_file = os.path.join('output', 'test_simple_reserve_psf.fits')
    config = {
        'input': {
            'image_file_name': image_file,
            'cat_file_name': cat_file,
            'reserve_frac': 0.2,
            'stamp_size': 32,
        },
        'psf': {
            'model': {
                'type': 'Gaussian',
                'fastfit': True,
                'include_pixel': False
            },
            'interp': {
                'type': 'Mean'
            },
        },
        'output': {
            'file_name': psf_file
        },
    }

    piff.piffify(config, logger)
    psf = piff.read(psf_file)
    assert type(psf.model) is piff.Gaussian
    assert type(psf.interp) is piff.Mean
    print('chisq = ', psf.chisq)
    print('dof = ', psf.dof)
    nreserve = len([s for s in psf.stars if s.is_reserve])
    ntot = len(psf.stars)
    print('reserve = %s/%s' % (nreserve, ntot))
    assert nreserve == 2
    assert ntot == 10
    print('dof =? ', (32 * 32 - 6) * (ntot - nreserve))
    assert psf.dof == (32 * 32 - 6) * (ntot - nreserve)
    for star in psf.stars:
        # Fits should be good for both reserve and non-reserve stars
        np.testing.assert_almost_equal(star.fit.params, true_params, decimal=4)
Exemple #9
0
def test_yaml():

    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(log_file='output/test_gp.log')

    # Take DES test image, and test doing a psf run with GP interpolator
    # Use config parser:
    psf_file = os.path.join('output', 'gp_psf.fits')
    config = {
        'input': {
            # These can be regular strings
            'image_file_name': 'input/DECam_00241238_01.fits.fz',
            # Or any GalSim str value type.  e.g. FormattedStr
            'cat_file_name': {
                'type': 'FormattedStr',
                'format':
                '%s/DECam_%08d_%02d_psfcat_tb_maxmag_17.0_magcut_3.0_findstars.fits',
                'items': [
                    'input',  # dir
                    241238,  # expnum
                    1  # chipnum
                ]
            },

            # What hdu is everything in?
            'image_hdu': 1,
            'badpix_hdu': 2,
            'weight_hdu': 3,
            'cat_hdu': 2,

            # What columns in the catalog have things we need?
            'x_col': 'XWIN_IMAGE',
            'y_col': 'YWIN_IMAGE',
            'ra': 'TELRA',
            'dec': 'TELDEC',
            'gain': 'GAINA',
            'sky_col': 'BACKGROUND',

            # How large should the postage stamp cutouts of the stars be?
            'stamp_size': 21,
        },
        'psf': {
            'model': {
                'type': 'GSObjectModel',
                'fastfit': True,
                'gsobj': 'galsim.Gaussian(sigma=1.0)'
            },
            'interp': {
                'type': 'GPInterp',
                'keys': ['u', 'v'],
                'optimizer': 'none',
                'kernel': 'RBF(200.0)'
            }
        },
        'output': {
            'file_name': psf_file
        },
    }

    piff.piffify(config, logger)
    psf = piff.read(psf_file)
    assert type(psf.model) is piff.GSObjectModel
    assert type(psf.interp) is piff.GPInterp
    print('nstars = ', len(psf.stars))
    target = psf.stars[17]
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   target.fit.params,
                                   decimal=3)
    # This should also work if the target doesn't have a fit yet.
    print('interpolate ', piff.Star(target.data, None))
    test_star = psf.interp.interpolate(piff.Star(target.data, None))
    np.testing.assert_almost_equal(test_star.fit.params,
                                   target.fit.params,
                                   decimal=3)
Exemple #10
0
def test_single_image():
    """Test the whole process with a single image.

    Note: This test is based heavily on test_single_image in test_simple.py.
    """
    import os
    import fitsio
    np_rng = np.random.RandomState(1234)

    # Make the image
    image = galsim.Image(2048, 2048, scale=0.2)

    # The (x,y) values will be on a grid 5 x 5 stars with a random sub-pixel offset.
    xvals = np.linspace(50., 1950., 5)
    yvals = np.linspace(50., 1950., 5)
    x_list, y_list = np.meshgrid(xvals, yvals)
    x_list = x_list.flatten()
    y_list = y_list.flatten()
    x_list = x_list + (np_rng.rand(len(x_list)) - 0.5)
    y_list = y_list + (np_rng.rand(len(x_list)) - 0.5)
    print('x_list = ', x_list)
    print('y_list = ', y_list)
    # Range of fluxes from 100 to 15000
    flux_list = 100. * np.exp(5. * np_rng.rand(len(x_list)))
    print('fluxes range from ', np.min(flux_list), np.max(flux_list))

    # Draw a Moffat PSF at each location on the image.
    # Have the truth values vary quadratically across the image.
    beta_fn = lambda x, y: 3.5 - 0.1 * (x / 1000) + 0.08 * (y / 1000)**2
    fwhm_fn = lambda x, y: 0.9 + 0.05 * (x / 1000) - 0.03 * (
        y / 1000) + 0.02 * (x / 1000) * (y / 1000)
    e1_fn = lambda x, y: 0.02 - 0.01 * (x / 1000)
    e2_fn = lambda x, y: -0.03 + 0.02 * (x / 1000)**2 - 0.01 * (y / 1000) * 2

    for x, y, flux in zip(x_list, y_list, flux_list):
        beta = beta_fn(x, y)
        fwhm = fwhm_fn(x, y)
        e1 = e1_fn(x, y)
        e2 = e2_fn(x, y)
        print(x, y, beta, fwhm, e1, e2)
        moffat = galsim.Moffat(fwhm=fwhm, beta=beta, flux=flux).shear(e1=e1,
                                                                      e2=e2)
        bounds = galsim.BoundsI(int(x - 31), int(x + 32), int(y - 31),
                                int(y + 32))
        offset = galsim.PositionD(x - int(x) - 0.5, y - int(y) - 0.5)
        moffat.drawImage(image=image[bounds], offset=offset, method='no_pixel')
    print('drew image')

    # Write out the image to a file
    image_file = os.path.join('data', 'pixel_moffat_image.fits')
    image.write(image_file)
    print('wrote image')

    # Write out the catalog to a file
    dtype = [('x', 'f8'), ('y', 'f8')]
    data = np.empty(len(x_list), dtype=dtype)
    data['x'] = x_list
    data['y'] = y_list
    cat_file = os.path.join('data', 'pixel_moffat_cat.fits')
    fitsio.write(cat_file, data, clobber=True)
    print('wrote catalog')

    # Use InputFiles to read these back in
    input = piff.InputFiles(image_file, cat_file, stamp_size=32)
    assert input.image_files == [image_file]
    assert input.cat_files == [cat_file]
    assert input.x_col == 'x'
    assert input.y_col == 'y'

    # Check image
    input.readImages()
    assert len(input.images) == 1
    np.testing.assert_equal(input.images[0].array, image.array)

    # Check catalog
    input.readStarCatalogs()
    assert len(input.cats) == 1
    np.testing.assert_equal(input.cats[0]['x'], x_list)
    np.testing.assert_equal(input.cats[0]['y'], y_list)

    # Make stars
    orig_stars = input.makeStars()
    assert len(orig_stars) == len(x_list)
    assert orig_stars[0].image.array.shape == (32, 32)

    # Make a test star, not at the location of any of the model stars to use for each of the
    # below tests.
    x0 = 1024  # Some random position, not where a star was originally.
    y0 = 133
    beta = beta_fn(x0, y0)
    fwhm = fwhm_fn(x0, y0)
    e1 = e1_fn(x0, y0)
    e2 = e2_fn(x0, y0)
    moffat = galsim.Moffat(fwhm=fwhm, beta=beta).shear(e1=e1, e2=e2)
    target_star = piff.Star.makeTarget(x=x0, y=y0, scale=image.scale)
    test_im = galsim.ImageD(bounds=target_star.image.bounds, scale=image.scale)
    moffat.drawImage(image=test_im, method='no_pixel', use_true_center=False)
    print('made test star')

    # These tests are slow, and it's really just doing the same thing three times, so
    # only do the first one when running via nosetests.
    if True:
        # Process the star data
        model = piff.PixelGrid(0.2, 16, start_sigma=0.9 / 2.355)
        interp = piff.BasisPolynomial(order=2)
        if __name__ == '__main__':
            logger = piff.config.setup_logger(2)
        else:
            logger = None
        pointing = None  # wcs is not Celestial here, so pointing needs to be None.
        psf = piff.SimplePSF(model, interp)
        psf.fit(orig_stars, {0: input.images[0].wcs}, pointing, logger=logger)

        # Check that the interpolation is what it should be
        print('target.flux = ', target_star.fit.flux)
        test_star = psf.drawStar(target_star)
        #print('test_im center = ',test_im[b].array)
        #print('flux = ',test_im.array.sum())
        #print('interp_im center = ',test_star.image[b].array)
        #print('flux = ',test_star.image.array.sum())
        #print('max diff = ',np.max(np.abs(test_star.image.array-test_im.array)))
        np.testing.assert_almost_equal(test_star.image.array,
                                       test_im.array,
                                       decimal=3)

        # Check the convenience function that an end user would typically use
        image = psf.draw(x=x0, y=y0)
        np.testing.assert_almost_equal(image.array, test_im.array, decimal=3)

        # Round trip through a file
        psf_file = os.path.join('output', 'pixel_psf.fits')
        psf.write(psf_file, logger)
        psf = piff.read(psf_file, logger)
        assert type(psf.model) is piff.PixelGrid
        assert type(psf.interp) is piff.BasisPolynomial
        test_star = psf.drawStar(target_star)
        np.testing.assert_almost_equal(test_star.image.array,
                                       test_im.array,
                                       decimal=3)

        # Check the convenience function that an end user would typically use
        image = psf.draw(x=x0, y=y0)
        np.testing.assert_almost_equal(image.array, test_im.array, decimal=3)

    # Do the whole thing with the config parser
    config = {
        'input': {
            'images': image_file,
            'cats': cat_file,
            'x_col': 'x',
            'y_col': 'y',
            'stamp_size': 48  # Bigger than we drew, but should still work.
        },
        'output': {
            'file_name': psf_file
        },
        'psf': {
            'model': {
                'type': 'PixelGrid',
                'scale': 0.2,
                'size':
                16,  # Much smaller than the input stamps, but this is plenty here.
                'start_sigma': 0.9 / 2.355
            },
            'interp': {
                'type': 'BasisPolynomial',
                'order': 2
            },
        },
    }
    if __name__ == '__main__':
        print("Running piffify function")
        piff.piffify(config)
        psf = piff.read(psf_file)
        test_star = psf.drawStar(target_star)
        np.testing.assert_almost_equal(test_star.image.array,
                                       test_im.array,
                                       decimal=3)

    # Test using the piffify executable
    config['verbose'] = 0
    with open('pixel_moffat.yaml', 'w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    if __name__ == '__main__':
        print("Running piffify executable")
        if os.path.exists(psf_file):
            os.remove(psf_file)
        piffify_exe = get_script_name('piffify')
        p = subprocess.Popen([piffify_exe, 'pixel_moffat.yaml'])
        p.communicate()
        psf = piff.read(psf_file)
        test_star = psf.drawStar(target_star)
        np.testing.assert_almost_equal(test_star.image.array,
                                       test_im.array,
                                       decimal=3)
Exemple #11
0
def test_yaml():

    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(log_file='output/test_gp.log')

    # Take DES test image, and test doing a psf run with GP interpolator
    # Use config parser:
    for gp_piff in ['GPInterp', 'GPInterp2pcf']:
        psf_file = os.path.join('output','gp_psf.fits')
        config = {
            'input' : {
                # These can be regular strings
                'image_file_name' : 'input/DECam_00241238_01.fits.fz',
                # Or any GalSim str value type.  e.g. FormattedStr
                'cat_file_name' : {
                    'type': 'FormattedStr',
                    'format': '%s/DECam_%08d_%02d_psfcat_tb_maxmag_17.0_magcut_3.0_findstars.fits',
                    'items': [
                        'input',    # dir
                        241238,     # expnum
                        1           # chipnum
                    ]
                },
    
                # What hdu is everything in?
                'image_hdu' : 1,
                'badpix_hdu' : 2,
                'weight_hdu' : 3,
                'cat_hdu' : 2,
    
                # What columns in the catalog have things we need?
                'x_col' : 'XWIN_IMAGE',
                'y_col' : 'YWIN_IMAGE',
                'ra' : 'TELRA',
                'dec' : 'TELDEC',
                'gain' : 'GAINA',
                'sky_col' : 'BACKGROUND',
    
                # How large should the postage stamp cutouts of the stars be?
                'stamp_size' : 21,
            },
            'psf' : {
                'model' : { 'type' : 'GSObjectModel',
                            'fastfit' : True,
                            'gsobj' : 'galsim.Gaussian(sigma=1.0)' },
                'interp' : { 'type' : gp_piff,
                             'keys' : ['u', 'v'],
                             'kernel' : 'RBF(200.0)',
                             'optimize' : False,}
            },
            'output' : { 'file_name' : psf_file },
        }

        if __name__ != '__main__':
            config['input']['nstars'] = 25

        piff.piffify(config, logger)
        psf = piff.read(psf_file)
        assert type(psf.model) is piff.GSObjectModel
        assert type(psf.interp) is piff.GPInterp or type(psf.interp) is piff.GPInterp2pcf
        print('nstars = ',len(psf.stars))
        target = psf.stars[17]
        test_star = psf.interp.interpolate(target)
        np.testing.assert_almost_equal(test_star.fit.params, target.fit.params, decimal=3)
        # This should also work if the target doesn't have a fit yet.
        print('interpolate ',piff.Star(target.data,None))
        test_star = psf.interp.interpolate(piff.Star(target.data,None))
        np.testing.assert_almost_equal(test_star.fit.params, target.fit.params, decimal=3)
Exemple #12
0
def test_parallel():
    # Run the same test as test_single, but using nproc
    wcs1 = galsim.TanWCS(
        galsim.AffineTransform(0.26, 0.05, -0.08, -0.24,
                               galsim.PositionD(1024, 1024)),
        galsim.CelestialCoord(-5 * galsim.arcmin, -25 * galsim.degrees))
    wcs2 = galsim.TanWCS(
        galsim.AffineTransform(0.25, -0.02, 0.01, 0.24,
                               galsim.PositionD(1024, 1024)),
        galsim.CelestialCoord(5 * galsim.arcmin, -25 * galsim.degrees))
    field_center = galsim.CelestialCoord(0 * galsim.degrees,
                                         -25 * galsim.degrees)

    if __name__ == '__main__':
        nstars = 20  # per ccd
    else:
        nstars = 6  # per ccd
    rng = np.random.RandomState(1234)
    x = rng.random_sample(nstars) * 2000 + 24
    y = rng.random_sample(nstars) * 2000 + 24
    ra1, dec1 = wcs1.toWorld(x, y, units='rad')
    u, v = field_center.project_rad(ra1, dec1, projection='gnomonic')
    e1 = 0.02 + 2.e-5 * u - 3.e-9 * u**2 + 2.e-9 * v**2
    e2 = -0.04 - 3.e-5 * v + 1.e-9 * u * v + 3.e-9 * v**2
    s = 0.3 + 8.e-9 * (u**2 + v**2) - 1.e-9 * u * v

    data1 = np.array(list(zip(x, y, e1, e2, s)),
                     dtype=[('x', float), ('y', float), ('e1', float),
                            ('e2', float), ('s', float)])
    im1 = drawImage(2048, 2048, wcs1, x, y, e1, e2, s)
    im1.write('output/test_parallel_im1.fits')

    x = rng.random_sample(nstars) * 2000 + 24
    y = rng.random_sample(nstars) * 2000 + 24
    ra2, dec2 = wcs2.toWorld(x, y, units='rad')
    u, v = field_center.project_rad(ra1, dec1, projection='gnomonic')
    # Same functions of u,v, but using the positions on chip 2
    e1 = 0.02 + 2.e-5 * u - 3.e-9 * u**2 + 2.e-9 * v**2
    e2 = -0.04 - 3.e-5 * v + 1.e-9 * u * v + 3.e-9 * v**2
    s = 0.3 + 8.e-9 * (u**2 + v**2) - 1.e-9 * u * v

    data2 = np.array(list(zip(x, y, e1, e2, s)),
                     dtype=[('x', float), ('y', float), ('e1', float),
                            ('e2', float), ('s', float)])
    im2 = drawImage(2048, 2048, wcs2, x, y, e1, e2, s)
    im2.write('output/test_parallel_im2.fits')

    ra12 = np.concatenate([ra1, ra2])
    dec12 = np.concatenate([dec1, dec2])
    data12 = np.array(list(zip(ra12, dec12)),
                      dtype=[('ra', float), ('dec', float)])
    fitsio.write('output/test_parallel.fits', data12, clobber=True)

    # im3 is blank.  Will give errors trying to measure PSF from it.
    im3 = galsim.Image(2048, 2048, wcs=wcs2)
    im3.write('output/test_parallel_im3.fits')

    psf_file = os.path.join('output', 'test_single.fits')
    config = {
        'input': {
            # A third way to input these same file names.  Use GalSim config values and
            # explicitly specify the number of images to read
            'nimages': 2,
            'image_file_name': {
                'type': 'FormattedStr',
                'format': '%s/test_parallel_im%d.fits',
                'items': ['output', '$image_num+1'],
            },
            'cat_file_name': 'output/test_parallel.fits',
            'chipnum': '$image_num+1',
            'ra_col': 'ra',
            'dec_col': 'dec',
            'ra_units': 'rad',
            'dec_units': 'rad',
            'nproc': -1,
        },
        'psf': {
            'type': 'SingleChip',
            'model': {
                'type': 'Moffat',
                'beta': 2.5,
            },
            'interp': {
                'type': 'Polynomial',
                'order': 2,
            },
            'nproc': 2,
        },
        'output': {
            'file_name': psf_file,
        },
    }
    with CaptureLog(level=2) as cl:
        piff.piffify(config, logger=cl.logger)
    psf = piff.read(psf_file)

    for chipnum, data, wcs in [(1, data1, wcs1), (2, data2, wcs2)]:
        for k in range(nstars):
            x = data['x'][k]
            y = data['y'][k]
            e1 = data['e1'][k]
            e2 = data['e2'][k]
            s = data['s'][k]
            image_pos = galsim.PositionD(x, y)
            star = piff.Star.makeTarget(x=x,
                                        y=y,
                                        wcs=wcs,
                                        stamp_size=48,
                                        pointing=field_center,
                                        chipnum=chipnum)
            star = psf.drawStar(star)
            np.testing.assert_almost_equal(star.fit.params, [s, e1, e2],
                                           decimal=6)

    # Finally, check that the logger properly captures the subprocess logs
    with CaptureLog(level=2) as cl:
        psf = piff.process(config, cl.logger)
    #print('with nproc=2, log = ',cl.output)
    assert "Processing catalog 1" in cl.output
    assert "Processing catalog 2" in cl.output
    assert "Building solution for chip 1" in cl.output
    assert "Building solution for chip 2" in cl.output

    # Check that errors in the solution get properly reported.
    config['input']['nimages'] = 3
    with CaptureLog(level=2) as cl:
        psf = piff.process(config, cl.logger)
    assert "Removed 6 stars in initialize" in cl.output
    assert "No stars.  Cannot find PSF model." in cl.output
    assert "Solutions failed for chipnums: [3]" in cl.output

    # Check that errors in the multiprocessing input get properly reported.
    config['input']['ra_col'] = 'invalid'
    with CaptureLog(level=2) as cl:
        with np.testing.assert_raises(ValueError):
            psf = piff.process(config, cl.logger)
    assert "ra_col = invalid is not a column" in cl.output

    # With nproc=1, the error is raised directly.
    config['input']['nproc'] = 1
    config['verbose'] = 0
    with np.testing.assert_raises(ValueError):
        psf = piff.process(config)

    # But just the input error.  Not the one in fitting.
    config['psf']['nproc'] = 1
    config['input']['ra_col'] = 'ra'
    config['verbose'] = 1
    with CaptureLog(level=1) as cl:
        psf = piff.process(config, logger=cl.logger)
    assert "No stars.  Cannot find PSF model." in cl.output
    assert "Ignoring this failure and continuing on." in cl.output
	# pixmappy = os.path.join(pixmappy_dir, 'zone%03d.astro'%zone)
	# wcs = pixmappy.GalSimWCS(pixmappy_file, exp=expnum, ccdnum=ccdnum, default_color=0)

	cat_file = '/Users/rebeccachen/Desktop/Piff_work/y3_test/'+str(expnum)+'_c'+str_ccdnum+'.fits'
	psf_file = '/Users/rebeccachen/Desktop/Piff_work/y3_test/D00'+str(expnum)+'_r_c'+str_ccdnum+'_r2277p01_gaiamatch.piff'


	config = piff.read_config(piff_config)
	config['input']['image_file_name'] = img_file
	config['input']['cat_file_name'] = cat_file
	config['output']['file_name'] = psf_file
	# config['input']['wcs']['file_name'] = pixmappy
	# config['input']['wcs']['exp'] = expnum
	# config['input']['wcs']['ccdnum'] = ccdnum
	piff.piffify(config, logger)


#gaia matches run
for i in [x for x in range(1, 63) if (x != 31 and x!= 61 and x!=2 and x!=5)]:
	ccdnum = i
	str_ccdnum = "%.2d" % ccdnum
	img_file = '/Users/rebeccachen/Desktop/Piff_work/y3_test/D00'+str(expnum)+'_r_c'+str_ccdnum+'_r2277p01_immasked.fits'

	# f = fitsio.FITS(img_file)
	# header_list = f[hdu].read_header_list()
	# header_list = [ d for d in header_list if 'CONTINUE' not in d['name'] ]
	# h = fitsio.FITSHDR(header_list)
	# detpos = h['DETPOS'].strip()
	# dp = detpos[ccdnum]
	# wz = np.where((which_zone['expnum'] == expnum) & (which_zone['detpos'] == dp))[0][0]
Exemple #14
0
def test_single_image():
    """Test the simple case of one image and one catalog.
    """
    # Make the image
    image = galsim.Image(2048, 2048, scale=0.26)

    # Where to put the stars.  Include some flagged and not used locations.
    x_list = [
        123.12, 345.98, 567.25, 1094.94, 924.15, 1532.74, 1743.11, 888.39,
        1033.29, 1409.31
    ]
    y_list = [
        345.43, 567.45, 1094.32, 924.29, 1532.92, 1743.83, 888.83, 1033.19,
        1409.20, 123.11
    ]
    flag_list = [0, 0, 12, 0, 0, 1, 0, 0, 0, 0]
    use_list = [1, 1, 1, 1, 1, 0, 1, 1, 0, 1]

    # Draw a Gaussian PSF at each location on the image.
    sigma = 1.3
    g1 = 0.23
    g2 = -0.17
    psf = galsim.Gaussian(sigma=sigma).shear(g1=g1, g2=g2)
    for x, y, flag, use in zip(x_list, y_list, flag_list, use_list):
        bounds = galsim.BoundsI(int(x - 31), int(x + 32), int(y - 31),
                                int(y + 32))
        offset = galsim.PositionD(x - int(x) - 0.5, y - int(y) - 0.5)
        psf.drawImage(image=image[bounds], method='no_pixel', offset=offset)
        # corrupt the ones that are marked as flagged
        if flag:
            print('corrupting star at ', x, y)
            ar = image[bounds].array
            im_max = np.max(ar) * 0.2
            ar[ar > im_max] = im_max
    image.addNoise(
        galsim.GaussianNoise(rng=galsim.BaseDeviate(1234), sigma=1e-6))

    # Write out the image to a file
    image_file = os.path.join('data', 'simple_image.fits')
    image.write(image_file)

    # Write out the catalog to a file
    dtype = [('x', 'f8'), ('y', 'f8'), ('flag', 'i2'), ('use', 'i2')]
    data = np.empty(len(x_list), dtype=dtype)
    data['x'] = x_list
    data['y'] = y_list
    data['flag'] = flag_list
    data['use'] = use_list
    cat_file = os.path.join('data', 'simple_cat.fits')
    fitsio.write(cat_file, data, clobber=True)

    # Use InputFiles to read these back in
    input = piff.InputFiles(image_file, cat_file)
    assert input.image_files == [image_file]
    assert input.cat_files == [cat_file]
    assert input.x_col == 'x'
    assert input.y_col == 'y'

    # Check image
    input.readImages()
    assert len(input.images) == 1
    np.testing.assert_equal(input.images[0].array, image.array)

    # Check catalog
    input.readStarCatalogs()
    assert len(input.cats) == 1
    np.testing.assert_equal(input.cats[0]['x'], x_list)
    np.testing.assert_equal(input.cats[0]['y'], y_list)

    # Repeat, using flag and use columns this time.
    input = piff.InputFiles(image_file,
                            cat_file,
                            flag_col='flag',
                            use_col='use',
                            stamp_size=48)
    assert input.flag_col == 'flag'
    assert input.use_col == 'use'
    input.readImages()
    input.readStarCatalogs()
    assert len(input.cats[0]) == 7

    # Make star data
    orig_stars = input.makeStars()
    assert len(orig_stars) == 7
    assert orig_stars[0].image.array.shape == (48, 48)

    # Process the star data
    # can only compare to truth if include_pixel=False
    model = piff.Gaussian(fastfit=True, include_pixel=False)
    interp = piff.Mean()
    fitted_stars = [model.fit(model.initialize(star)) for star in orig_stars]
    interp.solve(fitted_stars)
    print('mean = ', interp.mean)

    # Check that the interpolation is what it should be
    target = piff.Star.makeTarget(x=1024,
                                  y=123)  # Any position would work here.
    true_params = [sigma, g1, g2]
    test_star = interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # Now test running it via the config parser
    psf_file = os.path.join('output', 'simple_psf.fits')
    config = {
        'input': {
            'images': image_file,
            'cats': cat_file,
            'flag_col': 'flag',
            'use_col': 'use',
            'stamp_size': 48
        },
        'psf': {
            'model': {
                'type': 'Gaussian',
                'fastfit': True,
                'include_pixel': False
            },
            'interp': {
                'type': 'Mean'
            },
        },
        'output': {
            'file_name': psf_file
        },
    }
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(verbose=0)
    orig_stars, wcs, pointing = piff.Input.process(config['input'], logger)

    # Use a SimplePSF to process the stars data this time.
    psf = piff.SimplePSF(model, interp)

    psf.fit(orig_stars, wcs, pointing, logger=logger)
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # Round trip to a file
    psf.write(psf_file, logger)
    psf = piff.read(psf_file, logger)
    assert type(psf.model) is piff.Gaussian
    assert type(psf.interp) is piff.Mean
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # Do the whole thing with the config parser
    os.remove(psf_file)

    piff.piffify(config, logger)
    psf = piff.read(psf_file)
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # Test using the piffify executable
    os.remove(psf_file)
    config['verbose'] = 0
    with open('simple.yaml', 'w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    piffify_exe = get_script_name('piffify')
    p = subprocess.Popen([piffify_exe, 'simple.yaml'])
    p.communicate()
    psf = piff.read(psf_file)
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # Test that we can make rho statistics
    min_sep = 1
    max_sep = 100
    bin_size = 0.1
    stats = piff.RhoStats(min_sep=min_sep, max_sep=max_sep, bin_size=bin_size)
    stats.compute(psf, orig_stars)

    rhos = [stats.rho1, stats.rho2, stats.rho3, stats.rho4, stats.rho5]
    for rho in rhos:
        # Test the range of separations
        radius = np.exp(rho.logr)
        # last bin can be one bigger than max_sep
        np.testing.assert_array_less(radius,
                                     np.exp(np.log(max_sep) + bin_size))
        np.testing.assert_array_less(min_sep, radius)
        np.testing.assert_array_almost_equal(np.diff(rho.logr),
                                             bin_size,
                                             decimal=5)

        # Test that the max absolute value of each rho isn't crazy
        np.testing.assert_array_less(np.abs(rho.xip), 1)

        # # Check that each rho isn't precisely zero. This means the sum of abs > 0
        np.testing.assert_array_less(0, np.sum(np.abs(rho.xip)))

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

    # Test that we can make summary shape statistics, using HSM
    shapeStats = piff.ShapeHistogramsStats()
    shapeStats.compute(psf, orig_stars)

    # test their characteristics
    np.testing.assert_array_almost_equal(sigma, shapeStats.T, decimal=4)
    np.testing.assert_array_almost_equal(sigma, shapeStats.T_model, decimal=3)
    np.testing.assert_array_almost_equal(g1, shapeStats.g1, decimal=4)
    np.testing.assert_array_almost_equal(g1, shapeStats.g1_model, decimal=3)
    np.testing.assert_array_almost_equal(g2, shapeStats.g2, decimal=4)
    np.testing.assert_array_almost_equal(g2, shapeStats.g2_model, decimal=3)

    shape_psf_file = os.path.join('output', 'simple_psf_shapestats.pdf')
    shapeStats.write(shape_psf_file)

    # Test that we can use the config parser for both RhoStats and ShapeHistogramsStats
    config['output']['stats'] = [
        {
            'type': 'ShapeHistograms',
            'file_name': shape_psf_file
        },
        {
            'type': 'Rho',
            'file_name': rho_psf_file
        },
        {
            'type': 'TwoDHist',
            'file_name': os.path.join('output',
                                      'simple_psf_twodhiststats.pdf'),
            'number_bins_u': 3,
            'number_bins_v': 3,
        },
        {
            'type': 'TwoDHist',
            'file_name': os.path.join('output',
                                      'simple_psf_twodhiststats_std.pdf'),
            'reducing_function': 'np.std',
            'number_bins_u': 3,
            'number_bins_v': 3,
        },
    ]

    os.remove(psf_file)
    os.remove(rho_psf_file)
    os.remove(shape_psf_file)
    piff.piffify(config, logger)

    # Test using the piffify executable
    os.remove(psf_file)
    os.remove(rho_psf_file)
    os.remove(shape_psf_file)
    config['verbose'] = 0
    with open('simple.yaml', 'w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    p = subprocess.Popen([piffify_exe, 'simple.yaml'])
    p.communicate()
Exemple #15
0
def test_depr_select():
    # A bunch of keys used to be allowed in input, but now belong in select.
    # Check that the old way still works, but gives a warning.

    # This is the input from test_stars in test_input.py
    dir = 'input'
    image_file = 'test_input_image_00.fits'
    cat_file = 'test_input_cat_00.fits'
    psf_file = os.path.join('output','test_depr_select.fits')

    config = {
        'input' : {
                'dir' : dir,
                'image_file_name' : image_file,
                'cat_file_name' : cat_file,
                'weight_hdu' : 1,
                'sky_col' : 'sky',
                'gain_col' : 'gain',
                'use_partial' : True,
                'nstars': 15,  # Just to make the test faster
             },
        'select': {
                'max_snr' : 200,
                'min_snr' : 20,
                'hsm_size_reject' : 20,
                'max_edge_frac': 0.25,
                'stamp_center_size': 10,
                'max_mask_pixels' : 20,
                'reserve_frac' : 0.1,
                'seed': 1234,
        },
        'psf': {
            'model' : {'type': 'Gaussian'},
            'interp' : {'type': 'Mean'},
        },
        'output' : { 'file_name' : psf_file },
    }

    logger = piff.config.setup_logger(log_file='output/test_depr_select.log')

    # This is the new API
    print('config = ',config)
    piff.piffify(config, logger)
    psf1 = piff.read(psf_file)
    im1 = psf1.draw(x=23, y=34, stamp_size=16)
    print('len1 = ',len(psf1.stars))

    # This is the old API
    config['input'].update(config['select'])
    del config['select']
    config = galsim.config.CleanConfig(config)
    print('config = ',config)
    with CaptureLog(level=1) as cl:
        piff.piffify(config, cl.logger)
    assert "WARNING: Items [" in cl.output
    assert "] should now be in the 'select' field of the config file." in cl.output
    psf2 = piff.read(psf_file)
    print('len2 = ',len(psf2.stars))
    assert len(psf1.stars) == len(psf2.stars)
    im2 = psf2.draw(x=23, y=34, stamp_size=16)
    np.testing.assert_allclose(im2.array, im1.array)

    # Also ok for some items to be in select, but erroneously put some in input.
    config['input']['min_snr'] = config['select'].pop('min_snr')
    config['input']['max_snr'] = config['select'].pop('max_snr')
    config = galsim.config.CleanConfig(config)
    print('config = ',config)
    with CaptureLog(level=1) as cl:
        piff.piffify(config, cl.logger)
    assert "WARNING: Items ['max_snr', 'min_snr'] should now be in the 'select' field of the config file." in cl.output
    psf3 = piff.read(psf_file)
    print('len3 = ',len(psf3.stars))
    assert len(psf1.stars) == len(psf3.stars)
    im3 = psf3.draw(x=23, y=34, stamp_size=16)
    np.testing.assert_allclose(im3.array, im1.array)
Exemple #16
0
def test_des_image():
    """Test the whole process with a DES CCD.
    """
    import os
    import fitsio

    image_file = 'input/DECam_00241238_01.fits.fz'
    cat_file = 'input/DECam_00241238_01_psfcat_tb_maxmag_17.0_magcut_3.0_findstars.fits'
    orig_image = galsim.fits.read(image_file)
    psf_file = os.path.join('output','pixel_des_psf.fits')

    if __name__ == '__main__':
        # These match what Gary used in fit_des.py
        nstars = None
        scale = 0.15
        size = 31
        order = 2
        nsigma = 4
    else:
        # These are faster and good enough for the unit tests.
        nstars = 25
        scale = 0.26
        size = 15
        order = 1
        nsigma = 1.  # This needs to be low to make sure we do test outlier rejection here.
    stamp_size = 25

    # The configuration dict with the right input fields for the file we're using.
    start_sigma = 1.0/2.355  # TODO: Need to make this automatic somehow.
    config = {
        'input' : {
            'nstars': nstars,
            'image_file_name' : image_file,
            'image_hdu' : 1,
            'weight_hdu' : 3,
            'badpix_hdu' : 2,
            'cat_file_name' : cat_file,
            'cat_hdu' : 2,
            'x_col' : 'XWIN_IMAGE',
            'y_col' : 'YWIN_IMAGE',
            'sky_col' : 'BACKGROUND',
            'stamp_size' : stamp_size,
            'ra' : 'TELRA',
            'dec' : 'TELDEC',
            'gain' : 'GAINA',
            # Test explicitly specifying the wcs (although it is the same here as what is in the
            # image anyway).
            'wcs' : {
                'type': 'Fits',
                'file_name': image_file
            }
        },
        'output' : {
            'file_name' : psf_file,
        },
        'psf' : {
            'model' : {
                'type' : 'PixelGrid',
                'scale' : scale,
                'size' : size,
                'interp' : 'Lanczos(5)',
                'start_sigma' : start_sigma,
            },
            'interp' : {
                'type' : 'BasisPolynomial',
                'order' : order,
            },
            'outliers' : {
                'type' : 'Chisq',
                'nsigma' : nsigma,
                'max_remove' : 3
            }
        },
    }
    if __name__ == '__main__':
        config['verbose'] = 2
    else:
        config['verbose'] = 0

    # These tests are slow, and it's really just doing the same thing three times, so
    # only do the first one when running via nosetests.
    if __name__ == '__main__':
        # Start by doing things manually:
        logger = piff.config.setup_logger(2)

        # Largely copied from Gary's fit_des.py, but using the Piff input_handler to
        # read the input files.
        stars, wcs, pointing = piff.Input.process(config['input'], logger=logger)
        if nstars is not None:
            stars = stars[:nstars]

        # Make model, force PSF centering
        model = piff.PixelGrid(scale=scale, size=size, interp=piff.Lanczos(3),
                               force_model_center=True, start_sigma=start_sigma,
                               logger=logger)

        # Interpolator will be zero-order polynomial.
        # Find u, v ranges
        interp = piff.BasisPolynomial(order=order, logger=logger)

        # Make a psf
        psf = piff.SimplePSF(model, interp)
        psf.fit(stars, wcs, pointing, logger=logger)

        # The difference between the images of the fitted stars and the originals should be
        # consistent with noise.  Keep track of how many don't meet that goal.
        n_bad = 0  # chisq/dof > 2
        n_marginal = 0  # chisq/dof > 1.1
        n_good = 0 # chisq/dof <= 1.1
        # Note: The 2 and 1.1 values here are very arbitrary!

        for s in psf.stars:
            fitted = psf.drawStar(s)
            orig_stamp = orig_image[fitted.image.bounds] - s['sky']
            fit_stamp = fitted.image

            x0 = int(s['x']+0.5)
            y0 = int(s['y']+0.5)
            b = galsim.BoundsI(x0-3,x0+3,y0-3,y0+3)
            #print('orig center = ',orig_stamp[b].array)
            #print('flux = ',orig_stamp.array.sum())
            #print('fit center = ',fit_stamp[b].array)
            #print('flux = ',fit_stamp.array.sum())
            flux = fitted.fit.flux
            #print('max diff/flux = ',np.max(np.abs(orig_stamp.array-fit_stamp.array))/flux)
            #np.testing.assert_almost_equal(fit_stamp.array/flux, orig_stamp.array/flux, decimal=2)
            weight = s.weight  # These should be 1/var_pix
            resid = fit_stamp - orig_stamp
            chisq = np.sum(resid.array**2 * weight.array)
            print('chisq = ',chisq)
            print('cf. star.chisq, dof = ',s.fit.chisq, s.fit.dof)
            assert abs(chisq - s.fit.chisq) < 1.e-3 * chisq
            if chisq > 2. * s.fit.dof:
                n_bad += 1
            elif chisq > 1.1 * s.fit.dof:
                n_marginal += 1
            else:
                n_good += 1

            # Check the convenience function that an end user would typically use
            offset = s.center_to_offset(s.fit.center)
            image = psf.draw(x=s['x'], y=s['y'], stamp_size=stamp_size,
                             flux=s.fit.flux, offset=offset)
            np.testing.assert_almost_equal(image.array, fit_stamp.array, decimal=4)

        print('n_good, marginal, bad = ',n_good,n_marginal,n_bad)
        # The real counts are 10 and 2.  So this says make sure any updates to the code don't make
        # things much worse.
        assert n_marginal <= 12
        assert n_bad <= 3

    # Use piffify function
    print('start piffify')
    piff.piffify(config)
    print('read stars')
    stars, wcs, pointing = piff.Input.process(config['input'])
    print('read psf')
    psf = piff.read(psf_file)
    stars = [psf.model.initialize(s) for s in stars]
    flux = stars[0].fit.flux
    offset = stars[0].center_to_offset(stars[0].fit.center)
    fit_stamp = psf.draw(x=stars[0]['x'], y=stars[0]['y'], stamp_size=stamp_size,
                         flux=flux, offset=offset)
    orig_stamp = orig_image[stars[0].image.bounds] - stars[0]['sky']
    # The first star happens to be a good one, so go ahead and test the arrays directly.
    np.testing.assert_almost_equal(fit_stamp.array/flux, orig_stamp.array/flux, decimal=2)

    # Test using the piffify executable
    with open('pixel_des.yaml','w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    if __name__ == '__main__':
        if os.path.exists(psf_file):
            os.remove(psf_file)
        piffify_exe = get_script_name('piffify')
        print('start piffify executable')
        p = subprocess.Popen( [piffify_exe, 'pixel_des.yaml'] )
        p.communicate()
        print('read stars')
        stars, wcs, pointing = piff.Input.process(config['input'])
        print('read psf')
        psf = piff.read(psf_file)
        stars = [psf.model.initialize(s) for s in stars]
        flux = stars[0].fit.flux
        offset = stars[0].center_to_offset(stars[0].fit.center)
        fit_stamp = psf.draw(x=stars[0]['x'], y=stars[0]['y'], stamp_size=stamp_size,
                             flux=flux, offset=offset)
        orig_stamp = orig_image[stars[0].image.bounds] - stars[0]['sky']
        np.testing.assert_almost_equal(fit_stamp.array/flux, orig_stamp.array/flux, decimal=2)
Exemple #17
0
def test_single_image():
    """Test the simple case of one image and one catalog.
    """
    # Make the image
    image = galsim.Image(2048, 2048, scale=0.26)

    # Where to put the stars.  Include some flagged and not used locations.
    x_list = [ 123.12, 345.98, 567.25, 1094.94, 924.15, 1532.74, 1743.11, 888.39, 1033.29, 1409.31 ]
    y_list = [ 345.43, 567.45, 1094.32, 924.29, 1532.92, 1743.83, 888.83, 1033.19, 1409.20, 123.11 ]
    flag_list = [ 0, 0, 12, 0, 0, 1, 0, 0, 0, 0 ]
    use_list = [ 1, 1, 1, 1, 1, 0, 1, 1, 0, 1 ]

    # Draw a Gaussian PSF at each location on the image.
    sigma = 1.3
    g1 = 0.23
    g2 = -0.17
    psf = galsim.Gaussian(sigma=sigma).shear(g1=g1, g2=g2)
    for x,y,flag,use in zip(x_list, y_list, flag_list, use_list):
        bounds = galsim.BoundsI(int(x-31), int(x+32), int(y-31), int(y+32))
        offset = galsim.PositionD( x-int(x)-0.5 , y-int(y)-0.5 )
        psf.drawImage(image=image[bounds], method='no_pixel', offset=offset)
        # corrupt the ones that are marked as flagged
        if flag:
            print('corrupting star at ',x,y)
            ar = image[bounds].array
            im_max = np.max(ar) * 0.2
            ar[ar > im_max] = im_max

    # Write out the image to a file
    image_file = os.path.join('data','simple_image.fits')
    image.write(image_file)

    # Write out the catalog to a file
    dtype = [ ('x','f8'), ('y','f8'), ('flag','i2'), ('use','i2') ]
    data = np.empty(len(x_list), dtype=dtype)
    data['x'] = x_list
    data['y'] = y_list
    data['flag'] = flag_list
    data['use'] = use_list
    cat_file = os.path.join('data','simple_cat.fits')
    fitsio.write(cat_file, data, clobber=True)

    # Use InputFiles to read these back in
    input = piff.InputFiles(image_file, cat_file)
    assert input.image_files == [ image_file ]
    assert input.cat_files == [ cat_file ]
    assert input.x_col == 'x'
    assert input.y_col == 'y'

    # Check image
    input.readImages()
    assert len(input.images) == 1
    np.testing.assert_equal(input.images[0].array, image.array)

    # Check catalog
    input.readStarCatalogs()
    assert len(input.cats) == 1
    np.testing.assert_equal(input.cats[0]['x'], x_list)
    np.testing.assert_equal(input.cats[0]['y'], y_list)

    # Repeat, using flag and use columns this time.
    input = piff.InputFiles(image_file, cat_file, flag_col='flag', use_col='use', stamp_size=48)
    assert input.flag_col == 'flag'
    assert input.use_col == 'use'
    input.readImages()
    input.readStarCatalogs()
    assert len(input.cats[0]) == 7

    # Make star data
    orig_stars = input.makeStars()
    assert len(orig_stars) == 7
    assert orig_stars[0].image.array.shape == (48,48)

    # Process the star data
    model = piff.Gaussian()
    interp = piff.Mean()
    fitted_stars = [ model.fit(star) for star in orig_stars ]
    interp.solve(fitted_stars)
    print('mean = ',interp.mean)

    # Check that the interpolation is what it should be
    target = piff.Star.makeTarget(x=1024, y=123) # Any position would work here.
    true_params = [ sigma, g1, g2 ]
    test_star = interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params, true_params, decimal=5)

    # Now test running it via the config parser
    psf_file = os.path.join('output','simple_psf.fits')
    config = {
        'input' : {
            'images' : image_file,
            'cats' : cat_file,
            'flag_col' : 'flag',
            'use_col' : 'use',
            'stamp_size' : 48
        },
        'psf' : {
            'model' : { 'type' : 'Gaussian' },
            'interp' : { 'type' : 'Mean' },
        },
        'output' : { 'file_name' : psf_file },
    }
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=3)
    else:
        logger = piff.config.setup_logger(verbose=1)
    orig_stars, wcs, pointing = piff.Input.process(config['input'], logger)

    # Use a SimplePSF to process the stars data this time.
    psf = piff.SimplePSF(model, interp)
    psf.fit(orig_stars, wcs, pointing, logger=logger)
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params, true_params, decimal=5)

    # Round trip to a file
    psf.write(psf_file, logger)
    psf = piff.read(psf_file, logger)
    assert type(psf.model) is piff.Gaussian
    assert type(psf.interp) is piff.Mean
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params, true_params, decimal=5)

    # Do the whole thing with the config parser
    os.remove(psf_file)

    piff.piffify(config, logger)
    psf = piff.read(psf_file)
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params, true_params, decimal=5)

    # Test using the piffify executable
    os.remove(psf_file)
    with open('simple.yaml','w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    piffify_exe = get_script_name('piffify')
    p = subprocess.Popen( [piffify_exe, 'simple.yaml'] )
    p.communicate()
    psf = piff.read(psf_file)
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params, true_params, decimal=5)

    # Test that we can make rho statistics
    min_sep = 1
    max_sep = 100
    bin_size = 0.1
    stats = piff.RhoStats(min_sep=min_sep, max_sep=max_sep, bin_size=bin_size)
    stats.compute(psf, orig_stars)

    rhos = [stats.rho1, stats.rho2, stats.rho3, stats.rho4, stats.rho5]
    for rho in rhos:
        # Test the range of separations
        radius = np.exp(rho.logr)
        # last bin can be one bigger than max_sep
        np.testing.assert_array_less(radius, np.exp(np.log(max_sep) + bin_size))
        np.testing.assert_array_less(min_sep, radius)
        np.testing.assert_array_almost_equal(np.diff(rho.logr), bin_size, decimal=5)

        # Test that the max absolute value of each rho isn't crazy
        np.testing.assert_array_less(np.abs(rho.xip), 1)

        # Check that each rho isn't precisely zero. This means the sum of abs > 0
        np.testing.assert_array_less(0, np.sum(np.abs(rho.xip)))

    # Test the plotting and writing
    rho_psf_file = os.path.join('output','simple_psf_rhostats.png')
    stats.write(rho_psf_file)

    # Test that we can make summary shape statistics, using HSM
    shapeStats = piff.ShapeHistogramsStats()
    shapeStats.compute(psf, orig_stars)

    # test their characteristics
    np.testing.assert_array_almost_equal(sigma, shapeStats.T, decimal=4)
    np.testing.assert_array_almost_equal(sigma, shapeStats.T_model, decimal=3)
    np.testing.assert_array_almost_equal(g1, shapeStats.g1, decimal=4)
    np.testing.assert_array_almost_equal(g1, shapeStats.g1_model, decimal=3)
    np.testing.assert_array_almost_equal(g2, shapeStats.g2, decimal=4)
    np.testing.assert_array_almost_equal(g2, shapeStats.g2_model, decimal=3)

    shape_psf_file = os.path.join('output','simple_psf_shapestats.png')
    shapeStats.write(shape_psf_file)

    # Test that we can use the config parser for both RhoStats and ShapeHistogramsStats
    config['output']['stats'] = [
        {
            'type': 'ShapeHistograms',
            'file_name': shape_psf_file
        },
        {
            'type': 'Rho',
            'file_name': rho_psf_file
        },
    ]

    os.remove(psf_file)
    os.remove(rho_psf_file)
    os.remove(shape_psf_file)
    piff.piffify(config)

    # Test using the piffify executable
    os.remove(psf_file)
    os.remove(rho_psf_file)
    os.remove(shape_psf_file)
    with open('simple.yaml','w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    piffify_exe = get_script_name('piffify')
    p = subprocess.Popen( [piffify_exe, 'simple.yaml'] )
    p.communicate()
Exemple #18
0
def test_des_image():
    """Test the whole process with a DES CCD.
    """
    import os
    import fitsio

    image_file = 'y1_test/DECam_00241238_01.fits.fz'
    cat_file = 'y1_test/DECam_00241238_01_psfcat_tb_maxmag_17.0_magcut_3.0_findstars.fits'
    orig_image = galsim.fits.read(image_file)
    psf_file = os.path.join('output', 'pixel_des_psf.fits')

    if __name__ == '__main__':
        # These match what Gary used in fit_des.py
        nstars = None
        scale = 0.15
        size = 41
    else:
        # These are faster and good enough for the unit tests.
        nstars = 25
        scale = 0.2
        size = 21
    stamp_size = 51

    # The configuration dict with the right input fields for the file we're using.
    start_sigma = 1.0 / 2.355  # TODO: Need to make this automatic somehow.
    config = {
        'input': {
            'images': image_file,
            'image_hdu': 1,
            'weight_hdu': 3,
            'badpix_hdu': 2,
            'cats': cat_file,
            'cat_hdu': 2,
            'x_col': 'XWIN_IMAGE',
            'y_col': 'YWIN_IMAGE',
            'sky_col': 'BACKGROUND',
            'stamp_size': stamp_size,
            'ra': 'TELRA',
            'dec': 'TELDEC',
            'gain': 'GAINA',
        },
        'output': {
            'file_name': psf_file,
        },
        'psf': {
            'model': {
                'type': 'PixelGrid',
                'scale': scale,
                'size': size,
                'start_sigma': start_sigma,
            },
            'interp': {
                'type': 'BasisPolynomial',
                'order': 2,
            },
        },
    }
    if __name__ == '__main__': config['verbose'] = 3

    # These tests are slow, and it's really just doing the same thing three times, so
    # only do the first one when running via nosetests.
    if True:
        # Start by doing things manually:
        if __name__ == '__main__':
            logger = piff.config.setup_logger(2)
        else:
            logger = None

        # Largely copied from Gary's fit_des.py, but using the Piff input_handler to
        # read the input files.
        stars, wcs, pointing = piff.Input.process(config['input'],
                                                  logger=logger)
        if nstars is not None:
            stars = stars[:nstars]

        # Make model, force PSF centering
        model = piff.PixelGrid(scale=scale,
                               size=size,
                               interp=piff.Lanczos(3),
                               force_model_center=True,
                               start_sigma=start_sigma,
                               logger=logger)

        # Interpolator will be zero-order polynomial.
        # Find u, v ranges
        interp = piff.BasisPolynomial(order=2, logger=logger)

        # Make a psf
        psf = piff.SimplePSF(model, interp)
        psf.fit(stars, wcs, pointing, logger=logger)

        # The difference between the images of the fitted stars and the originals should be
        # consistent with noise.  Keep track of how many don't meet that goal.
        n_bad = 0  # chisq/dof > 2
        n_marginal = 0  # chisq/dof > 1.1
        n_good = 0  # chisq/dof <= 1.1
        # Note: The 2 and 1.1 values here are very arbitrary!

        for s in psf.stars:
            fitted = psf.drawStar(s)
            orig_stamp = orig_image[fitted.image.bounds] - s['sky']
            fit_stamp = fitted.image

            x0 = int(s['x'] + 0.5)
            y0 = int(s['y'] + 0.5)
            b = galsim.BoundsI(x0 - 3, x0 + 3, y0 - 3, y0 + 3)
            #print('orig center = ',orig_stamp[b].array)
            #print('flux = ',orig_stamp.array.sum())
            #print('fit center = ',fit_stamp[b].array)
            #print('flux = ',fit_stamp.array.sum())
            flux = fitted.fit.flux
            #print('max diff/flux = ',np.max(np.abs(orig_stamp.array-fit_stamp.array))/flux)
            #np.testing.assert_almost_equal(fit_stamp.array/flux, orig_stamp.array/flux, decimal=2)
            weight = s.weight  # These should be 1/var_pix
            resid = fit_stamp - orig_stamp
            chisq = np.sum(resid.array**2 * weight.array)
            print('chisq = ', chisq)
            print('cf. star.chisq, dof = ', s.fit.chisq, s.fit.dof)
            assert abs(chisq - s.fit.chisq) < 1.e-3 * chisq
            if chisq > 2. * s.fit.dof:
                n_bad += 1
            elif chisq > 1.1 * s.fit.dof:
                n_marginal += 1
            else:
                n_good += 1

            # Check the convenience function that an end user would typically use
            offset = s.center_to_offset(s.fit.center)
            image = psf.draw(x=s['x'],
                             y=s['y'],
                             stamp_size=stamp_size,
                             flux=s.fit.flux,
                             offset=offset)
            np.testing.assert_almost_equal(image.array,
                                           fit_stamp.array,
                                           decimal=4)

        print('n_good, marginal, bad = ', n_good, n_marginal, n_bad)
        # The real counts are 10 and 2.  So this says make sure any updates to the code don't make
        # things much worse.
        assert n_marginal <= 12
        assert n_bad <= 3

    # Use piffify function
    if __name__ == '__main__':
        print('start piffify')
        piff.piffify(config)
        print('read stars')
        stars, wcs, pointing = piff.Input.process(config['input'])
        print('read psf')
        psf = piff.read(psf_file)
        stars = [psf.model.initialize(s) for s in stars]
        flux = stars[0].fit.flux
        offset = stars[0].center_to_offset(stars[0].fit.center)
        fit_stamp = psf.draw(x=stars[0]['x'],
                             y=stars[0]['y'],
                             stamp_size=stamp_size,
                             flux=flux,
                             offset=offset)
        orig_stamp = orig_image[stars[0].image.bounds] - stars[0]['sky']
        # The first star happens to be a good one, so go ahead and test the arrays directly.
        np.testing.assert_almost_equal(fit_stamp.array / flux,
                                       orig_stamp.array / flux,
                                       decimal=2)

    # Test using the piffify executable
    config['verbose'] = 0
    with open('pixel_des.yaml', 'w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    if __name__ == '__main__':
        if os.path.exists(psf_file):
            os.remove(psf_file)
        piffify_exe = get_script_name('piffify')
        print('start piffify executable')
        p = subprocess.Popen([piffify_exe, 'pixel_des.yaml'])
        p.communicate()
        print('read stars')
        stars, wcs, pointing = piff.Input.process(config['input'])
        print('read psf')
        psf = piff.read(psf_file)
        stars = [psf.model.initialize(s) for s in stars]
        flux = stars[0].fit.flux
        offset = stars[0].center_to_offset(stars[0].fit.center)
        fit_stamp = psf.draw(x=stars[0]['x'],
                             y=stars[0]['y'],
                             stamp_size=stamp_size,
                             flux=flux,
                             offset=offset)
        orig_stamp = orig_image[stars[0].image.bounds] - stars[0]['sky']
        np.testing.assert_almost_equal(fit_stamp.array / flux,
                                       orig_stamp.array / flux,
                                       decimal=2)
Exemple #19
0
def test_single_image():
    """Test the simple case of one image and one catalog.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(
            log_file='output/test_single_image.log')

    # Make the image
    image = galsim.Image(2048, 2048, scale=0.26)

    # Where to put the stars.  Include some flagged and not used locations.
    x_list = [
        123.12, 345.98, 567.25, 1094.94, 924.15, 1532.74, 1743.11, 888.39,
        1033.29, 1409.31
    ]
    y_list = [
        345.43, 567.45, 1094.32, 924.29, 1532.92, 1743.83, 888.83, 1033.19,
        1409.20, 123.11
    ]
    flag_list = [1, 1, 13, 1, 1, 4, 1, 1, 0, 1]

    # Draw a Gaussian PSF at each location on the image.
    sigma = 1.3
    g1 = 0.23
    g2 = -0.17
    psf = galsim.Gaussian(sigma=sigma).shear(g1=g1, g2=g2)
    for x, y, flag in zip(x_list, y_list, flag_list):
        bounds = galsim.BoundsI(int(x - 31), int(x + 32), int(y - 31),
                                int(y + 32))
        offset = galsim.PositionD(x - int(x) - 0.5, y - int(y) - 0.5)
        psf.drawImage(image=image[bounds], method='no_pixel', offset=offset)
        # corrupt the ones that are marked as flagged
        if flag & 4:
            print('corrupting star at ', x, y)
            ar = image[bounds].array
            im_max = np.max(ar) * 0.2
            ar[ar > im_max] = im_max
    image.addNoise(
        galsim.GaussianNoise(rng=galsim.BaseDeviate(1234), sigma=1e-6))

    # Write out the image to a file
    image_file = os.path.join('output', 'simple_image.fits')
    image.write(image_file)

    # Write out the catalog to a file
    dtype = [('x', 'f8'), ('y', 'f8'), ('flag', 'i2')]
    data = np.empty(len(x_list), dtype=dtype)
    data['x'] = x_list
    data['y'] = y_list
    data['flag'] = flag_list
    cat_file = os.path.join('output', 'simple_cat.fits')
    fitsio.write(cat_file, data, clobber=True)

    # Use InputFiles to read these back in
    config = {'image_file_name': image_file, 'cat_file_name': cat_file}
    input = piff.InputFiles(config, logger=logger)
    assert input.image_file_name == [image_file]
    assert input.cat_file_name == [cat_file]

    # Check image
    assert input.nimages == 1
    image1, _, image_pos, _, _, _ = input.getRawImageData(0)
    np.testing.assert_equal(image1.array, image.array)

    # Check catalog
    np.testing.assert_equal([pos.x for pos in image_pos], x_list)
    np.testing.assert_equal([pos.y for pos in image_pos], y_list)

    # Repeat, using flag columns this time.
    config = {
        'image_file_name': image_file,
        'cat_file_name': cat_file,
        'flag_col': 'flag',
        'use_flag': '1',
        'skip_flag': '4',
        'stamp_size': 48
    }
    input = piff.InputFiles(config, logger=logger)
    assert input.nimages == 1
    _, _, image_pos, _, _, _ = input.getRawImageData(0)
    assert len(image_pos) == 7

    # Make star data
    orig_stars = input.makeStars()
    assert len(orig_stars) == 7
    assert orig_stars[0].image.array.shape == (48, 48)

    # Process the star data
    # can only compare to truth if include_pixel=False
    model = piff.Gaussian(fastfit=True, include_pixel=False)
    interp = piff.Mean()
    fitted_stars = [model.fit(model.initialize(star)) for star in orig_stars]
    interp.solve(fitted_stars)
    print('mean = ', interp.mean)

    # Check that the interpolation is what it should be
    # Any position would work here.
    chipnum = 0
    x = 1024
    y = 123
    orig_wcs = input.getWCS()[chipnum]
    orig_pointing = input.getPointing()
    image_pos = galsim.PositionD(x, y)
    world_pos = piff.StarData.calculateFieldPos(image_pos, orig_wcs,
                                                orig_pointing)
    u, v = world_pos.x, world_pos.y
    stamp_size = config['stamp_size']

    target = piff.Star.makeTarget(x=x,
                                  y=y,
                                  u=u,
                                  v=v,
                                  wcs=orig_wcs,
                                  stamp_size=stamp_size,
                                  pointing=orig_pointing)
    true_params = [sigma, g1, g2]
    test_star = interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # Check default values of options
    psf = piff.SimplePSF(model, interp)
    assert psf.chisq_thresh == 0.1
    assert psf.max_iter == 30
    assert psf.outliers == None
    assert psf.extra_interp_properties == []

    # Now test running it via the config parser
    psf_file = os.path.join('output', 'simple_psf.fits')
    config = {
        'input': {
            'image_file_name': image_file,
            'cat_file_name': cat_file,
            'flag_col': 'flag',
            'use_flag': 1,
            'skip_flag': 4,
            'stamp_size': stamp_size
        },
        'psf': {
            'model': {
                'type': 'Gaussian',
                'fastfit': True,
                'include_pixel': False
            },
            'interp': {
                'type': 'Mean'
            },
            'max_iter': 10,
            'chisq_thresh': 0.2,
        },
        'output': {
            'file_name': psf_file
        },
    }
    orig_stars, wcs, pointing = piff.Input.process(config['input'], logger)

    # Use a SimplePSF to process the stars data this time.
    interp = piff.Mean()
    psf = piff.SimplePSF(model, interp, max_iter=10, chisq_thresh=0.2)
    assert psf.chisq_thresh == 0.2
    assert psf.max_iter == 10

    psf.fit(orig_stars, wcs, pointing, logger=logger)
    test_star = psf.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # test that drawStar and drawStarList work
    test_star = psf.drawStar(target)
    test_star_list = psf.drawStarList([target])[0]
    np.testing.assert_equal(test_star.fit.params, test_star_list.fit.params)
    np.testing.assert_equal(test_star.image.array, test_star_list.image.array)

    # test copy_image property of drawStar and draw
    for draw in [psf.drawStar, psf.model.draw]:
        target_star_copy = psf.interp.interpolate(
            piff.Star(target.data.copy(), target.fit.copy()))
        # interp is so that when we do psf.model.draw we have fit.params to work with

        test_star_copy = draw(target_star_copy, copy_image=True)
        test_star_nocopy = draw(target_star_copy, copy_image=False)
        # if we modify target_star_copy, then test_star_nocopy should be modified,
        # but not test_star_copy
        target_star_copy.image.array[0, 0] = 23456
        assert test_star_nocopy.image.array[
            0, 0] == target_star_copy.image.array[0, 0]
        assert test_star_copy.image.array[0,
                                          0] != target_star_copy.image.array[0,
                                                                             0]
        # however the other pixels SHOULD still be all the same value
        assert test_star_nocopy.image.array[
            1, 1] == target_star_copy.image.array[1, 1]
        assert test_star_copy.image.array[1,
                                          1] == target_star_copy.image.array[1,
                                                                             1]

    # test that draw works
    test_image = psf.draw(x=target['x'],
                          y=target['y'],
                          stamp_size=config['input']['stamp_size'],
                          flux=target.fit.flux,
                          offset=target.fit.center)
    # this image should be the same values as test_star
    assert test_image == test_star.image
    # test that draw does not copy the image
    image_ref = psf.draw(x=target['x'],
                         y=target['y'],
                         stamp_size=config['input']['stamp_size'],
                         flux=target.fit.flux,
                         offset=target.fit.center,
                         image=test_image)
    image_ref.array[0, 0] = 123456789
    assert test_image.array[0, 0] == image_ref.array[0, 0]
    assert test_star.image.array[0, 0] != test_image.array[0, 0]
    assert test_star.image.array[1, 1] == test_image.array[1, 1]

    # Round trip to a file
    psf.write(psf_file, logger)
    psf2 = piff.read(psf_file, logger)
    assert type(psf2.model) is piff.Gaussian
    assert type(psf2.interp) is piff.Mean
    assert psf2.chisq == psf.chisq
    assert psf2.last_delta_chisq == psf.last_delta_chisq
    assert psf2.chisq_thresh == psf.chisq_thresh
    assert psf2.max_iter == psf.max_iter
    assert psf2.dof == psf.dof
    assert psf2.nremoved == psf.nremoved
    test_star = psf2.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # Do the whole thing with the config parser
    os.remove(psf_file)

    piff.piffify(config, logger)
    psf3 = piff.read(psf_file)
    assert type(psf3.model) is piff.Gaussian
    assert type(psf3.interp) is piff.Mean
    assert psf3.chisq == psf.chisq
    assert psf3.last_delta_chisq == psf.last_delta_chisq
    assert psf3.chisq_thresh == psf.chisq_thresh
    assert psf3.max_iter == psf.max_iter
    assert psf3.dof == psf.dof
    assert psf3.nremoved == psf.nremoved
    test_star = psf3.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # Test using the piffify executable
    os.remove(psf_file)
    # This would be simpler as a direct assignment, but this once, test the way you would set
    # this from the command line, which would call parse_variables.
    piff.config.parse_variables(config, ['verbose=0'], logger=logger)
    #config['verbose'] = 0
    with open('simple.yaml', 'w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    config2 = piff.config.read_config('simple.yaml')
    assert config == config2
    piffify_exe = get_script_name('piffify')
    p = subprocess.Popen([piffify_exe, 'simple.yaml'])
    p.communicate()
    psf4 = piff.read(psf_file)
    assert type(psf4.model) is piff.Gaussian
    assert type(psf4.interp) is piff.Mean
    assert psf4.chisq == psf.chisq
    assert psf4.last_delta_chisq == psf.last_delta_chisq
    assert psf4.chisq_thresh == psf.chisq_thresh
    assert psf4.max_iter == psf.max_iter
    assert psf4.dof == psf.dof
    assert psf4.nremoved == psf.nremoved
    test_star = psf4.interp.interpolate(target)
    np.testing.assert_almost_equal(test_star.fit.params,
                                   true_params,
                                   decimal=4)

    # With very low max_iter, we hit the warning about non-convergence
    config['psf']['max_iter'] = 1
    with CaptureLog(level=1) as cl:
        piff.piffify(config, cl.logger)
    assert 'PSF fit did not converge' in cl.output
Exemple #20
0
def setup():
    np.random.seed(42)
    if __name__ == '__main__':
        nimages = 20
        stars_per_image = 500
    else:
        nimages = 2
        stars_per_image = 50

    # Delete any existing image files
    for image_file in glob.glob(os.path.join('output','test_mean_image_*.fits')):
        os.remove(image_file)

    for k in range(nimages):
        print(k)
        image = galsim.Image(2048, 2048, scale=0.26)

        x_list = [np.random.uniform(0, 2048)]
        y_list = [np.random.uniform(0, 2048)]
        i=0
        while i < stars_per_image:
            x = np.random.uniform(0, 2048)
            y = np.random.uniform(0, 2048)
            D = np.sqrt((np.array(x_list)-x)**2 + (np.array(y_list)-y)**2)
            #avoid 2 stars on the same stamp
            if np.all(D > 60):
                x_list.append(x)
                y_list.append(y)
                i+=1

        coord = np.array([x_list,y_list]).T
        params = make_average(coord=coord)
        psfs = []
        for x, y, hlr, g1, g2 in zip(x_list, y_list, params['hlr'], params['g1'], params['g2']):
            psf = galsim.Kolmogorov(half_light_radius=hlr, flux=1.).shear(g1=g1, g2=g2)
            bounds = galsim.BoundsI(int(x-21), int(x+22), int(y-21), int(y+22))
            if not image.bounds.includes(bounds): continue
            offset = galsim.PositionD( x-int(x)-0.5 , y-int(y)-0.5 )
            psf.drawImage(image=image[bounds], method='no_pixel', offset=offset)

        image_file = os.path.join('output','test_mean_image_%02i.fits'%k)
        image.write(image_file)

        dtype = [ ('x','f8'), ('y','f8') ]
        data = np.empty(len(x_list), dtype=dtype)
        data['x'] = x_list
        data['y'] = y_list
        cat_file = os.path.join('output','test_mean_cat_%02i.fits'%k)
        fitsio.write(cat_file, data, clobber=True)

        image_file = os.path.join('output','test_mean_image_%02i.fits'%k)
        cat_file = os.path.join('output','test_mean_cat_%02i.fits'%k)
        psf_file = os.path.join('output','test_mean_%02i.piff'%k)

        config = {
            'input' : {
                'image_file_name' : image_file,
                'cat_file_name' : cat_file,
                'stamp_size' : 48
            },
            'psf' : {
                'model' : { 'type' : 'Kolmogorov',
                            'fastfit': True,
                            'include_pixel': False },
                'interp' : { 'type' : 'Polynomial',
                             'order' : 2}
            },
            'output' : {
                'file_name' : psf_file
            }
        }
        if __name__ == '__main__':
            config['verbose'] = 2
        else:
            config['verbose'] = 0
        piff.piffify(config)
Exemple #21
0
def setup():
    np.random.seed(42)
    if __name__ == '__main__':
        nimages = 20
        stars_per_image = 500
    else:
        nimages = 2
        stars_per_image = 50

    # Delete any existing image files
    for image_file in glob.glob(
            os.path.join('output', 'test_mean_image_*.fits')):
        os.remove(image_file)

    for k in range(nimages):
        print(k)
        image = galsim.Image(2048, 2048, scale=0.26)

        x_list = [np.random.uniform(0, 2048)]
        y_list = [np.random.uniform(0, 2048)]
        i = 0
        while i < stars_per_image:
            x = np.random.uniform(0, 2048)
            y = np.random.uniform(0, 2048)
            D = np.sqrt((np.array(x_list) - x)**2 + (np.array(y_list) - y)**2)
            #avoid 2 stars on the same stamp
            if np.all(D > 60):
                x_list.append(x)
                y_list.append(y)
                i += 1

        coord = np.array([x_list, y_list]).T
        params = make_average(coord=coord)
        psfs = []
        for x, y, hlr, g1, g2 in zip(x_list, y_list, params['hlr'],
                                     params['g1'], params['g2']):
            psf = galsim.Kolmogorov(half_light_radius=hlr,
                                    flux=1.).shear(g1=g1, g2=g2)
            bounds = galsim.BoundsI(int(x - 21), int(x + 22), int(y - 21),
                                    int(y + 22))
            if not image.bounds.includes(bounds): continue
            offset = galsim.PositionD(x - int(x) - 0.5, y - int(y) - 0.5)
            psf.drawImage(image=image[bounds],
                          method='no_pixel',
                          offset=offset)

        image_file = os.path.join('output', 'test_mean_image_%02i.fits' % k)
        image.write(image_file)

        dtype = [('x', 'f8'), ('y', 'f8')]
        data = np.empty(len(x_list), dtype=dtype)
        data['x'] = x_list
        data['y'] = y_list
        cat_file = os.path.join('output', 'test_mean_cat_%02i.fits' % k)
        fitsio.write(cat_file, data, clobber=True)

        image_file = os.path.join('output', 'test_mean_image_%02i.fits' % k)
        cat_file = os.path.join('output', 'test_mean_cat_%02i.fits' % k)
        psf_file = os.path.join('output', 'test_mean_%02i.piff' % k)

        config = {
            'input': {
                'image_file_name': image_file,
                'cat_file_name': cat_file,
                'stamp_size': 48
            },
            'psf': {
                'model': {
                    'type': 'Kolmogorov',
                    'fastfit': True,
                    'include_pixel': False
                },
                'interp': {
                    'type': 'Polynomial',
                    'order': 2
                }
            },
            'output': {
                'file_name': psf_file
            }
        }
        if __name__ == '__main__':
            config['verbose'] = 2
        else:
            config['verbose'] = 0
        piff.piffify(config)
Exemple #22
0
def test_hsmcatalog():
    """Test HSMCatalog stats type.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(
            log_file='output/test_hsmcatalog.log')

    image_file = os.path.join('output', 'test_stats_image.fits')
    cat_file = os.path.join('output', 'test_stats_cat.fits')
    psf_file = os.path.join('output', 'test_starstats.fits')
    hsm_file = os.path.join('output', 'test_hsmcatalog.fits')
    config = {
        'input': {
            'image_file_name': image_file,
            'cat_file_name': cat_file,
            'stamp_size': 48,
            'reserve_frac': 0.2,
            'seed': 123
        },
        'psf': {
            'model': {
                'type': 'Gaussian',
                'fastfit': True,
                'include_pixel': False
            },
            'interp': {
                'type': 'Mean'
            },
        },
        'output': {
            'file_name': psf_file,
            'stats': [{
                'type': 'HSMCatalog',
                'file_name': hsm_file,
            }]
        }
    }
    piff.piffify(config, logger)
    assert os.path.isfile(hsm_file)

    data = fitsio.read(hsm_file)
    for col in [
            'ra', 'dec', 'x', 'y', 'u', 'v', 'T_data', 'g1_data', 'g2_data',
            'T_model', 'g1_model', 'g2_model', 'flux', 'reserve'
    ]:
        assert len(data[col]) == 10
    true_data = fitsio.read(cat_file)

    np.testing.assert_allclose(data['x'], true_data['x'])
    np.testing.assert_allclose(data['y'], true_data['y'])
    np.testing.assert_allclose(data['flux'], 123.45, atol=0.001)
    print('reserve = ', data['reserve'])
    print('nreserve = ', np.sum(data['reserve']))
    print('ntot = ', len(data['reserve']))
    assert np.sum(data['reserve']) == int(0.2 * len(data['reserve']))
    np.testing.assert_allclose(data['T_model'], data['T_data'], rtol=1.e-4)
    np.testing.assert_allclose(data['g1_model'], data['g1_data'], rtol=1.e-4)
    np.testing.assert_allclose(data['g2_model'], data['g2_data'], rtol=1.e-4)

    image = galsim.fits.read(image_file)
    world = [
        image.wcs.toWorld(galsim.PositionD(x, y))
        for x, y in zip(data['x'], data['y'])
    ]
    np.testing.assert_allclose(data['ra'], [w.ra.deg for w in world],
                               rtol=1.e-4)
    np.testing.assert_allclose(data['dec'], [w.dec.deg for w in world],
                               rtol=1.e-4)

    # Repeat with non-Celestial WCS
    wcs = galsim.AffineTransform(0.26, 0.05, -0.08, -0.24,
                                 galsim.PositionD(1024, 1024))
    config['input']['wcs'] = wcs
    piff.piffify(config, logger)
    data = fitsio.read(hsm_file)
    np.testing.assert_array_equal(data['ra'], 0.)
    np.testing.assert_array_equal(data['dec'], 0.)
    world = [
        wcs.toWorld(galsim.PositionD(x, y))
        for x, y in zip(data['x'], data['y'])
    ]
    np.testing.assert_allclose(data['u'], [w.x for w in world], rtol=1.e-4)
    np.testing.assert_allclose(data['v'], [w.y for w in world], rtol=1.e-4)

    # Use class directly, rather than through config.
    psf = piff.PSF.read(psf_file)
    stars, _, _ = piff.Input.process(config['input'])
    hsmcat = piff.stats.HSMCatalogStats()
    with np.testing.assert_raises(RuntimeError):
        hsmcat.write('dummy')  # Cannot write before compute
    hsmcat.compute(psf, stars)
    hsm_file2 = os.path.join('output', 'test_hsmcatalog2.fits')
    with np.testing.assert_raises(ValueError):
        hsmcat.write()  # Must supply file_name if not given in constructor
    hsmcat.write(hsm_file2)
    data2 = fitsio.read(hsm_file2)
    for key in data.dtype.names:
        np.testing.assert_allclose(data2[key], data[key], rtol=1.e-5)
Exemple #23
0
def test_rhostats_config():
    """Test running stats through a config file.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(log_file='output/test_rhostats_config.log')

    image_file = os.path.join('output','test_stats_image.fits')
    cat_file = os.path.join('output','test_stats_cat.fits')
    psf_file = os.path.join('output','test_rhostats.fits')
    rho_file = os.path.join('output','test_rhostats.pdf')
    config = {
        'input' : {
            'image_file_name' : image_file,
            'cat_file_name' : cat_file,
            'stamp_size' : 48
        },
        'psf' : {
            'model' : { 'type' : 'Gaussian',
                        'fastfit': True,
                        'include_pixel': False },
            'interp' : { 'type' : 'Mean' },
        },
        'output' : {
            'file_name' : psf_file,
            'stats' : {  # Note: stats doesn't have to be a list.
                'type': 'Rho',
                'file_name': rho_file
            }
        },
    }
    piff.piffify(config, logger)
    assert os.path.isfile(rho_file)

    # repeat with plotify function
    os.remove(rho_file)
    piff.plotify(config, logger)
    assert os.path.isfile(rho_file)

    # Test rho statistics directly.
    min_sep = 1
    max_sep = 100
    bin_size = 0.1
    psf = piff.read(psf_file)
    orig_stars, wcs, pointing = piff.Input.process(config['input'], logger)
    stats = piff.RhoStats(min_sep=min_sep, max_sep=max_sep, bin_size=bin_size)
    stats.compute(psf, orig_stars)

    rhos = [stats.rho1, stats.rho2, stats.rho3, stats.rho4, stats.rho5]
    for rho in rhos:
        # Test the range of separations
        radius = np.exp(rho.logr)
        np.testing.assert_array_less(radius, max_sep)
        np.testing.assert_array_less(min_sep, radius)
        # bin_size is reduced slightly to get integer number of bins
        assert rho.bin_size < bin_size
        assert np.isclose(rho.bin_size, bin_size, rtol=0.1)
        np.testing.assert_array_almost_equal(np.diff(rho.logr), rho.bin_size, decimal=5)

        # Test that the max absolute value of each rho isn't crazy
        np.testing.assert_array_less(np.abs(rho.xip), 1)

        # # Check that each rho isn't precisely zero. This means the sum of abs > 0
        np.testing.assert_array_less(0, np.sum(np.abs(rho.xip)))

    # Test using the piffify executable
    os.remove(rho_file)
    config['verbose'] = 0
    with open('rho.yaml','w') as f:
        f.write(yaml.dump(config, default_flow_style=False))
    piffify_exe = get_script_name('piffify')
    p = subprocess.Popen( [piffify_exe, 'rho.yaml'] )
    p.communicate()
    assert os.path.isfile(rho_file)

    # Test using the plotify executable
    os.remove(rho_file)
    plotify_exe = get_script_name('plotify')
    p = subprocess.Popen( [plotify_exe, 'rho.yaml'] )
    p.communicate()
    assert os.path.isfile(rho_file)

    # test running plotify with dir in config, with no logger, and with a modules specification.
    # (all to improve test coverage)
    config['output']['dir'] = '.'
    config['modules'] = [ 'custom_wcs' ]
    os.remove(rho_file)
    piff.plotify(config)
    assert os.path.isfile(rho_file)
Exemple #24
0
def test_bad_hsm():
    """Test that stats don't break when all stars end up being flagged with hsm errors.
    """
    image_file = os.path.join('input', 'DECam_00241238_01.fits.fz')
    cat_file = os.path.join(
        'input',
        'DECam_00241238_01_psfcat_tb_maxmag_17.0_magcut_3.0_findstars.fits')
    psf_file = os.path.join('output', 'bad_hsm.fits')

    twodhist_file = os.path.join('output', 'bad_hsm_twod.pdf')
    whisker_file = os.path.join('output', 'bad_hsm_whisk.pdf')
    rho_file = os.path.join('output', 'bad_hsm_rho.pdf')
    shape_file = os.path.join('output', 'bad_hsm_shape.pdf')
    star_file = os.path.join('output', 'bad_hsm_star.pdf')
    hsm_file = os.path.join('output', 'bad_hsm_hsm.fits')

    stamp_size = 25

    # The configuration dict with the right input fields for the file we're using.
    config = {
        'input': {
            'nstars': 8,
            'image_file_name': image_file,
            'image_hdu': 1,
            'weight_hdu': 3,
            'badpix_hdu': 2,
            'cat_file_name': cat_file,
            'cat_hdu': 2,
            # These next two are intentionally backwards.  The PixelGrid will find some kind
            # of solution, but it will be complex garbage, and hsm will fail for them.
            'x_col': 'YWIN_IMAGE',
            'y_col': 'XWIN_IMAGE',
            'sky_col': 'BACKGROUND',
            'stamp_size': stamp_size,
            'ra': 'TELRA',
            'dec': 'TELDEC',
            'gain': 'GAINA',
        },
        'output': {
            'file_name':
            psf_file,
            'stats': [
                {
                    'type': 'TwoDHist',
                    'file_name': twodhist_file,
                },
                {
                    'type': 'Whisker',
                    'file_name': whisker_file,
                },
                {  # Note: stats doesn't have to be a list.
                    'type': 'Rho',
                    'file_name': rho_file
                },
                {
                    'type': 'ShapeHist',
                    'file_name': shape_file,
                },
                {
                    'type': 'Star',
                    'file_name': star_file,
                },
                {
                    'type': 'HSMCatalog',
                    'file_name': hsm_file,
                },
            ],
        },
        'psf': {
            'model': {
                'type': 'PixelGrid',
                'scale': 0.3,
                'size': 10,
            },
            'interp': {
                'type': 'Mean'
            },
            'outliers': {
                'type': 'Chisq',
                'nsigma':
                1.e-3,  # This will throw out all but 1, which adds an additional
                # test of Star stats when nstars < nplot
            }
        },
    }
    if __name__ == '__main__':
        logger = piff.config.setup_logger(1)
    else:
        config['verbose'] = 0
        logger = None

    for f in [twodhist_file, rho_file, shape_file, star_file, hsm_file]:
        if os.path.exists(f):
            os.remove(f)

    piff.piffify(config, logger=logger)

    for f in [twodhist_file, rho_file, shape_file, star_file, hsm_file]:
        assert os.path.exists(f)
Exemple #25
0
def test_starstats_config():
    """Test running stats through a config file.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(log_file='output/test_starstats_config.log')

    image_file = os.path.join('output','test_stats_image.fits')
    cat_file = os.path.join('output','test_stats_cat.fits')
    psf_file = os.path.join('output','test_starstats.fits')
    star_file = os.path.join('output', 'test_starstats.pdf')
    star_noadjust_file = os.path.join('output', 'test_starstats_noadjust.pdf')
    config = {
        'input' : {
            'image_file_name' : image_file,
            'cat_file_name' : cat_file,
            'stamp_size' : 48
        },
        'psf' : {
            'model' : { 'type' : 'Gaussian',
                        'fastfit': True,
                        'include_pixel': False },
            'interp' : { 'type' : 'Mean' },
        },
        'output' : {
            'file_name' : psf_file,
            'stats' : [
                {
                    'type': 'Star',
                    'file_name': star_file,
                    'number_plot': 5,
                    'adjust_stars': True,
                }
            ]
        }
    }
    piff.piffify(config, logger)
    assert os.path.isfile(star_file)

    # repeat with plotify function
    os.remove(star_file)
    piff.plotify(config, logger)
    assert os.path.isfile(star_file)

    # check default number_plot
    psf = piff.read(psf_file)
    starStats = piff.StarStats()
    orig_stars, wcs, pointing = piff.Input.process(config['input'], logger)
    starStats.compute(psf, orig_stars)
    assert starStats.number_plot == len(starStats.stars)
    assert starStats.number_plot == len(starStats.models)
    assert starStats.number_plot == len(starStats.indices)
    np.testing.assert_array_equal(starStats.stars[2].image.array,
                                  orig_stars[starStats.indices[2]].image.array)

    # check number_plot = 6
    starStats = piff.StarStats(number_plot=6)
    starStats.compute(psf, orig_stars)
    assert len(starStats.stars) == 6

    # check number_plot >> len(stars)
    starStats = piff.StarStats(number_plot=1000000)
    starStats.compute(psf, orig_stars)
    assert len(starStats.stars) == len(orig_stars)
    # if use all stars, no randomness
    np.testing.assert_array_equal(starStats.stars[3].image.array, orig_stars[3].image.array)
    np.testing.assert_array_equal(starStats.indices, np.arange(len(orig_stars)))

    # check number_plot = 0
    starStats = piff.StarStats(number_plot=0)
    starStats.compute(psf, orig_stars)
    assert len(starStats.stars) == len(orig_stars)
    # if use all stars, no randomness
    np.testing.assert_array_equal(starStats.stars[3].image.array, orig_stars[3].image.array)
    np.testing.assert_array_equal(starStats.indices, np.arange(len(orig_stars)))

    # rerun with adjust stars and see if it did the right thing
    # first with starstats == False
    starStats = piff.StarStats(number_plot=0, adjust_stars=False)
    starStats.compute(psf, orig_stars, logger=logger)
    fluxs_noadjust = np.array([s.fit.flux for s in starStats.stars])
    ds_noadjust = np.array([s.fit.center for s in starStats.stars])
    # check that fluxes 1
    np.testing.assert_array_equal(fluxs_noadjust, 1)
    # check that ds are 0
    np.testing.assert_array_equal(ds_noadjust, 0)

    # now with starstats == True
    starStats = piff.StarStats(number_plot=0, adjust_stars=True)
    starStats.compute(psf, orig_stars, logger=logger)
    fluxs_adjust = np.array([s.fit.flux for s in starStats.stars])
    ds_adjust = np.array([s.fit.center for s in starStats.stars])
    # copy the right values from setup()
    dx = 0.31
    dy = -0.32
    flux = 123.45
    # compare fluxes
    np.testing.assert_allclose(fluxs_adjust, flux, rtol=1e-4)
    # compare dx and dy, keeping in mind that ds_adjust is dx/y * 0.26 (scale)
    dx_adjust = ds_adjust[:, 0] / 0.26
    dy_adjust = ds_adjust[:, 1] / 0.26
    np.testing.assert_allclose(dx_adjust, dx, rtol=1e-4)
    np.testing.assert_allclose(dy_adjust, dy, rtol=1e-4)

    # do once with adjust_stars = False to graphically demonstrate
    config['output']['stats'][0]['file_name'] = star_noadjust_file
    config['output']['stats'][0]['adjust_stars'] = False
    piff.plotify(config, logger)
    assert os.path.isfile(star_noadjust_file)
Exemple #26
0
def test_shapestats_config():
    """Test running stats through a config file.
    """
    if __name__ == '__main__':
        logger = piff.config.setup_logger(verbose=2)
    else:
        logger = piff.config.setup_logger(log_file='output/test_shapestats_config.log')

    image_file = os.path.join('output','test_stats_image.fits')
    cat_file = os.path.join('output','test_stats_cat.fits')
    psf_file = os.path.join('output','test_shapestats.fits')
    shape_file = os.path.join('output','test_shapestats.pdf')
    config = {
        'input' : {
            'image_file_name' : image_file,
            'cat_file_name' : cat_file,
            'stamp_size' : 48
        },
        'psf' : {
            'model' : { 'type' : 'Gaussian',
                        'fastfit': True,
                        'include_pixel': False },
            'interp' : { 'type' : 'Mean' },
        },
        'output' : {
            'file_name' : psf_file,
            'stats' : [
                {
                    'type': 'ShapeHist',
                    'file_name': shape_file
                },
            ]
        },
    }
    piff.piffify(config, logger)
    assert os.path.isfile(shape_file)

    # repeat with plotify function
    os.remove(shape_file)
    piff.plotify(config, logger)
    assert os.path.isfile(shape_file)

    # Test ShapeHistStats directly
    psf = piff.read(psf_file)
    shapeStats = piff.ShapeHistStats(nbins=5)  # default is sqrt(nstars)
    orig_stars, wcs, pointing = piff.Input.process(config['input'], logger)
    with np.testing.assert_raises(RuntimeError):
        shapeStats.write()  # Cannot write before compute
    shapeStats.compute(psf, orig_stars)
    shapeStats.plot(histtype='bar', log=True)  # can supply additional args for matplotlib

    # test their characteristics
    sigma = 1.3  # (copied from setup())
    T = 2*sigma**2
    g1 = 0.23
    g2 = -0.17
    np.testing.assert_array_almost_equal(T, shapeStats.T, decimal=4)
    np.testing.assert_array_almost_equal(T, shapeStats.T_model, decimal=3)
    np.testing.assert_array_almost_equal(g1, shapeStats.g1, decimal=4)
    np.testing.assert_array_almost_equal(g1, shapeStats.g1_model, decimal=3)
    np.testing.assert_array_almost_equal(g2, shapeStats.g2, decimal=4)
    np.testing.assert_array_almost_equal(g2, shapeStats.g2_model, decimal=3)