Ejemplo n.º 1
1
def measure_image_moments(image):
    """Compute 0th, 1st and 2nd moments of an image.

    NaN values are ignored in the computation.

    Parameters
    ----------
    image :`astropy.io.fits.ImageHDU`
        Image to measure on.

    Returns
    -------
    image moments : list
        List of image moments:
        [A, x_cms, y_cms, x_sigma, y_sigma, sqrt(x_sigma * y_sigma)]
    """
    x, y = coordinates(image, lon_sym=True)
    A = image.data[np.isfinite(image.data)].sum()

    # Center of mass
    x_cms = (x * image.data)[np.isfinite(image.data)].sum() / A
    y_cms = (y * image.data)[np.isfinite(image.data)].sum() / A

    # Second moments
    x_var = ((x - x_cms) ** 2 * image.data)[np.isfinite(image.data)].sum() / A
    y_var = ((y - y_cms) ** 2 * image.data)[np.isfinite(image.data)].sum() / A
    x_sigma = np.sqrt(x_var)
    y_sigma = np.sqrt(y_var)

    return A, x_cms, y_cms, x_sigma, y_sigma, np.sqrt(x_sigma * y_sigma)
Ejemplo n.º 2
0
def _to_image_bbox(catalog, image):
    """@todo: make the usage of bbox an option of the function
    _to_image_simple, otherwise we duplicate a lot of code!


    Function takes catalog and an empty image.
    It returns the image of the catalog.
    catalog = atpy.Table
    image = kapteyn.FITSimage

    @todo: This function should have NO explicit references to
    morphology column names.
    Do something like:
    for p in morphology.morph_pars:
        exec('p = {0}'.format(p))

    and then
    pars = [eval('[??? for x in eval('morphology.{0}_par'.format(???
    """
    logging.info('Building image out of catalog.')
    # Select sources in FOV
    # TODO: improve this check by reading the min, max from
    # the FITS header instead of finding the min of the array.
    l, b = utils.coordinates(image)  #, glon_sym=True)

    # Get catalog columns common to all morph types
    morph_type = catalog.field('morph_type')
    glon = catalog.field('glon')
    glat = catalog.field('glat')
    S_PWN = catalog.field('S_PWN')
    S_SNR = catalog.field('S_SNR')
    ext_in_SNR = catalog.field('ext_in_SNR')
    ext_out_SNR = catalog.field('ext_out_SNR')
    ext_out_PWN = catalog.field('ext_out_PWN')

    contributing = np.all([
        l.min() < glon + ext_out_SNR, glon - ext_out_SNR < l.max(),
        b.min() < glat + ext_out_SNR, glat - ext_out_SNR < b.max(), S_SNR > 0
    ],
                          axis=0)

    # Make image, adding one source at a time
    nsources = contributing.sum()
    logging.info('Adding {0} sources.'.format(nsources))
    logging.info('Skipping {0} sources.'.format(catalog.size - nsources))
    for i in range(catalog.size):
        # Skip sources that are not contributing
        if not contributing[i]:
            # logging.debug('Skipping source {0:6d}.'.format(i))
            continue

        # Make a list of parameters appropriate for the morph_type
        pars = [glon[i], glat[i]]
        if morph_type[i] == 'sphere2d':
            pars += [S_PWN[i], ext_out_PWN[i]]
        elif morph_type[i] == 'shell2d':
            pars += [S_SNR[i], ext_out_SNR[i], ext_in_SNR[i]]

        logging.debug('Adding source {0:6d}.'.format(i))
        _add_source(image, morph_type[i], pars, l, b)
Ejemplo n.º 3
0
def measure_image_moments(image):
    """Compute 0th, 1st and 2nd moments of an image.

    NaN values are ignored in the computation.

    Parameters
    ----------
    image :`astropy.io.fits.ImageHDU`
        Image to measure on.

    Returns
    -------
    image moments : list
        List of image moments:
        [A, x_cms, y_cms, x_sigma, y_sigma, sqrt(x_sigma * y_sigma)]
    """
    x, y = coordinates(image, lon_sym=True)
    A = image.data[np.isfinite(image.data)].sum()

    # Center of mass
    x_cms = (x * image.data)[np.isfinite(image.data)].sum() / A
    y_cms = (y * image.data)[np.isfinite(image.data)].sum() / A

    # Second moments
    x_var = ((x - x_cms)**2 * image.data)[np.isfinite(image.data)].sum() / A
    y_var = ((y - y_cms)**2 * image.data)[np.isfinite(image.data)].sum() / A
    x_sigma = np.sqrt(x_var)
    y_sigma = np.sqrt(y_var)

    return A, x_cms, y_cms, x_sigma, y_sigma, np.sqrt(x_sigma * y_sigma)
Ejemplo n.º 4
0
def measure_containment_radius(image, glon, glat, containment_fraction=0.8):
    """Measure containment radius.

    Uses `scipy.optimize.brentq`.

    Parameters
    ----------
    image : `astropy.io.fits.ImageHDU`
        Image to measure on.
    glon : float
        Source longitude in degree.
    glat : float
        Source latitude in degree.
    containment_fraction : float (default 0.8)
        Containment fraction

    Returns
    -------
    containment_radius : float
        Containment radius (pix)
    """
    from scipy.optimize import brentq

    GLON, GLAT = coordinates(image, lon_sym=True)
    rr = (GLON - glon)**2 + (GLAT - glat)**2

    # Normalize image
    image.data = image.data / image.data[np.isfinite(image.data)].sum()

    def func(r):
        return measure_containment_fraction(r, rr,
                                            image.data) - containment_fraction

    containment_radius = brentq(func, a=0, b=np.sqrt(rr.max()))
    return containment_radius
Ejemplo n.º 5
0
def measure_containment_radius(image, glon, glat, containment_fraction=0.8):
    """Measure containment radius.

    Uses `scipy.optimize.brentq`.

    Parameters
    ----------
    image : `astropy.io.fits.ImageHDU`
        Image to measure on.
    glon : float
        Source longitude in degree.
    glat : float
        Source latitude in degree.
    containment_fraction : float (default 0.8)
        Containment fraction

    Returns
    -------
    containment_radius : float
        Containment radius (pix)
    """
    from scipy.optimize import brentq

    GLON, GLAT = coordinates(image, lon_sym=True)
    rr = (GLON - glon) ** 2 + (GLAT - glat) ** 2

    # Normalize image
    image.data = image.data / image.data[np.isfinite(image.data)].sum()

    def func(r):
        return measure_containment_fraction(r, rr, image.data) - containment_fraction

    containment_radius = brentq(func, a=0, b=np.sqrt(rr.max()))
    return containment_radius
Ejemplo n.º 6
0
def _to_image_bbox(catalog, image):
    """@todo: make the usage of bbox an option of the function
    _to_image_simple, otherwise we duplicate a lot of code!


    Function takes catalog and an empty image.
    It returns the image of the catalog.
    catalog = atpy.Table
    image = kapteyn.FITSimage

    @todo: This function should have NO explicit references to
    morphology column names.
    Do something like:
    for p in morphology.morph_pars:
        exec('p = {0}'.format(p))

    and then
    pars = [eval('[??? for x in eval('morphology.{0}_par'.format(???
    """
    logging.info('Building image out of catalog.')
    # Select sources in FOV
    # TODO: improve this check by reading the min, max from
    # the FITS header instead of finding the min of the array.
    l, b = utils.coordinates(image)#, glon_sym=True)

    # Get catalog columns common to all morph types
    morph_type = catalog.field('morph_type')
    glon = catalog.field('glon')
    glat = catalog.field('glat')
    S_PWN = catalog.field('S_PWN')
    S_SNR = catalog.field('S_SNR')
    ext_in_SNR = catalog.field('ext_in_SNR')
    ext_out_SNR = catalog.field('ext_out_SNR')
    ext_out_PWN = catalog.field('ext_out_PWN')

    contributing = np.all([l.min() < glon + ext_out_SNR, glon - ext_out_SNR < l.max(),
                           b.min() < glat + ext_out_SNR, glat - ext_out_SNR < b.max(), S_SNR > 0], axis=0)

    # Make image, adding one source at a time
    nsources = contributing.sum()
    logging.info('Adding {0} sources.'.format(nsources))
    logging.info('Skipping {0} sources.'.format(catalog.size - nsources))
    for i in range(catalog.size):
        # Skip sources that are not contributing
        if not contributing[i]:
            # logging.debug('Skipping source {0:6d}.'.format(i))
            continue

        # Make a list of parameters appropriate for the morph_type
        pars = [glon[i], glat[i]]
        if morph_type[i] == 'sphere2d':
            pars += [S_PWN[i], ext_out_PWN[i]]
        elif morph_type[i] == 'shell2d':
            pars += [S_SNR[i], ext_out_SNR[i], ext_in_SNR[i]]

        logging.debug('Adding source {0:6d}.'.format(i))
        _add_source(image, morph_type[i], pars, l, b)
Ejemplo n.º 7
0
def _to_image_gaussian(catalog, image):
    """Add catalog of asymmetric Gaussian sources to an image.

    @type catalog: atpy.Table
    @type image: maputils.FITSimage
    @return: maputils.FITSimage"""
    from kapteyn.maputils import FITSimage
    logging.info('Adding %d sources.' % len(catalog.data))

    #
    # Read catalog
    #
    l_center = catalog.data['glon']
    b_center = catalog.data['glat']
    a = catalog.data['a']
    b = catalog.data['b']
    theta = catalog.data['theta']
    flux = catalog.data['flux']

    # Compute matrix entries that describe the ellipse, as defined in
    # the section "9.1.6. Ellipse parameters" in the SExtractor Manual.
    # Note that clb already contains the factor of 2!
    #
    # Another reference giving formulas is
    # http://en.wikipedia.org/wiki/Gaussian_function
    cll = np.cos(theta) ** 2 / a ** 2 + np.sin(theta) ** 2 / b ** 2
    cbb = np.sin(theta) ** 2 / a ** 2 + np.cos(theta) ** 2 / b ** 2
    clb = 2 * np.cos(theta) * np.sin(theta) * (a ** -2 - b ** -2)

    #
    # Add sources to image
    #
    data = image.dat
    header = image.hdr
    for i in range(len(catalog)):  # Loop sources
        l, b = utils.coordinates(image)
        # convert l to the range -180 to +180
        l = np.where(l > 180, l - 360, l)
        exponent = cll[i] * (l - l_center[i]) ** 2 + \
            cbb[i] * (b - b_center[i]) ** 2 + \
            clb[i] * (l - l_center[i]) * (b - b_center[i])
        data += flux[i] * np.exp(-exponent)

    # Return image with sources
    image_out = FITSimage(externalheader=header,
                          externaldata=data)
    return image_out
Ejemplo n.º 8
0
def _to_image_simple(catalog, image):
    """Add sources from a catalog to an image.

    catalog = atpy.Table
    image = kapteyn.maputils.FITSimage

    Note: This implementation doesn't use bounding boxes and thus is slow.
    You should use the faster _to_image_bbox()"""
    from kapteyn.maputils import FITSimage
    from morphology.shapes import morph_types
    nsources = len(catalog)
    data = image.dat
    logging.info('Adding {0} sources.'.format(nsources))

    # Get coordinate maps
    l, b = utils.coordinates(image)

    # Add sources to image one at a time
    for i in range(nsources):
        logging.debug('Adding source {0:3d} of {1:3d}.' ''.format(i, nsources))
        # nans = np.isnan(data).sum()
        # if nans:
        #    logging.debug('Image contains {0} nan entries.'.format(nans))

        # Get relevant columns
        morph_type = catalog[i]['morph_type']
        xpos = catalog[i]['glon']
        xpos = np.where(xpos > 180, xpos - 360, xpos)
        ypos = catalog[i]['glat']
        ampl = catalog[i]['ampl']
        sigma = catalog[i]['sigma']
        epsilon = catalog[i]['epsilon']
        theta = catalog[i]['theta']
        r_in = catalog[i]['r_in']
        r_out = catalog[i]['r_out']

        pars = {
            'delta2d': (xpos, ypos, ampl),
            'shell2d': (xpos, ypos, ampl, r_in, r_out),
            'gauss2d': (xpos, ypos, ampl, sigma, epsilon, theta)
        }
        par = pars[morph_type]

        data += morph_types[morph_type](par, l, b)

    return FITSimage(externalheader=image.hdr, externaldata=data)
Ejemplo n.º 9
0
def _to_image_gaussian(catalog, image):
    """Add catalog of asymmetric Gaussian sources to an image.

    @type catalog: atpy.Table
    @type image: maputils.FITSimage
    @return: maputils.FITSimage"""
    from kapteyn.maputils import FITSimage
    logging.info('Adding %d sources.' % len(catalog.data))

    #
    # Read catalog
    #
    l_center = catalog.data['glon']
    b_center = catalog.data['glat']
    a = catalog.data['a']
    b = catalog.data['b']
    theta = catalog.data['theta']
    flux = catalog.data['flux']

    # Compute matrix entries that describe the ellipse, as defined in
    # the section "9.1.6. Ellipse parameters" in the SExtractor Manual.
    # Note that clb already contains the factor of 2!
    #
    # Another reference giving formulas is
    # http://en.wikipedia.org/wiki/Gaussian_function
    cll = np.cos(theta)**2 / a**2 + np.sin(theta)**2 / b**2
    cbb = np.sin(theta)**2 / a**2 + np.cos(theta)**2 / b**2
    clb = 2 * np.cos(theta) * np.sin(theta) * (a**-2 - b**-2)

    #
    # Add sources to image
    #
    data = image.dat
    header = image.hdr
    for i in range(len(catalog)):  # Loop sources
        l, b = utils.coordinates(image)
        # convert l to the range -180 to +180
        l = np.where(l > 180, l - 360, l)
        exponent = cll[i] * (l - l_center[i]) ** 2 + \
            cbb[i] * (b - b_center[i]) ** 2 + \
            clb[i] * (l - l_center[i]) * (b - b_center[i])
        data += flux[i] * np.exp(-exponent)

    # Return image with sources
    image_out = FITSimage(externalheader=header, externaldata=data)
    return image_out
Ejemplo n.º 10
0
def _to_image_simple(catalog, image):
    """Add sources from a catalog to an image.

    catalog = atpy.Table
    image = kapteyn.maputils.FITSimage

    Note: This implementation doesn't use bounding boxes and thus is slow.
    You should use the faster _to_image_bbox()"""
    from kapteyn.maputils import FITSimage
    from morphology.shapes import morph_types
    nsources = len(catalog)
    data = image.dat
    logging.info('Adding {0} sources.'.format(nsources))

    # Get coordinate maps
    l, b = utils.coordinates(image)

    # Add sources to image one at a time
    for i in range(nsources):
        logging.debug('Adding source {0:3d} of {1:3d}.'
                      ''.format(i, nsources))
        # nans = np.isnan(data).sum()
        # if nans:
        #    logging.debug('Image contains {0} nan entries.'.format(nans))

        # Get relevant columns
        morph_type = catalog[i]['morph_type']
        xpos = catalog[i]['glon']
        xpos = np.where(xpos > 180, xpos - 360, xpos)
        ypos = catalog[i]['glat']
        ampl = catalog[i]['ampl']
        sigma = catalog[i]['sigma']
        epsilon = catalog[i]['epsilon']
        theta = catalog[i]['theta']
        r_in = catalog[i]['r_in']
        r_out = catalog[i]['r_out']

        pars = {'delta2d': (xpos, ypos, ampl),
                'shell2d': (xpos, ypos, ampl, r_in, r_out),
                'gauss2d': (xpos, ypos, ampl, sigma, epsilon, theta)}
        par = pars[morph_type]

        data += morph_types[morph_type](par, l, b)

    return FITSimage(externalheader=image.hdr, externaldata=data)
Ejemplo n.º 11
0
def measure_containment(image, glon, glat, radius):
    """
    Measure containment in a given circle around the source position.

    Parameters
    ----------
    image : `astropy.io.fits.ImageHDU`
        Image to measure on.
    glon : float
        Source longitude in degree.
    glat : float
        Source latitude in degree.
    radius : float
        Radius of the region to measure the containment in.
    """
    GLON, GLAT = coordinates(image, lon_sym=True)
    rr = (GLON - glon) ** 2 + (GLAT - glat) ** 2
    return measure_containment_fraction(radius, rr, image.data)
Ejemplo n.º 12
0
def measure_containment(image, glon, glat, radius):
    """
    Measure containment in a given circle around the source position.

    Parameters
    ----------
    image : `astropy.io.fits.ImageHDU`
        Image to measure on.
    glon : float
        Source longitude in degree.
    glat : float
        Source latitude in degree.
    radius : float
        Radius of the region to measure the containment in.
    """
    GLON, GLAT = coordinates(image, lon_sym=True)
    rr = (GLON - glon)**2 + (GLAT - glat)**2
    return measure_containment_fraction(radius, rr, image.data)
Ejemplo n.º 13
0
def lookup_max(image, GLON, GLAT, theta):
    """Look up the max image values within a circle of radius theta
    around lists of given positions (nan if outside)"""
    from .utils import coordinates
    GLON = np.asarray(GLON)
    GLON = np.where(GLON > 180, GLON - 360, GLON)
    GLAT = np.asarray(GLAT)
    n_pos = len(GLON)
    theta = np.asarray(theta) * np.ones(n_pos, dtype='float32')

    ll, bb = coordinates(image)

    val = np.nan * np.ones(n_pos, dtype='float32')
    for ii in range(n_pos):
        mask = ((GLON[ii] - ll)**2 + (GLAT[ii] - bb)**2 <= theta[ii]**2)
        try:
            val[ii] = image.data[mask].max()
        except ValueError:
            pass
    return val
Ejemplo n.º 14
0
def lookup_max(image, GLON, GLAT, theta):
    """Look up the max image values within a circle of radius theta
    around lists of given positions (nan if outside)"""
    from .utils import coordinates
    GLON = np.asarray(GLON)
    GLON = np.where(GLON > 180, GLON - 360, GLON)
    GLAT = np.asarray(GLAT)
    n_pos = len(GLON)
    theta = np.asarray(theta) * np.ones(n_pos, dtype='float32')

    ll, bb = coordinates(image)

    val = np.nan * np.ones(n_pos, dtype='float32')
    for ii in range(n_pos):
        mask = ((GLON[ii] - ll) ** 2 +
                (GLAT[ii] - bb) ** 2 <=
                theta[ii] ** 2)
        try:
            val[ii] = image.data[mask].max()
        except ValueError:
            pass
    return val
Ejemplo n.º 15
0
def _add_source(image, morph_type, pars, l, b):
    """Adds a specified source at a given position."""
    from gammapy.morphology.shapes import morph_types
    # Get position and extension info
    # TODO: this won't work for delta2d, which doesn't
    # have a pars[3] entry!
    glon, glat, ext = pars[0], pars[1], pars[3]
    logging.debug('Adding source of type {0} at position '
                  '{1}, {2} with extension {3}'
                  ''.format(morph_type, glon, glat, ext))

    # Get indices of position
    #import IPython; IPython.embed()
    x_pix, y_pix = np.arange(image.header['NAXIS1']), np.arange(
        image.header['NAXIS2'])

    # Correct pixel numbering
    x_pix = np.floor(x_pix) - 1
    y_pix = np.floor(y_pix) - 1

    # Get data
    data = image.data
    pixsize = image.header['CDELT2']

    # Compute boxsize with one pixel margin
    boxsize = 2 * np.floor(ext / pixsize + 2)

    # Determine corner pixels
    left_bottom = [y_pix, x_pix] - boxsize / 2
    right_top = [y_pix, x_pix] + boxsize / 2

    # Determine image boundaries
    y_bound, x_bound = data.shape

    # Correct Behaviour at the boundaries
    if left_bottom[1] < 0 or left_bottom[0] < 0 or right_top[
            1] > x_bound or right_top[0] > y_bound:
        logging.debug('Source is not completely in image.')

        # Get out of range coordinate map
        l, b = utils.coordinates(image, x_pix, y_pix, boxsize)

        # Get image of source
        box_image = morph_types[morph_type](pars, l, b)

        # Get slices
        s_x, s_y, b_x, b_y = _get_slices(left_bottom, right_top, x_bound,
                                         y_bound)

        # For debugging
        logging.debug('left_bottom: {0}'.format(left_bottom))
        logging.debug('right_top: {0}'.format(right_top))
        logging.debug('box_image.shape: {0}'.format(box_image.shape))
        logging.debug('s_x: {0}'.format(s_x))
        logging.debug('s_y: {0}'.format(s_y))
        logging.debug('b_x: {0}'.format(b_x))
        logging.debug('b_y: {0}'.format(b_y))
        logging.debug('box_image.shape: {0}'.format(box_image[b_y, b_x].shape))
        logging.debug('data.shape: {0}'.format(data[s_y, s_x].shape))

        # Add box to image
        data[s_y, s_x] += box_image[b_y, b_x]

    else:
        logging.debug('Source is completely in image.')
        s_x = slice(left_bottom[1], right_top[1])
        s_y = slice(left_bottom[0], right_top[0])
        # Get image of source
        box_image = morph_types[morph_type](pars, l[s_y, s_x], b[s_y, s_x])
        # Add box to image
        data[s_y, s_x] += box_image
Ejemplo n.º 16
0
""" Script to determine what fraction of source and diffuse flux is found in the large and small region"""

from astropy.io import fits

filename = raw_input('Image filename: ')
source = fits.open(filename)[1]

from gammapy.image.utils import coordinates, solid_angle
lats, lons = coordinates(source)
solid_angle = solid_angle(source)
region_glat_high = 5
region_glat_low = -5
region_glon_high = 100
region_glon_low = -100

mask1 = (region_glat_low < lats) & (lats < region_glat_high)
mask2 = (region_glon_low < lons) & (lons < region_glon_high)
mask = mask1 & mask2

a = source.data  #/ solid_angle.value
source_flux_frac = a[mask].sum() / a.sum()
print "Total Flux in Image"
print a.sum()

print "Galactic Flux"
print a[mask].sum()

print "Source Flux Fraction"
print source_flux_frac
Ejemplo n.º 17
0
def _add_source(image, morph_type, pars, l, b):
    """Adds a specified source at a given position."""
    from gammapy.morphology.shapes import morph_types
    # Get position and extension info
    # TODO: this won't work for delta2d, which doesn't
    # have a pars[3] entry!
    glon, glat, ext = pars[0], pars[1], pars[3]
    logging.debug('Adding source of type {0} at position '
                 '{1}, {2} with extension {3}'
                 ''.format(morph_type, glon, glat, ext))

    # Get indices of position
    #import IPython; IPython.embed()
    x_pix, y_pix = np.arange(image.header['NAXIS1']), np.arange(image.header['NAXIS2'])

    # Correct pixel numbering
    x_pix = np.floor(x_pix) - 1
    y_pix = np.floor(y_pix) - 1

    # Get data
    data = image.data
    pixsize = image.header['CDELT2']

    # Compute boxsize with one pixel margin
    boxsize = 2 * np.floor(ext / pixsize + 2)

    # Determine corner pixels
    left_bottom = [y_pix, x_pix] - boxsize / 2
    right_top = [y_pix, x_pix] + boxsize / 2

    # Determine image boundaries
    y_bound, x_bound = data.shape

    # Correct Behaviour at the boundaries
    if left_bottom[1] < 0 or left_bottom[0] < 0 or right_top[1] > x_bound or right_top[0] > y_bound:
        logging.debug('Source is not completely in image.')

        # Get out of range coordinate map
        l, b = utils.coordinates(image, x_pix, y_pix, boxsize)

        # Get image of source
        box_image = morph_types[morph_type](pars, l, b)

        # Get slices
        s_x, s_y, b_x, b_y = _get_slices(left_bottom, right_top, x_bound, y_bound)

        # For debugging
        logging.debug('left_bottom: {0}'.format(left_bottom))
        logging.debug('right_top: {0}'.format(right_top))
        logging.debug('box_image.shape: {0}'.format(box_image.shape))
        logging.debug('s_x: {0}'.format(s_x))
        logging.debug('s_y: {0}'.format(s_y))
        logging.debug('b_x: {0}'.format(b_x))
        logging.debug('b_y: {0}'.format(b_y))
        logging.debug('box_image.shape: {0}'.format(box_image[b_y, b_x].shape))
        logging.debug('data.shape: {0}'.format(data[s_y, s_x].shape))

        # Add box to image
        data[s_y, s_x] += box_image[b_y, b_x]

    else:
        logging.debug('Source is completely in image.')
        s_x = slice(left_bottom[1], right_top[1])
        s_y = slice(left_bottom[0], right_top[0])
        # Get image of source
        box_image = morph_types[morph_type](pars, l[s_y, s_x], b[s_y, s_x])
        # Add box to image
        data[s_y, s_x] += box_image
Ejemplo n.º 18
0
""" Script to determine what fraction of source and diffuse flux is found in the large and small region"""

from astropy.io import fits
import numpy as np

filename = raw_input('Image filename: ')
source = fits.open(filename)[1]

from gammapy.image.utils import coordinates, solid_angle
lats, lons = coordinates(source)
solid_angle = solid_angle(source)
region_glat_high = 5
region_glat_low = -5
region_glon_high = 100
region_glon_low = -100

mask1 = (region_glat_low < lats) & (lats < region_glat_high)
mask2 = (region_glon_low < lons) & (lons < region_glon_high)
mask = mask1 & mask2

a = np.nan_to_num(source.data)
source_flux_frac = a[mask].sum()/a.sum()
print "Total Flux in Image"
print a.sum()

print "Galactic Flux"
print a[mask].sum()

print "Source Flux Fraction"
print source_flux_frac