コード例 #1
0
def aperture_mask(fnlist, axcen, aycen, arad):
    """Opens a series of images and masks pixels outside a circular aperture.
    The images are overwritten with the new masked image. The values of axcen,
    aycen, and arad are added to the FITS headers as keywords 'fpaxcen',
    'fpaycen', and 'fparad' respectively.

    Inputs:
    fnlist -> A list containing strings, each the path to a fits image.
    axcen -> The aperture x center
    aycen -> The aperture y center
    arad -> The aperture radius

    """

    for i in range(len(fnlist)):
        print ("Masking pixels outside aperture for image " +
               str(i+1)+" of "+str(len(fnlist))+": "+fnlist[i])
        image = FPImage(fnlist[i], update=True)
        rgrid = image.rarray(axcen, aycen)
        image.inty[rgrid > arad] = 0
        image.badp[rgrid > arad] = 1
        image.axcen = axcen
        image.aycen = aycen
        image.arad = arad
        image.close()
コード例 #2
0
def make_final_image(input_image, output_image,
                     desired_fwhm, clobber=False):
    """This routine makes the 'final' images for a data cube. At least the
    paths to the input image, output image, and output wavelength image are
    necessary for this. Beyond that, the user may also have the routine create
    uncertainty images as well.

    Images are convolved to the resolution 'desired_fwhm'. If the current fwhm
    is already higher than that, the routine will throw an error.

    A number of fits header keywords are necessary for this program to function
    properly. Any of these missing will throw an error.

    The output images are intensity-weighted, i.e. the wavelength image will be
    created such that the wavelengths at each pixel are the 'most likely'
    wavelength for the intensity at that pixel, etc.

    Inputs:
    input_image -> Path to the input image.
    output_image -> Path to the output image.
    desired_fwhm -> Desired FWHM for the resultant image to have.

    Optional Inputs:
    clobber -> Overwrite output images if they already exist. Default is False.

    """

    print "Making final data cube images for image "+input_image

    # Open the image
    image = FPImage(input_image)

    # Measure the sky background level in the input image
    skyavg, _truesig, skysig = image.skybackground()

    # Get various header keywords, crash if necessary
    intygrid = image.inty
    fwhm = image.fwhm
    wave0 = image.wave0
    calf = image.calf
    xcen = image.xcen
    ycen = image.ycen
    if fwhm is None:
        exit("Error! FWHM not measured for image "+input_image+".")
    if wave0 is None or calf is None:
        exit("Error! Wavelength solution does " +
             "not exist for image "+input_image+".")
    if xcen is None or ycen is None:
        exit("Error! Center values not measured " +
             "image "+input_image+".")
    if fwhm > desired_fwhm:
        exit("Error! Desired FWHM too low for image " +
             input_image+".")

    # Calculate the necessary FWHM for convolution
    fwhm_conv = np.sqrt(desired_fwhm**2-fwhm**2)
    # Magic number converts sigma to fwhm
    sig = fwhm_conv/2.3548
    # Extremely conservative "safe" kernel size
    ksize = np.ceil(4*sig)
    # Generate the gaussian kernel, shifted to shift the image
    kxgrid, kygrid = np.meshgrid(np.linspace(-ksize, ksize, 2*ksize+1),
                                 np.linspace(-ksize, ksize, 2*ksize+1))
    xshift, yshift = image.xshift, image.yshift
    rad2grid = (kxgrid + xshift)**2 + (kygrid + yshift)**2
    kern = np.exp(-rad2grid/(2*sig**2))

    # Normalize the kernel
    kern = kern/np.sum(kern)

    # Extract relevant arrays
    vargrid = image.vari
    badpixgrid = image.badp

    # Convolve the variances appropriately
    new_vargrid = convolve_variance(vargrid, badpixgrid, kern)

    # Add the sky background uncertainty to the uncertainty grid
    vargrid = vargrid+skysig**2

    # Create and convolve the wavelength array
    if image.wave is None:
        rgrid = image.rarray(xcen, ycen)
        wavegrid = wave0 / np.sqrt(1+rgrid**2/calf**2)
    else:
        wavegrid = image.wave
    new_wavegrid = convolve_wave(wavegrid, intygrid, badpixgrid, kern)

    # Convolve the intensity image
    new_intygrid = convolve_inty(intygrid, badpixgrid, kern)
    new_intygrid[new_intygrid == 0] = intygrid[new_intygrid == 0]
    new_intygrid[np.isnan(new_intygrid)] = intygrid[np.isnan(new_intygrid)]
    image.fwhm = desired_fwhm  # Update header FWHM keyword

    # Subtract the sky background from the image
    new_intygrid[new_intygrid != 0] -= skyavg

    # Create a new fits extension for the wavelength array
    if image.wave is None:
        waveheader = image.openimage[2].header.copy()
        waveheader['EXTVER'] = 4
        wavehdu = ImageHDU(data=new_wavegrid,
                           header=waveheader,
                           name="WAVE")
        image.openimage[1].header.set('WAVEEXT', 4,
                                      comment='Extension for Wavelength Frame')
        image.openimage.append(wavehdu)

    # Put all of the convolved images in the right extensions
    image.inty = new_intygrid
    image.vari = new_vargrid
    image.wave = new_wavegrid

    # Adjust header keywords (even though they're kinda irrelevant now)
    image.xcen += image.xshift
    image.ycen += image.yshift
    image.axcen += image.xshift
    image.aycen += image.yshift

    # Write the output file
    image.writeto(output_image, clobber=clobber)

    # Close images
    image.close()

    return
コード例 #3
0
ファイル: deghost.py プロジェクト: carlmitchell/saltfppipe
def deghost(fn):
    """Routine to deghost an image by rotating it about a central point and
    subtracting a constant multiple of this rotated image from the original.
    My experience has shown that about 0.04 is the right value, but your
    mileage may vary.

    The fits header must contain values in "fpxcen" and "fpycen" for the center
    about which to be rotated.

    Optionally also modifies an uncertainty image to account for the effects
    of deghosting on the error propagation.

    Creates the fits header keyword "fpghost" = "True".

    Inputs:
    fn -> String, the path to the fits image to be deghosted.

    """

    # Open the image and check for center coordinates
    image = FPImage(fn, update=True)
    if image.xcen is None:
        exit("Error! Image "+fn+" doesn't have center coordinates in header!")
    xcen = image.xcen+1
    ycen = image.ycen+1
    bins = int(image.bins.split()[0])
    reflection_xcen = image.xcen + reflection_center_x_shift/bins
    reflection_ycen = image.ycen + reflection_center_y_shift/bins
    r_array = image.rarray(reflection_xcen, reflection_ycen)
    g_array = reflection_intercept + reflection_slope*bins*r_array

    # Deghost the intensity image
    print "Deghosting image "+fn

    # Determine image size
    xsize, ysize = image.xsize, image.ysize

    # Make a mask for the chip gaps and outside-aperture stuff
    mask = image.inty == 0

    # Make an array of the flipped data
    flipinty = image.inty[::-1, ::-1].copy()*1.0
    flipvari = image.vari[::-1, ::-1].copy()*1.0
    flip_g = g_array[::-1, ::-1].copy()*1.0

    # Calculate the difference between the image's geometric center (midpoint)
    # and the axis of rotation
    xshift = 2*xcen-xsize-1
    yshift = 2*ycen-ysize-1

    # A given pixel's position, when rotated, will overlap its four
    # neighboring pixels. All pixels will have the same four overlapping
    # regions because the rotation is 180 degrees. Here we take a weighted
    # sum of these four pixels, where the weights are equal to the areas
    # of overlap. This weighted sum is subtracted from the original pixel.
    for i in range(4):
        # This branching is for the four overlapping pixel regions
        if i == 0:
            miny = max(np.floor(yshift), 0)
            maxy = min(ysize+np.floor(yshift), ysize)
            minx = max(np.floor(xshift), 0)
            maxx = min(xsize+np.floor(xshift), xsize)
            flipminy = max(-np.floor(yshift), 0)
            flipmaxy = min(ysize, ysize-np.floor(yshift))
            flipminx = max(-np.floor(xshift), 0)
            flipmaxx = min(xsize, xsize-np.floor(xshift))
            frac = abs((np.ceil(yshift)-yshift)*(np.ceil(xshift)-xshift))
        if i == 1:
            miny = max(np.ceil(yshift), 0)
            maxy = min(ysize+np.ceil(yshift), ysize)
            minx = max(np.floor(xshift), 0)
            maxx = min(xsize+np.floor(xshift), xsize)
            flipminy = max(-np.ceil(yshift), 0)
            flipmaxy = min(ysize, ysize-np.ceil(yshift))
            flipminx = max(-np.floor(xshift), 0)
            flipmaxx = min(xsize, xsize-np.floor(xshift))
            frac = abs((np.floor(yshift)-yshift)*(np.ceil(xshift)-xshift))
        if i == 2:
            miny = max(np.floor(yshift), 0)
            maxy = min(ysize+np.floor(yshift), ysize)
            minx = max(np.ceil(xshift), 0)
            maxx = min(xsize+np.ceil(xshift), xsize)
            flipminy = max(-np.floor(yshift), 0)
            flipmaxy = min(ysize, ysize-np.floor(yshift))
            flipminx = max(-np.ceil(xshift), 0)
            flipmaxx = min(xsize, xsize-np.ceil(xshift))
            frac = abs((np.ceil(yshift)-yshift)*(np.floor(xshift)-xshift))
        if i == 3:
            miny = max(np.ceil(yshift), 0)
            maxy = min(ysize+np.ceil(yshift), ysize)
            minx = max(np.ceil(xshift), 0)
            maxx = min(xsize+np.ceil(xshift), xsize)
            flipminy = max(-np.ceil(yshift), 0)
            flipmaxy = min(ysize, ysize-np.ceil(yshift))
            flipminx = max(-np.ceil(xshift), 0)
            flipmaxx = min(xsize, xsize-np.ceil(xshift))
            frac = abs((np.floor(yshift)-yshift)*(np.floor(xshift)-xshift))
        g = flip_g[flipminy:flipmaxy,
                   flipminx:flipmaxx]

        # Rotate and subtract the intensity array
        image.inty[miny:maxy,
                   minx:maxx] -= g*frac*flipinty[flipminy:flipmaxy,
                                                 flipminx:flipmaxx]
        image.vari[miny:maxy,
                   minx:maxx] += (g*frac)**2*flipvari[flipminy:flipmaxy,
                                                      flipminx:flipmaxx]

    # Remask the intensity data using the mask we created
    image.inty[mask] = 0

    # Update the header
    image.ghosttog = "True"

    # Close the image
    image.close()

    return