""" Code to perform photometry on FITS frames

Context : SRP
Module  : SRPPhotometry.py
Version : 2.3.0
Author  : Stefano Covino
Date    : 18/08/2013
E-mail  : stefano.covino@brera.inaf.it
URL:    : http://www.merate.mi.astro.it/utenti/covino
Purpose : Manage the photometry of FITS files.

Usage   : SRPPhotometry [-e arg1] [-g arg2] [-h] [-H arg3 arg4] -i arg5 [-r arg6] [-s arg7] [-S] [-v] [-z arg8 arg9]
            -i Input FITS file list or single FITS file
            -g Gain (e-/ADU) for error estimate in photometry
            -s Saturation level (ADU) for frame(s)
            -e Exposure time (sec) for frame(s)
            -S ESO-Skycat output
            -r Radius (pixel) for aperture photometry
            -z Zero point and error for photometry
            -H FITS file header for exposure time, duration, airmass
                and filter [default: MJD-OBS EXPTIME AIRMASS FILTER]

History : (30/05/2003) First version.
        : (04/06/2003) Management of non-numeric exposure times.
        : (15/06/2003) Selection of stars for photometry.
        : (29/06/2003) Better search for exposure times.
        : (20/09/2003) Create SExtractor paramter files only if there are not anymore.
        : (10/10/2003) Aperture photometry in output file.
        : (23/12/2003) Minor correction and zero-point management.
        : (03/02/2005) Optparse.
        : (01/12/2005) CygWin porting.
        : (09/06/2006) Different out filename extension for skycat format.
        : (13/06/2006) Minor correction.
        : (20/10/2008) Minor correction.
        : (11/09/2009) Better pipes.
        : (21/05/2010) Better management of FITS header.
        : (26/08/2010) Minor improvements.
        : (28/09/2010) Better coding.
        : (30/09/2010) More input data.
        : (01/10/2010) Code cosmesis.
        : (13/10/2010) shutil not imported.
        : (15/10/2010) Better management of saturation level.
        : (26/10/2010) No more RA,DEC from sextractor.
        : (07/08/2011) Better cosmetics.
        : (20/08/2011) Exptime in output file.
        : (30/10/2011) Source ellipticity in output file.
        : (21/05/2012) Better import style.
        : (17/06/2012) Bug in Pipe import.
        : (11/02/2013) CLASS_STAR parameter in output and threshold in input.
        : (18/08/2013) Better management of optional parameters.
"""



import os, os.path, shutil, string
from optparse import OptionParser
import SRP.SRPConstants as SRPConstants
import SRP.SRPFiles as SRPFiles
import SRP.SRPUtil as SRPUtil
from SRP.SRPFits.GetHeaderValue import GetHeaderValue
from SRP.SRPFits.IsFits import IsFits
from SRP.SRPFrames import SExtractorConstants
from SRP.SRPSystem.Pipe import Pipe
from SRP.SRPSystem.Which import Which
from SRP.SRPFits.GetHeader import GetHeader
from SRP.SRPFrames.Pixel2WCS import Pixel2WCS


parser = OptionParser(usage="usage: %prog [-e arg1] [-g arg2] [-h] [-H arg3 arg4] -i arg5 [-r arg6] [-s arg7] [-t arg8] [-S] [-v] [-z arg9 arg10]", version="%prog 2.3.0")
parser.add_option("-i", "--inputlist", action="store", nargs=1, type="string", dest="fitsfilelist", help="Input FITS file list or single FITS file")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Fully describe operations")
parser.add_option("-g", "--gain", action="store", type="float", dest="gainvalue", help="Gain (e-/ADU) for error estimate in photometry")
parser.add_option("-s", "--saturation", action="store", type="float", dest="satvalue", help="Saturation level (ADU) for frame(s)")
parser.add_option("-e", "--exptime", action="store", type="float", dest="exptime", help="Exposure time (sec) for frame(s)")
parser.add_option("-S", "--skycat", action="store_true", dest="skycat", help="ESO-Skycat output")
parser.add_option("-r", "--radius", action="store", type="float", dest="radius", help="Radius (pixel) for aperture photometry")
parser.add_option("-t", "--threshold", action="store", type="float", dest="threshold", help="Threshold for detection and analysis")
parser.add_option("-z", "--zerpoints", action="store", nargs=2, type="float", dest="zpoints", help="Zero point and error for photometry")
parser.add_option("-H", "--headerinfo", action="store", nargs=4, type="string", dest="headinf", default=('MJD-OBS','EXPTIME','AIRMASS','FILTER'),help="FITS file header for exposure time, duration, airmass and filter [default: MJD-OBS EXPTIME AIRMASS FILTER]")
(options, args) = parser.parse_args()


if options.fitsfilelist:
    # Input file
    if os.path.isfile(options.fitsfilelist):
        # FITS file
        if IsFits(options.fitsfilelist):
            if options.verbose:
                print "Input FITS file is: %s" % options.fitsfilelist
            FITSfileflag = True
        # FITS file list
        else:
            f = SRPFiles.SRPFile(SRPConstants.SRPLocalDir,options.fitsfilelist,SRPFiles.ReadMode)
            f.SRPOpenFile()
            if options.verbose:
                print "Input FITS file list is: %s" % options.fitsfilelist
            FITSfileflag = False
        #                        
        flist = []
        nentr = 0
        while True:
            if FITSfileflag:
                flist.append(options.fitsfilelist)
                nentr = 1
                break
            else:
                dt = f.SRPReadFile()
                if dt != '':
                    flist.append(string.split(string.strip(dt))[0])
                    nentr = nentr + 1
                    if not os.path.isfile(flist[nentr-1]):
                        parser.error("Input FITS file %s not found" % flist[nentr-1])
                    if options.verbose:
                        print "FITS file selected: %s" % flist[nentr-1]    
                else:
                    break
        if not FITSfileflag:
            f.SRPCloseFile()
        # Fill data
        hflist = []
        mflist = []
        aflist = []
        wflist = []
        for i in range(len(flist)):
            # exptime
            eh = GetHeaderValue(flist[i],options.headinf[1])
            if eh[0] != None:
                try:
                    hflist.append(float(eh[0]))
                except:
                    hflist.append(1.0)
            else:
                hflist.append(1.0)
            # date
            eh = GetHeaderValue(flist[i],options.headinf[0])
            if eh[0] != None:
                try:
                    mflist.append(eh[0])
                except:
                    mflist.append(-99.0)
            else:
                mflist.append(-99.0)
            # airmass
            eh = GetHeaderValue(flist[i],options.headinf[2])
            if eh[0] != None:
                try:
                    aflist.append(float(eh[0]))
                except:
                    aflist.append(1.0)
            else:
                aflist.append(1.0)
            # airmass
            eh = GetHeaderValue(flist[i],options.headinf[3])
            if eh[0] != None:
                try:
                    wflist.append(eh[0])
                except:
                    wflist.append('Unknown')
            else:
                wflist.append('Unknown')
            #
    else:
        parser.error("Input FITS file or file list %s not found" % options.fitsfilelist)
    if options.gainvalue > 0.0:
        Gain = options.gainvalue
        if options.verbose:
            print "Gain value is %.2f" % Gain
    if options.satvalue > 0.0:
        Saturation = options.satvalue
        if options.verbose:
            print "Saturation level is %.1f" % Saturation
    else:
        Saturation = 1e7
    if options.radius > 0.0:
        Radius = options.radius
        if options.verbose:
            print "Aperture photometry radius is %.1f" % Radius
    zpl = [25.0,0.0]
    if options.zpoints:
        zpl[0] = options.zpoints[0]
        zpl[1] = options.zpoints[1]
    if options.verbose:
        print "Zero point is %.3f +/- %.3f" % (zpl[0], zpl[1])
    if options.threshold > 0.0:
        Threshold = options.threshold
        if options.verbose:
            print "Threshold is %.2f" % Threshold
    #
    if Which(SExtractorConstants.SRPsex) == None and Which(SExtractorConstants.SRPsex_cyg) == None:
        parser.error("SExtractor package not found.")
    # sextractor parameters
    pflcreated = False
    for i in range(len(SExtractorConstants.SexFName)):
        if not SRPFiles.IsReadable(SExtractorConstants.SexFName[i]):
            shutil.copyfile(os.path.join(SExtractorConstants.BasePath,SExtractorConstants.GenParSet[i]),os.path.join('.',SExtractorConstants.SexFName[i]))
            pflcreated = True
    if options.verbose and pflcreated:
        print "SExctractor parameter files created."
    # Process
    for i in range(len(flist)):
        if options.verbose:
            print "Processing file: %s..." % flist[i]
        if options.exptime:
            Exptime = options.exptime
        else:
            Exptime = hflist[i]
            if Exptime == None:
                Exptime = 1.0
        if options.verbose:
            print "Exposure time is %.1f" % Exptime
        #
        root,ext = os.path.splitext(flist[i])
        parstr1 = SExtractorConstants.SRPsex+' '+flist[i]+' -c SRP.sex '
        parstr2 = " "
        if options.gainvalue:
            parstr2 = parstr2 + " -GAIN %.2f " % (Gain)
        if options.satvalue:
            parstr2 = parstr2 + " -SATUR_LEVEL %.1f " % (Saturation)
        if options.radius:
            parstr2 = parstr2 + " -PHOT_APERTURES %.1f " % (Radius)
        if options.threshold:
            parstr2 = parstr2 + " -DETECT_THRESH %.2f -ANALYSIS_THRESH %.2f" % (Threshold, Threshold)
        #print parstr1+parstr2
        stardata = Pipe(parstr1+parstr2)
        if stardata == None:
            parser.error("%s not a FITS file." % flist[i])
        starlist = SRPUtil.getStarData(string.split(stardata,os.linesep), Exptime, zpl, mflist[i], aflist[i], wflist[i])
        if options.skycat:
            g = SRPFiles.SRPFile(SRPConstants.SRPLocalDir, root+SRPConstants.SRPPhotomFileSky, SRPFiles.WriteMode)
        else:
            g = SRPFiles.SRPFile(SRPConstants.SRPLocalDir, root+SRPConstants.SRPPhotomFile, SRPFiles.WriteMode)
        g.SRPOpenFile()
        if options.skycat:
            g.SRPWriteFile("serv_type: catalog"+os.linesep)
            g.SRPWriteFile("long_name: SRP catalog for file %s" % flist[i]+os.linesep)
            g.SRPWriteFile("short_name: %s" % root+SRPConstants.SRPPhotomFileSky+os.linesep)
            g.SRPWriteFile("url: ./%s" % root+SRPConstants.SRPPhotomFileSky+os.linesep)
            g.SRPWriteFile("id_col: 0"+os.linesep)
            g.SRPWriteFile("x_col: 1"+os.linesep)
            g.SRPWriteFile("y_col: 2"+os.linesep)
            g.SRPWriteFile("symbol: {} circle 4"+os.linesep)
            g.SRPWriteFile("Id\tX\tY\tRA\tDEC\tmag_ap\temag_ap\tsky\tfmax\tmag\temag\tFWHM\tMJD\tAirmass\tFilter\tExptime\tEllipticity\tClassification"+os.linesep)
            g.SRPWriteFile("---------"+os.linesep)
        ndetec = 0
        #
        # RA,DEC from sextractor not correct.
        fhed = GetHeader(flist[i])[0]
        pixc = []
        for l in range(len(starlist)):
            pixc.append((starlist[l].X,starlist[l].Y))
        fc = Pixel2WCS(fhed,pixc)
        # file header
        for l in range (len(starlist)):
            if starlist[l].fmax < Saturation:
                starlist[l].RA = fc[l][0]
                starlist[l].DEC = fc[l][1]
                g.SRPWriteFile(starlist[l])
                ndetec = ndetec + 1
        if options.skycat:
            g.SRPWriteFile("EOD"+os.linesep)
        g.SRPCloseFile()
        if options.verbose:
            print "%d objects selected." % ndetec
        else:
            if options.skycat:
                print ndetec, root+SRPConstants.SRPPhotomFileSky
            else:
                print ndetec, root+SRPConstants.SRPPhotomFile 
        if options.verbose:
            if options.skycat:
                print "Photometric results reported in file %s" % root+SRPConstants.SRPPhotomFileSky
            else:
                print "Photometric results reported in file %s" % root+SRPConstants.SRPPhotomFile
else:
    parser.print_help()
