Example #1
0
    def cog(self, window_size, method, tolerance = 0.01):
        """
        Curve of growth to determine nominal aperture for photometry using
        astropy photutils.

        Parameters
        ----------
        tolerance : float
            Magnitude difference tolerance between different apertures

        Returns
        -------
        aperture : float
            Nominal aperture radius for photmetry
        """
        # Aperture values in pixels
        apertures = np.array([2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
        naper = apertures.shape[0]

        # Randomly perform curve of growth on 5 frames
        framenum = np.random.randint(1, self.nframes, 5)

        apertures = np.linspace(2,20,19)

        # Read input image and star position
        image = chimera.fitsread(self.sci_file)
        pos = np.loadtxt(self.coords, ndmin = 2)

        # Iterate through the frames and determine nominal aperture
        nom_aper = np.zeros(5, dtype = np.float32)
        cnt = 0
        for val in framenum:
            mags_arr = np.zeros(len(apertures))
            objpos = chimera.recenter(image[val,:,:], pos, window_size, method)
            for i in range(naper):
                flux = self.phot(image[val,:,:], objpos, aper = apertures[i])
                try:
                    mags_arr[i] = -2.5 * np.log10(flux['flux'])
                except:
                    mags_arr[i] = -2.5 * np.log10(flux['flux'][1])
            mags_diff = np.diff(mags_arr)
            idx = np.where((np.abs(mags_diff) < 0.01) & (np.abs(mags_diff) != 0.0))
            if len(idx[0]) != 0:
                nom_aper[cnt] = apertures[idx[0][0]]
            else:
                nom_aper[cnt] = 10.0
            cnt += 1

        return np.median(nom_aper)
Example #2
0
 def cog(self, window_size, method, tolerance = 0.01):
     """
     Curve of growth to determine nominal aperture for photometry using 
     astropy photutils.
     
     Parameters
     ----------
     tolerance : float
         Magnitude difference tolerance between different apertures
     
     Returns
     -------
     aperture : float
         Nominal aperture radius for photmetry
     """
     # Aperture values in pixels
     apertures = np.array([2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
     naper = apertures.shape[0]
     
     # Randomly peform curve of growth on 5 frames
     framenum = np.random.randint(1, self.nframes, 5)
     
     apertures = np.linspace(2,20,19)
     
     # Read input image and star position
     image = chimera.fitsread(self.sci_file)
     pos = np.loadtxt(self.coords, ndmin = 2)
     
     # Iterate through the frames and determine nominal aperture
     nom_aper = np.zeros(5, dtype = np.float32)
     cnt = 0
     for val in framenum:
         mags_arr = np.zeros(len(apertures))
         objpos = chimera.recenter(image[val,:,:], pos, window_size, method)
         for i in range(naper):
             flux = self.phot(image[val,:,:], objpos, aper = apertures[i])
             mags_arr[i] = -2.5 * np.log10(flux['flux'])
         mags_diff = np.diff(mags_arr)
         idx = np.where(np.abs(mags_diff) < 0.01)
         if len(idx[0]) != 0:
             nom_aper[cnt] = apertures[idx[0][0]]
         else:
             nom_aper[cnt] = 12.0
         cnt += 1
         
     return np.median(nom_aper)
Example #3
0
def animate(image, nframes, vmin, vmax, scale, cmap, fps, outtype):
    """ 
    Generate animation from CHIMERA image cube.
    
    Parameters
    ----------
    image : string
        CHIMERA FITS image name
        
    nframes : int
        Number of frames to include in animation
        
    vmin, vmax : float
        Minimum and maximum pixel value
        
    scale : string
        Scale the images? (linear or log)
        
    cmap : string
        Matlab colormap
    
    fps : int
        Frames per second for mp4 animation
        
    outtype : string
        Save animation as gif or mp4
    
    Returns
    -------
    anim_fname : string
        Name of the animation file name.
    """

    print "ANIMATE: Animate CHIMERA 3D image cubes"

    nframes = int(nframes)
    vmin = int(vmin)
    vmax = int(vmax)
    fps = int(fps)

    # Create a matplotlib figure
    fig = plt.figure(figsize=(12, 10))
    plt.axis("off")

    # Read FITS image
    img_data = chimera.fitsread(image)

    # Display each frame to create an animation
    if nframes > img_data.shape[0]:
        nframes = img_data.shape[0]

    print "  Generating animation"

    ims = []
    for i in range(0, nframes):
        if scale == 'linear':
            im = plt.imshow(img_data[i, :, :],
                            origin="lower",
                            cmap=plt.get_cmap(cmap),
                            vmin=vmin,
                            vmax=vmax)
        else:
            img_log = np.log10(img_data[i, :, :])
            im = plt.imshow(img_log,
                            origin="lower",
                            cmap=plt.get_cmap(cmap),
                            vmin=np.min(img_log),
                            vmax=np.max(img_log))
        ims.append([im])

    # Animate the frames
    ani = animation.ArtistAnimation(fig,
                                    ims,
                                    interval=50,
                                    blit=True,
                                    repeat_delay=10)

    # Save the animation
    if outtype == "gif":
        anim_fname = image.replace(".fits", ".gif")
        ani.save(anim_fname, dpi=100, writer="imagemagick")
    else:
        anim_fname = image.replace(".fits", ".mp4")
        ani.save(anim_fname,
                 fps=fps,
                 dpi=100,
                 extra_args=['-vcodec', 'libx264'])

    return anim_fname
Example #4
0
def process(infile, coords, method, inner_radius, outer_radius, cen_method,
            window_size, output, zmag, avg):
    """
    Entry point function to process science image.

    Parameters
    ----------
    infile : string
        Science image or list of science images

    coords : string
        Input text file with coordinates of stars

    method : string
        FWHM of the stelar psf in pixels

    inner_radius : float
        Sky background sigma

    outer_radius : int
        Inner sky annulus radius in pixels

    cen_method : string
        Centroid method

    window_size : int
        Centroid finding window size in pixels

    output : string
        Output file name

    zmag : float
        Photometric zero point


    Returns
    -------
    None
    """
    print("FASTPHOT: CHIMERA Fast Aperture Photometry Routine")

    inner_radius = float(inner_radius)
    outer_radius = float(outer_radius)

    # Check if input is a string of FITS images or a text file with file names
    if infile[0] == "@":
        infile = infile[1:]

        if not os.path.exists(infile):
            print("REGISTER: Not able to locate file %s" % infile)

        image_cubes = []
        with open(infile, "r") as fd:
            for line in fd.readlines():
                if len(line) > 1:
                    image_cubes.append(line.replace("\n", ""))
    else:
        image_cubes = infile.split(",")

    # Number of images
    ncubes = len(image_cubes)
    pos = np.loadtxt(coords, ndmin=2)
    nstars = len(pos)

    total_phot_data = []

    for i in range(ncubes):
        sci_file = image_cubes[i]
        print("  Processing science image %s" % sci_file)

        # Read FITS image and star coordinate
        image = chimera.fitsread(sci_file)
        if avg != "":
            image = time_average(image, avg)
            avg = int(avg)
        else:
            avg = 1

        # Instantiate an Aperphot object
        ap = chimera.Aperphot(sci_file, coords)

        # Set fwhmpsf, sigma, annulus, dannulus and zmag
        ap.method = method
        ap.inner_radius = inner_radius
        ap.outer_radius = outer_radius

        if zmag != "":
            ap.zmag = float(zmag)

        # Determine nominal aperture radius for photometry
        if i == 0:
            nom_aper = ap.cog(window_size, cen_method)

#nom_aper = 3

        print("  Nominal aperture radius : %4.1f pixels" % nom_aper)

        # Perform aperture photometry on all the frames
        dtype = [("DATETIME", "S25"), ("XCEN", "f4"), ("YCEN", "f4"),
                 ("MSKY", "f8"), ("NSKY", "f8"), ("AREA", "f8"),
                 ("FLUX_ADU", "f8"), ("FLUX_ELEC", "f8"), ("FERR", "f8"),
                 ("MAG", "f8")]
        phot_data = np.zeros([nstars, ap.nframes / avg], dtype=dtype)

        for j in range(ap.nframes / avg):
            print("    Processing frame number : %d" % (j + 1))

            objpos = chimera.recenter(image[j, :, :], pos, window_size,
                                      cen_method)
            aperphot_data = ap.phot(image[j, :, :], objpos, nom_aper)
            pos = np.copy(objpos)

            phot_data[:, j]['DATETIME'] = ap.addtime(j * avg *
                                                     ap.kintime).isoformat()
            phot_data[:, j]['XCEN'] = aperphot_data["xcenter_raw"]
            phot_data[:, j]['YCEN'] = aperphot_data["ycenter_raw"]
            phot_data[:, j]['MSKY'] = aperphot_data["msky"]
            phot_data[:, j]['NSKY'] = aperphot_data["nsky"]
            phot_data[:, j]['AREA'] = aperphot_data["area"]
            phot_data[:, j]['FLUX_ADU'] = aperphot_data["flux"]
            phot_data[:,
                      j]['FLUX_ELEC'] = phot_data[:, j]['FLUX_ADU'] * ap.epadu
            phot_data[:, j]['MAG'] = ap.zmag - 2.5 * np.log10(
                phot_data[:, j]['FLUX_ELEC'] / (ap.exptime))

            # Calculate error in flux - using the formula
            # err = sqrt(flux * gain + npix * (1 + (npix/nsky)) * (flux_sky * gain + R**2))
            phot_data[:, j]['FERR'] = np.sqrt(
                phot_data[:, j]['FLUX_ELEC'] + phot_data[:, j]['AREA'] *
                (1 + phot_data[:, j]['AREA'] / phot_data[:, j]['NSKY']) *
                (phot_data[:, j]['MSKY'] * ap.epadu + ap.readnoise**2))

        total_phot_data.append(phot_data)

        # Save photometry data in numpy binary format
        print("  Saving photometry data as numpy binary")
        if output != "":
            npy_outfile = output + ".npy"
        else:
            npy_outfile = sci_file.replace(".fits", ".phot.npy")
        if os.path.exists(npy_outfile):
            os.remove(npy_outfile)

        #np.save(npy_outfile, phot_data)
        '''
        # Plot first pass light curve
        if plot_flag:
            print "  Plotting normalized light curve"
            if output != "":
                plt_outfile = output + ".png"
            else:
                plt_outfile = sci_file.replace(".fits", ".lc.png")
            plotter(phot_data, ap.nframes, ap.kintime, plt_outfile)
	'''
    # Convert the total_phot_data to array and reshape it
    print('  Saving consolidated photometry data...')
    total_phot_data_arr = np.concatenate(total_phot_data, axis=1)

    # Save the array as npy file
    if output != "":
        np.save(output + "phot_total.npy", total_phot_data_arr)
    else:
        np.save("phot_total.npy", total_phot_data_arr)

    return
Example #5
0
def process(sci_files, sci_bias_file, flat_file, nskip, threshold, flat_bias_file, output):
    """
    Entry point function to process science images.
    
    Parameters
    ----------
    sci_files : string
        Science image file names
        
    sci_bias_file : string
        Bias image file name for science images
        
    flat_file : string
        Flat field file name
        
    skip : int
        Number of bias frames to skip before averaging the frames. Default is 0.
        
    threshold : float
        Threshold for normalized fat field (value between 0 and 1.0). 
        Default is 0.8.

    flat_bias_file : string
        Bias image file name for flat field images
                
    Returns
    -------
    None 
    """
    print "REDUCE: CHIMERA Image Reduction Rotuine"

    nskip = int(nskip)
    threshold = float(threshold)

    # Check if input is a string of FITS images or a text file with file names
    if sci_files[0] == "@":
        infile = sci_files[1:]

        if not os.path.exists(infile):
            print "  Not able to locate file %s" % infile

        image_cubes = []
        with open(infile, "r") as fd:
            for line in fd.readlines():
                if len(line) > 1:
                    image_cubes.append(line.replace("\n", ""))
    else:
        image_cubes = sci_files.split(",")

    # Read bias and flat field images
    sci_bias_image = chimera.fitsread(sci_bias_file)
    flat_image = chimera.fitsread(flat_file)

    if flat_bias_file != "":
        flat_bias_image = chimera.fitsread(flat_bias_file)
    else:
        flat_bias_image = sci_bias_image

    # Create master bias image
    print "  Generating master bias image"
    master_sci_bias_image = chimera.masterbias(sci_bias_image)
    master_flat_bias_image = chimera.masterbias(flat_bias_image)

    # Create normalized flat field
    print "  Generating normalized flat field image"
    master_flat_image = chimera.masterflat(flat_image, master_flat_bias_image)

    ncubes = len(image_cubes)
    for i in range(ncubes):
        sci_file = image_cubes[i]

        print "  Reducing science image : ", sci_file

        sci_image, header = chimera.fitsread(sci_file, header=True)

        # Reduced the science frames
        sci_red_image, sci_avg_image = chimera.imreduce(sci_image, master_sci_bias_image, master_flat_image)

        # Write the reduced and average FITS image
        if output != "":
            red_file = output + "_final.fits"
            avg_file = output + "_avg.fits"
        else:
            red_file = sci_file.replace(".fits", "_final.fits")
            avg_file = sci_file.replace(".fits", "_avg.fits")

        if os.path.exists(red_file):
            os.remove(red_file)
        if os.path.exists(avg_file):
            os.remove(avg_file)

        chimera.fitswrite(sci_red_image, red_file, header=header)
        chimera.fitswrite(sci_avg_image, avg_file, header=header)

        print "  Reduced science image : ", red_file

    return
Example #6
0
def process(sci_files, sci_bias_file, flat_file, nskip, threshold,
            flat_bias_file, output):
    """
    Entry point function to process science images.
    
    Parameters
    ----------
    sci_files : string
        Science image file names
        
    sci_bias_file : string
        Bias image file name for science images
        
    flat_file : string
        Flat field file name
        
    skip : int
        Number of bias frames to skip before averaging the frames. Default is 0.
        
    threshold : float
        Threshold for normalized fat field (value between 0 and 1.0). 
        Default is 0.8.

    flat_bias_file : string
        Bias image file name for flat field images
                
    Returns
    -------
    None 
    """
    print "REDUCE: CHIMERA Image Reduction Rotuine"

    nskip = int(nskip)
    threshold = float(threshold)

    # Check if input is a string of FITS images or a text file with file names
    if sci_files[0] == "@":
        infile = sci_files[1:]

        if not os.path.exists(infile):
            print "  Not able to locate file %s" % infile

        image_cubes = []
        with open(infile, "r") as fd:
            for line in fd.readlines():
                if len(line) > 1:
                    image_cubes.append(line.replace("\n", ""))
    else:
        image_cubes = sci_files.split(",")

    # Read bias and flat field images
    sci_bias_image = chimera.fitsread(sci_bias_file)
    flat_image = chimera.fitsread(flat_file)

    if flat_bias_file != "":
        flat_bias_image = chimera.fitsread(flat_bias_file)
    else:
        flat_bias_image = sci_bias_image

    # Create master bias image
    print "  Generating master bias image"
    master_sci_bias_image = chimera.masterbias(sci_bias_image)
    master_flat_bias_image = chimera.masterbias(flat_bias_image)

    # Create normalized flat field
    print "  Generating normalized flat field image"
    master_flat_image = chimera.masterflat(flat_image, master_flat_bias_image)

    ncubes = len(image_cubes)
    for i in range(ncubes):
        sci_file = image_cubes[i]

        print "  Reducing science image : ", sci_file

        sci_image, header = chimera.fitsread(sci_file, header=True)

        # Reduced the science frames
        sci_red_image, sci_avg_image = chimera.imreduce(
            sci_image, master_sci_bias_image, master_flat_image)

        # Write the reduced and average FITS image
        if output != "":
            red_file = output + "_final.fits"
            avg_file = output + "_avg.fits"
        else:
            red_file = sci_file.replace('.fits', '_final.fits')
            avg_file = sci_file.replace('.fits', '_avg.fits')

        if os.path.exists(red_file):
            os.remove(red_file)
        if os.path.exists(avg_file):
            os.remove(avg_file)

        chimera.fitswrite(sci_red_image, red_file, header=header)
        chimera.fitswrite(sci_avg_image, avg_file, header=header)

        print "  Reduced science image : ", red_file

    return
Example #7
0
def process(infile, coords, fwhmpsf, sigma, aperture, annulus, dannulus,
            output, zmag, debug):
    """
    Entry point function to process science image.
    
    Parameters
    ----------
    infile : string
        Science image or list of science images
        
    coords : string
        Input text file with coordinates of stars
        
    fwhmpsf : float
        FWHM of the stelar psf in pixels
        
    sigma : float
        Sky background sigma
        
    annulus : int
        Inner sky annulus radius in pixels
        
    dannulus : int
        Radius of sky annulus in pixels 
        
    output : string
        Output file name
        
    zmag : string
        Photometric zero point
                
    Returns
    -------
    None 
    """
    print("PHOTOMETRY: CHIMERA Aperture Photometry Routine")

    fwhmpsf = float(fwhmpsf)
    sigma = float(sigma)
    annulus = int(annulus)
    dannulus = int(dannulus)

    # Check if input is a string of FITS images or a text file with file names
    if infile[0] == "@":
        infile = infile[1:]

        if not os.path.exists(infile):
            raise IOError("PHOTOMETRY: Not able to locate file %s. Stopping." %
                          infile)

        image_cubes = []
        with open(infile, "r") as fd:
            for line in fd.readlines():
                if len(line) > 1:
                    image_cubes.append(line.replace("\n", ""))
    else:
        image_cubes = infile.split(",")

    # Number of images
    ncubes = len(image_cubes)

    # Check if the input coordinates file exists. Take a tmp copy of the input
    # file and use that. Delete at the end of processing.
    if not os.path.exists(coords):
        raise IOError("Input coordinate file %s does not exist. Stopping." %
                      coords)
    else:
        tmp_coords = coords + ".tmp"
        iraf.copy(coords, tmp_coords)

    # Fields to extract from phot file
    fields = "XCEN,YCEN,CIER,MSKY,STDEV,NSKY,SIER,SUM,AREA,FLUX,MERR,PIER"

    total_phot_data = []
    img_sec = []
    for i in range(ncubes):
        sci_file = image_cubes[i]

        if not os.path.exists(sci_file):
            raise IOError("FITS image %s does not exist. Stopping." % sci_file)

        fpath, fname = os.path.split(sci_file)

        print("\n  Processing science image %s" % fname)

        # Instantiate an Aperphot object
        ap = chimera.Aperphot(sci_file, coords)

        # Set fwhmpsf, sigma, annulus. dannulus and zero point
        ap.fwhmpsf = fwhmpsf
        ap.sigma = sigma
        ap.annulus = annulus
        ap.dannulus = dannulus

        if zmag != "":
            ap.zmag = float(zmag)

        # Read the input FITS image
        if i == 0:
            img, imghdr = chimera.fitsread(ap.sci_file, header=True)
        else:
            img = chimera.fitsread(ap.sci_file)

        # Determine nominal aperture radius for photometry
        if i == 0:
            if aperture:
                nom_aper = float(aperture)
            else:
                nom_aper = ap.daocog()

            print("  Nominal aperture radius : %4.1f pixels" % nom_aper)

        # Perform aperture photometry on all the frames
        dtype = [
            ("DATETIME", "S25"),
            ("XCEN", "f4"),
            ("YCEN", "f4"),
            ("CIER", "i4"),
            ("MSKY", "f4"),
            ("STDEV", "f4"),
            ("NSKY", "i4"),
            ("SIER", "i4"),
            ("SUM", "f4"),
            ("AREA", "f4"),
            ("FLUX_ADU", "f4"),
            ("FLUX_ELEC", "f4"),
            ("FERR", "f4"),
            ("MAG", "f4"),
            ("MERR", "f4"),
            ("PIER", "i4"),
        ]
        phot_data = np.zeros([ap.nframes], dtype=dtype)
        for j in range(ap.nframes):
            print("    Processing frame number : %d" % (j + 1))

            outfile = sci_file.replace(".fits", "_" + str(j) + ".phot.1")
            ap.daophot(j + 1, tmp_coords, outfile, nom_aper)
            objcen = dump(outfile, "XCEN,YCEN")
            with open(tmp_coords, "w") as fd:
                fd.write(objcen + '\n')

            aperphot_data = dump(outfile, fields).split()

            phot_data[j]['DATETIME'] = ap.addtime(j * ap.kintime).isoformat()
            phot_data[j]['XCEN'] = float(aperphot_data[0])
            phot_data[j]['YCEN'] = float(aperphot_data[1])
            phot_data[j]['CIER'] = int(aperphot_data[2])
            phot_data[j]['MSKY'] = float(aperphot_data[3])
            phot_data[j]['STDEV'] = float(aperphot_data[4])
            phot_data[j]['NSKY'] = int(aperphot_data[5])
            phot_data[j]['SIER'] = int(aperphot_data[6])
            phot_data[j]['SUM'] = float(aperphot_data[7])
            phot_data[j]['AREA'] = float(aperphot_data[8])
            phot_data[j]['FLUX_ADU'] = float(aperphot_data[9])
            phot_data[j]['FLUX_ELEC'] = float(aperphot_data[9]) * ap.epadu
            phot_data[j]['MAG'] = ap.zmag - 2.5 * np.log10(
                phot_data[j]['FLUX_ELEC'] / ap.exptime)
            if aperphot_data[10] == 'INDEF':
                phot_data[j]['MERR'] = -10
            else:
                phot_data[j]['MERR'] = float(aperphot_data[10])
            phot_data[j]['PIER'] = int(aperphot_data[11])

            # Calculate error in flux - using the formula
            # err = sqrt(flux * gain + npix * (1 + (npix/nsky)) * (flux_sky * gain + R**2))
            phot_data[j]['FERR'] = np.sqrt(
                phot_data[j]['FLUX_ELEC'] + phot_data[j]['AREA'] *
                (1 + phot_data[j]['AREA'] / phot_data[j]['NSKY']) *
                (phot_data[j]['MSKY'] * ap.epadu + ap.readnoise**2))

            # Save a 51x51 image section of the object
            xmin, xmax = int(phot_data[j]['XCEN']) - 25, int(
                phot_data[j]['XCEN']) + 25
            ymin, ymax = int(phot_data[j]['YCEN']) - 25, int(
                phot_data[j]['YCEN']) + 25

            img_sec.append(img[j, ymin:ymax, xmin:xmax])

        # Save photometry of all the image cubes in a single file
        total_phot_data.append(phot_data)

        # If debug mode -
        # 1. save DAOPHOT phot files
        # 2. save individual phot data as npy file
        # 3. Plot light cuve for each data cube separatly

        if debug:
            # Save photometry data in numpy binary format
            print("  Saving photometry data as numpy binary")
            if output != "":
                npy_outfile = output + ".npy"
            else:
                npy_outfile = coords + "_phot.npy"

            if os.path.exists(npy_outfile):
                os.remove(npy_outfile)

            np.save(npy_outfile, phot_data)

            # Plot first pass light curve
            if plot_flag:
                print("  Plotting normalized light curve")
                if output != "":
                    plt_outfile = output + ".png"
                else:
                    plt_outfile = coords + "_lc.png"
                plotter(phot_data, ap.nframes, ap.kintime, plt_outfile)
        else:
            # Delete intermediate files is not debug mode
            iraf.delete(os.path.join(fpath, '*.phot.1'))

    # Convert the total_phot_data to array and reshape it
    print('  Saving consolidated photometry data...')
    total_phot_data_arr = np.concatenate(total_phot_data)

    # Save the array as npy file
    np.save(coords + "_total.phot.npy", total_phot_data_arr)

    # Save the image section with object as FITS file
    print('  Saving image section with object as FITS image...')
    img_sec_arr = np.asarray(img_sec)

    img_fname = coords + "_obj.fits"
    if os.path.exists(img_fname):
        os.remove(img_fname)

    chimera.fitswrite(img_sec_arr, coords + "_obj.fits", header=imghdr)

    # Delete temporary coordinate file
    if os.path.exists(tmp_coords):
        os.remove(tmp_coords)

    return
Example #8
0
def animate(image, nframes, vmin, vmax, scale, cmap, fps, outtype):
    """ 
    Generate animation from CHIMERA image cube.
    
    Parameters
    ----------
    image : string
        CHIMERA FITS image name
        
    nframes : int
        Number of frames to include in animation
        
    vmin, vmax : float
        Minimum and maximum pixel value
        
    scale : string
        Scale the images? (linear or log)
        
    cmap : string
        Matlab colormap
    
    fps : int
        Frames per second for mp4 animation
        
    outtype : string
        Save animation as gif or mp4
    
    Returns
    -------
    anim_fname : string
        Name of the animation file name.
    """
    
    print "ANIMATE: Animate CHIMERA 3D image cubes"
    
    nframes = int(nframes)
    vmin = int(vmin)
    vmax = int(vmax)
    fps = int(fps)
    
    # Create a matplotlib figure
    fig = plt.figure(figsize = (12,10))
    plt.axis("off")
    
    # Read FITS image
    img_data = chimera.fitsread(image)        
    
    # Display each frame to create an animation
    if nframes > img_data.shape[0]:
        nframes = img_data.shape[0]
    
    print "  Generating animation"
         
    ims = []
    for i in range(0, nframes):
        if scale == 'linear':
            im = plt.imshow(img_data[i,:,:], origin = "lower", cmap = plt.get_cmap(cmap), vmin = vmin, vmax = vmax)
        else:
            img_log = np.log10(img_data[i,:,:])
            im = plt.imshow(img_log, origin = "lower", cmap = plt.get_cmap(cmap), vmin = np.min(img_log), vmax = np.max(img_log))
        ims.append([im])

    # Animate the frames
    ani = animation.ArtistAnimation(fig, ims, interval = 50, blit = True, repeat_delay = 10)

    # Save the animation
    if outtype == "gif":
        anim_fname = image.replace(".fits", ".gif")
        ani.save(anim_fname, dpi = 100, writer = "imagemagick")
    else:
        anim_fname = image.replace(".fits", ".mp4")
        ani.save(anim_fname, fps = fps, dpi = 100, extra_args=['-vcodec', 'libx264'])
                
    return anim_fname
Example #9
0
def process(infile, coords, fwhmpsf, sigma, aperture, annulus, dannulus, output, zmag, debug):
    """
    Entry point function to process science image.
    
    Parameters
    ----------
    infile : string
        Science image or list of science images
        
    coords : string
        Input text file with coordinates of stars
        
    fwhmpsf : float
        FWHM of the stelar psf in pixels
        
    sigma : float
        Sky background sigma
        
    annulus : int
        Inner sky annulus radius in pixels
        
    dannulus : int
        Radius of sky annulus in pixels 
        
    output : string
        Output file name
        
    zmag : string
        Photometric zero point
                
    Returns
    -------
    None 
    """
    print "PHOTOMETRY: CHIMERA Aperture Photometry Routine"
    
    fwhmpsf = float(fwhmpsf)
    sigma = float(sigma)
    annulus = int(annulus)
    dannulus = int(dannulus)
    
    # Check if input is a string of FITS images or a text file with file names
    if infile[0] == "@":
        infile = infile[1:]
        
        if not os.path.exists(infile):
            raise IOError("PHOTOMETRY: Not able to locate file %s. Stopping." %infile)
        
        image_cubes = []
        with open(infile, "r") as fd:
            for line in fd.readlines():
                if len(line) > 1:
                    image_cubes.append(line.replace("\n", ""))
    else:
        image_cubes = infile.split(",")

    # Number of images
    ncubes = len(image_cubes)

    # Check if the input coordinates file exists. Take a tmp copy of the input
    # file and use that. Delete at the end of processing.
    if not os.path.exists(coords):
        raise IOError("Input coordinate file %s does not exist. Stopping." %coords)
    else:
        tmp_coords = coords + ".tmp"
        iraf.copy(coords, tmp_coords)
    

    # Fields to extract from phot file
    fields = "XCEN,YCEN,CIER,MSKY,STDEV,NSKY,SIER,SUM,AREA,FLUX,MERR,PIER"

    total_phot_data = []
    img_sec = []
    for i in range(ncubes):
        sci_file = image_cubes[i]
        
        if not os.path.exists(sci_file):
            raise IOError("FITS image %s does not exist. Stopping." %sci_file)
        
        fpath, fname = os.path.split(sci_file)
        
        print "\n  Processing science image %s" %fname

        # Instantiate an Aperphot object
        ap = chimera.Aperphot(sci_file, coords)
        
        # Set fwhmpsf, sigma, annulus. dannulus and zero point
        ap.fwhmpsf = fwhmpsf
        ap.sigma = sigma
        ap.annulus = annulus
        ap.dannulus = dannulus
        
        if zmag != "":
            ap.zmag = float(zmag)
        
        # Read the input FITS image
        if i == 0:
            img, imghdr = chimera.fitsread(ap.sci_file, header = True)
        else:
            img = chimera.fitsread(ap.sci_file)

        
        # Determine nominal aperture radius for photometry
        if i == 0:
            if aperture:
                nom_aper = float(aperture)
            else:
                nom_aper = ap.daocog()
            
            print "  Nominal aperture radius : %4.1f pixels" %nom_aper
           
           
        # Perform aperture photometry on all the frames
        dtype = [("DATETIME", "S25"),("XCEN", "f4"),("YCEN", "f4"),("CIER", "i4"),("MSKY", "f4"),("STDEV", "f4"),("NSKY", "i4"),("SIER", "i4"),("SUM", "f4"),("AREA", "f4"),("FLUX_ADU", "f4"),("FLUX_ELEC", "f4"),("FERR", "f4"),("MAG", "f4"),("MERR", "f4"),("PIER", "i4"),]
        phot_data = np.zeros([ap.nframes], dtype = dtype)
        for j in range(ap.nframes):
            print "    Processing frame number : %d" %(j+1)
             
            outfile = sci_file.replace(".fits", "_" + str(j) + ".phot.1")
            ap.daophot(j+1, tmp_coords, outfile, nom_aper)
            objcen = dump(outfile, "XCEN,YCEN")
            with open(tmp_coords, "w") as fd:
                fd.write(objcen + '\n')
            
            aperphot_data = dump(outfile, fields).split()
            
            phot_data[j]['DATETIME'] = ap.addtime(j * ap.kintime).isoformat()
            phot_data[j]['XCEN'] = float(aperphot_data[0])
            phot_data[j]['YCEN'] = float(aperphot_data[1])
            phot_data[j]['CIER'] = int(aperphot_data[2])
            phot_data[j]['MSKY'] = float(aperphot_data[3])
            phot_data[j]['STDEV'] = float(aperphot_data[4])
            phot_data[j]['NSKY'] = int(aperphot_data[5])
            phot_data[j]['SIER'] = int(aperphot_data[6])
            phot_data[j]['SUM'] = float(aperphot_data[7])
            phot_data[j]['AREA'] = float(aperphot_data[8])
            phot_data[j]['FLUX_ADU'] = float(aperphot_data[9])
            phot_data[j]['FLUX_ELEC'] = float(aperphot_data[9]) * ap.epadu
            phot_data[j]['MAG'] = ap.zmag - 2.5 * np.log10(phot_data[j]['FLUX_ELEC']/ap.exptime)
            if aperphot_data[10] == 'INDEF':
                phot_data[j]['MERR'] = -10
            else:
                phot_data[j]['MERR'] = float(aperphot_data[10])
            phot_data[j]['PIER'] = int(aperphot_data[11])
            
            # Calculate error in flux - using the formula
            # err = sqrt(flux * gain + npix * (1 + (npix/nsky)) * (flux_sky * gain + R**2))
            phot_data[j]['FERR'] = np.sqrt(phot_data[j]['FLUX_ELEC'] + phot_data[j]['AREA'] * (1 + phot_data[j]['AREA']/phot_data[j]['NSKY']) * (phot_data[j]['MSKY'] * ap.epadu + ap.readnoise**2))
                      
            # Save a 51x51 image section of the object
            xmin, xmax = int(phot_data[j]['XCEN']) - 25, int(phot_data[j]['XCEN']) + 25
            ymin, ymax = int(phot_data[j]['YCEN']) - 25, int(phot_data[j]['YCEN']) + 25            
            
            img_sec.append(img[j, ymin:ymax, xmin:xmax])


        # Save photometry of all the image cubes in a single file
        total_phot_data.append(phot_data)
                
        # If debug mode -
        # 1. save DAOPHOT phot files
        # 2. save individual phot data as npy file
        # 3. Plot light cuve for each data cube separatly
        
        if debug:
            # Save photometry data in numpy binary format
            print "  Saving photometry data as numpy binary"
            if output != "":
                npy_outfile = output + ".npy"
            else:
                npy_outfile = coords + "_phot.npy"
        
            if os.path.exists(npy_outfile):
                os.remove(npy_outfile)
            
            np.save(npy_outfile, phot_data)

        
            # Plot first pass light curve
            if plot_flag:
                print "  Plotting normalized light curve"
                if output != "":
                    plt_outfile = output + ".png"
                else:
                    plt_outfile = coords + "_lc.png"
                plotter(phot_data, ap.nframes, ap.kintime, plt_outfile)
        else:
            # Delete intermediate files is not debug mode
            iraf.delete(os.path.join(fpath, '*.phot.1'))    
                    
    # Convert the total_phot_data to array and reshape it
    print '  Saving consolidated photometry data...'
    total_phot_data_arr = np.concatenate(total_phot_data)
        
    # Save the array as npy file
    np.save(coords + "_total.phot.npy", total_phot_data_arr)

    # Save the image section with object as FITS file
    print '  Saving image section with object as FITS image...'
    img_sec_arr = np.asarray(img_sec)

    img_fname = coords + "_obj.fits"
    if os.path.exists(img_fname):
        os.remove(img_fname)
            
    chimera.fitswrite(img_sec_arr, coords + "_obj.fits", header = imghdr)
                        
    # Delete temporary coordinate file
    if os.path.exists(tmp_coords):
        os.remove(tmp_coords)
    
    return