Sample Usage

The following assumes an interactive Python session (such as an iPython session or Jupyter notebook).

Read an image from a FITS file, read a model description from an Imfit-format text file, and then fit the model to the data:

from astropy.io import fits
import pyimfit


# 1. A simple fit to an image (no PSF or mask)

imageFile = "<path-to-FITS-file-directory>/ic3478rss_256.fits"
imfitConfigFile = "<path-to-config-file-directory>/config_exponential_ic3478_256.dat"

# read in image data
image_data = fits.getdata(imageFile)

# construct model (ModelDescription object) from config file
model_desc = pyimfit.ModelDescription.load(configFile)

# create an Imfit object, using the previously loaded model configuration
imfit_fitter = pyimfit.Imfit(model_desc)

# load the image data and image characteristics and do a standard fit
# (using default chi^2 statistics and Levenberg-Marquardt solver)
fit_result = imfit_fitter.fit(image_data, gain=4.725, read_noise=4.3, original_sky=130.14)
print(fit_result)

# check the fit and print the resulting best-fit parameter values
if imfit_fitter.fitConverged is True:
    print("Fit converged: chi^2 = {0}, reduced chi^2 = {1}".format(imfit_fitter.fitStatistic,
        imfit_fitter.reducedFitStatistic))
    print("Best-fit parameter values:")
    print(imfit_fitter.getRawParameters())


# 2. Same basic model and data, but now with PSF convolution and a mask

# Load PSF image from FITS file, then create Imfit fitter with model + PSF
psfImageFile = "<path-to-FITS-file-directory>/psf_moffat_35.fits"
psf_image_data = fits.getdata(psfImageFile)

imfit_fitter2 = pyimfit.Imfit(model_desc, psf=psf_image_data)

# load the image data and characteristics, and also a mask image, but don't run the fit yet
maskImageFile = "<path-to-FITS-file-directory>/mask.fits"
mask_image_data = fits.getdata(maskImageFile)

imfit_fitter2.loadData(image_data, mask=mask_image_data, gain=4.725, read_noise=4.3, original_sky=130.14)

# do the fit, using Nelder-Mead simplex (instead of default Levenberg-Marquardt) as the solver
fit_result2 = imfit_fitter2.doFit(solver="NM")

You can also programmatically construct a model within Python (rather than having to read it from a text file):

# define a function for making a simple bulge+disk model, where both components
# share the same central coordinate (SimpleModelDescription class)
def galaxy_model(x0, y0, PA_bulge, ell_bulge, n, I_e, r_e, PA_disk, ell_disk, I_0, h):
    model = pyimfit.SimpleModelDescription()
    # define the limits on X0 and Y0 as +/-10 pixels relative to initial values
    model.x0.setValue(x0, [x0 - 10, x0 + 10])
    model.y0.setValue(y0, [y0 - 10, y0 + 10])

    bulge = pyimfit.make_imfit_function('Sersic', label='bulge')
    bulge.PA.setValue(PA_bulge, [0, 180])
    bulge.ell.setValue(ell_bulge, [0, 1])
    bulge.I_e.setValue(I_e, [0, 10*I_e])
    bulge.r_e.setValue(r_e, [0, 10*r_e])
    bulge.n.setValue(n, [0.5, 5])

    disk = pyimfit.make_imfit_function('Exponential', label='disk')
    disk.PA.setValue(PA_disk, [0, 180])
    disk.ell.setValue(ell_disk, [0, 1])
    disk.I_0.setValue(I_0, [0, 10*I_0])
    disk.h.setValue(h, [0, 10*h])

    model.addFunction(bulge)
    model.addFunction(disk)

    return model


model_desc = galaxy_model(x0=33, y0=33, PA_bulge=90.0, ell_bulge=0.2, n=4, I_e=1,
                        r_e=25, pa_disk=90.0, ell_disk=0.5, I_0=1, h=25)

imfit_fitter = pyimfit.Imfit(model_desc)

# etc.

Another way to construct the model is by defining it using a set of nested Python dicts, and passing the parent dict to the ModelObject.dict_to_ModelDescription function:

# define a function for making a simple bulge+disk model, where both components
# share the same central coordinate; this version uses dicts internally

def galaxy_model(x0, y0, PA_bulge, ell_bulge, n, I_e, r_e, PA_disk, ell_disk, I_0, h):
    # dict describing the bulge (first define the parameter dict, with initial values
    # and lower & upper limits for each parameter)
    p_bulge = {'PA': [PA_bulge, 0, 180], 'ell_bulge': [ell, 0, 1], 'n': [n, 0.5, 5],
                'I_e': [I_e, 0.0, 10*I_e], 'r_e': [r_e, 0.0, 10*r_e]}
    bulge_dict = {'name': "Sersic", 'label': "bulge", 'parameters': p_bulge}
    # do the same thing for the disk component
    p_disk = {'PA': [PA_disk, 0, 180], 'ell_disk': [ell, 0, 1], 'I_0': [I_0, 0, 10*I_0],
                'h': [h, 0.0, 10*h]}
    disk_dict = {'name': "Exponential", 'label': "disk", 'parameters': p_disk}

    # make dict for the function set that combines the bulge and disk components
    # with a single shared center, and then a dict for the whole model
    funcset_dict = {'X0': [x0, x0 - 10, x0 + 10], 'Y0': [y0, y0 - 10, y0 + 10],
                    'function_list': [bulge_dict, disk_dict]}
    model_dict = {'function_sets': [funcset_dict]}

    model = pyimfit.ModelDescription.dict_to_ModelDescription(model_dict)
    return model


model_desc = galaxy_model(x0=33, y0=33, PA_bulge=90.0, ell_bulge=0.2, n=4, I_e=1,
                        r_e=25, pa_disk=90.0, ell_disk=0.5, I_0=1, h=25)

imfit_fitter = pyimfit.Imfit(model_desc)

# etc.

You can get a list of PyImfit’s image functions (“Sersic”, “Exponential”, etc.) from the package-level variable pyimfit.imageFunctionList, and you can get a list of the parameter names for each image function from pyimfit.imageFunctionDict. Full descriptions of the individual image functions and their parameters can be found in the Imfit manual (PDF)