###################################################################################
#                                                                                 #
#  summaryReconcile_VIPERS                                                        #
#  script to reconcile two summary files for a given VIPERS pointing              #
#  run wiht the command "python summaryReconcile_VIPERS sumFile1 sumFile2         #
#                                                                                 #
#  created by Marco Scodeggio, 08/10/2009                                         #
#  last modified 09/10/2009 - MS -                                                #
#                                                                                 #
###################################################################################

import string,os,sys

_THRESHOLD_DELTAZ = 0.001

def scanSummary(summaryContent):

    summarySlits={}

    # cycle through all the lines in summary file
    for line in summaryContent[4:]:

        # read obj information
        tmpString=string.split(line)
        slitNo=tmpString[0]
        objNo=tmpString[1]
        objID=tmpString[2]
        slitInfo='  %6s     %s   %7s  %7s  %7s  %7s ' % (tmpString[3],tmpString[4],tmpString[5],tmpString[6],tmpString[7],tmpString[8])
        try:
            zValue=float(tmpString[9])
        except:
            zValue=9.9999
        try:
            zMethod=tmpString[10]
        except:
            zMethod=None
        try:
            # string conversion requires the number to be transformed into float first
            zFlag=int(float(tmpString[11]))
        except:
            zFlag=None

        zComment=string.join(tmpString[12:])
        if len(zComment)==0:
            zComment='-'

        # if this is a slit already examined, add the new object info
        if summarySlits.has_key(slitNo):
            summarySlits[slitNo].append([objNo,objID,zValue,zFlag,zMethod,zComment,slitInfo])
        # if this is a new slit, add it to the slits dictionary
        else:
            summarySlits[slitNo]=[[objNo,objID,zValue,zFlag,zMethod,zComment,slitInfo],]

    print ' Analyzed %s slits' % slitNo
    return summarySlits

def main():
    if len(sys.argv) != 3:
        print 'Usage: python %s summaryFile_1 summaryFile_2' % sys.argv[0]
        print '      where summaryFile_1 is taken to be the reference file'
        print '      created by the primary reducer, that is to be matched to the seq file'

    else:
        sumFile1Name=sys.argv[1]
        sumFile2Name=sys.argv[2]

        # print info on the pointing being processed
        tmpString=string.split(sumFile1Name,'_')
        pointName=string.join(tmpString[1:5],'_')
        print '\n Processing pointing %s' % pointName

        # determine output file names
        tmpString=string.split(sumFile1Name,'_seq')
        tmpString[-1]='seq.summary'
        newSummaryName=string.join(tmpString,'_')
        newCommentsName1=newSummaryName[:-7]+'comments'
        newCommentsName2=newSummaryName[:-7]+'commentsTable'

        # check if the output files already exist....
        if os.path.isfile(newSummaryName):
            print '\n Error: output summary file %s already exist !!\n' % newSummaryName
            return 1

        # open the input files and read their content
        if os.path.isfile(sumFile1Name):
            sumF1=open(sumFile1Name,'r')
            sum1Cont=sumF1.readlines()
            sumF1.close()
        else:
            print '\n Error: input file %s does not exist !!\n' % sumFile1Name
            return 1

        if os.path.isfile(sumFile2Name):
            sumF2=open(sumFile2Name,'r')
            sum2Cont=sumF2.readlines()
            sumF2.close()
        else:
            print '\n Error: input file %s does not exist !!\n' % sumFile2Name
            return 1

        # scan the summary files to gather info for each slit data
        sum1Slits=scanSummary(sum1Cont)
        sum2Slits=scanSummary(sum2Cont)

        # check that the same slits appear in both summary files
        if len(sum1Slits) != len(sum2Slits):
            print '\n Error: the number of slits in the two input summary files does not match !!\n'
            return 1

        sum1NewSlits={}
        sum1NewComments={}
        sum1NewCommentsTable={}

        # comparison and matching cycle
        # for each slit in summary file nr.1
        for slitNum in sum1Slits.keys():
            sum1Objs=sum1Slits[slitNum]
            sum2Objs=sum2Slits[slitNum]

            # check that the same objects appear in both summary files
            if len(sum1Objs) != len(sum2Objs):
                print '\n Error: different number of objects in slit nr. %s !!!\n' % slitNum
                return 1

            sum1NewSlits[slitNum]=[]
            sum1NewComments[slitNum]=[]
            sum1NewCommentsTable[slitNum]=[]

            # for each object in the slit
            for ii in range(len(sum1Objs)):
                objNo=sum1Objs[ii][0]
                objID=sum1Objs[ii][1]
                zValue=sum1Objs[ii][2]
                zFlag=sum1Objs[ii][3]
                obj2No=sum2Objs[ii][0]
                obj2ID=sum2Objs[ii][1]
                z2Value=sum2Objs[ii][2]
                z2Flag=sum2Objs[ii][3]

                # compare the z values, and ALWAYS take the primary value
                newZ=zValue
                deltaZ=zValue-z2Value

                # if the z values agree.....
                if abs(deltaZ) < _THRESHOLD_DELTAZ*(1.+zValue):
                    match='good'

                    # if both flags exist....
                    if (zFlag or zFlag==0) and (z2Flag or z2Flag==0):

                        # if they are in agreement, take the maximum value
                        if abs(zFlag-z2Flag) <= 1:
                            if zFlag>=0:
                                newZflag=max(zFlag,z2Flag)
                            else:
                                newZflag=min(zFlag,z2Flag)
                            flagMatch='OK'

                        # if they don't agree take the primary and set flagMatch to NO
                        else:
                            newZflag=zFlag
                            flagMatch='NO'

                    # otherwise, if only the primary flag exists....
                    elif (zFlag or zFlag==0):
                        newZflag=zFlag
                        flagMatch='NO'

                    # and finally, if no primary flag exists.....
                    else:
                        newZflag=None
                        flagMatch='NO'

                # else, if the z values do not agree, take the primary flag value to match the primary z value
                else:
                    match='nomatch'
                    flagMatch='NO'
                    if (zFlag or zFlag==0):
                        newZflag=zFlag
                    else:
                        newZflag=None

                # correct zflag values so that they can be printed correctly
                if newZflag==None:
                    newZflag=-999

                # add the object data to the slit summary data
                sum1NewSlits[slitNum].append([objNo,objID,newZ,newZflag,sum1Objs[ii][4],sum1Objs[ii][5],sum1Objs[ii][6]])

                # prepare the comments about the mis-matches
                # first, the case of flags mismatch only
                if match=='good' and flagMatch=='NO':
                    commentString=' FLAGS MISMATCH'
                    if (zFlag or zFlag==0) and (z2Flag or z2Flag==0):
                        commentString+='\n Summary_1: flag=%d; Summary_2: flag=%d\n' % (zFlag,z2Flag)
                        commentTableString='%.4f  %4d  %.4f  %4d  %s / %s' % (zValue,zFlag,z2Value,z2Flag,sum1Objs[ii][5],sum2Objs[ii][5])
                    elif (zFlag or zFlag==0):
                        commentString+='\n Summary_1: flag=%d; Summary_2: flag=NONE\n' % zFlag
                        commentTableString='%.4f  %4d  %.4f  NONE  %s / %s' % (zValue,zFlag,z2Value,sum1Objs[ii][5],sum2Objs[ii][5])
                    elif (z2Flag or z2Flag==0):
                        commentString+='\n Summary_1: flag=NONE; Summary_2: flag=%d\n' % z2Flag
                        commentTableString='%.4f  NONE  %.4f  %4d  %s / %s' % (zValue,z2Value,z2Flag,sum1Objs[ii][5],sum2Objs[ii][5])
                    else:
                        commentString+='\n Both Summary files with flag=NONE\n'
                        commentTableString='%.4f  NONE  %.4f  NONE  %s / %s' % (zValue,z2Value,sum1Objs[ii][5],sum2Objs[ii][5])

                    sum1NewComments[slitNum].append((objNo, objID,commentString))
                    sum1NewCommentsTable[slitNum].append((objNo, objID,commentTableString))

                # second, the case of redshift mismatch
                elif match=='nomatch':
                    commentString='NO MATCH !!!'
                    if (zFlag or zFlag==0) and (z2Flag or z2Flag==0):
                        commentString+='\n Summary_1: z=%.4f with flag=%d; Summary_2: z=%.4f with flag=%d\n' % (zValue,zFlag,z2Value,z2Flag)
                        commentTableString='%.4f  %4d  %.4f  %4d  %s / %s' % (zValue,zFlag,z2Value,z2Flag,sum1Objs[ii][5],sum2Objs[ii][5])
                    elif (zFlag or zFlag==0):
                        commentString+='\n Summary_1: z=%.4f with flag=%d; Summary_2: z=%.4f with flag=NONE\n' % (zValue,zFlag,z2Value)
                        commentTableString='%.4f  %4d  %.4f  NONE  %s / %s' % (zValue,zFlag,z2Value,sum1Objs[ii][5],sum2Objs[ii][5])
                    elif (z2Flag or z2Flag==0):
                        commentString+='\n Summary_1: z=%.4f with flag=NONE; Summary_2: z=%.4f with flag=%d\n' % (zValue,z2Value,z2Flag)
                        commentTableString='%.4f  NONE  %.4f  %4d  %s / %s' % (zValue,z2Value,z2Flag,sum1Objs[ii][5],sum2Objs[ii][5])
                    else:
                        commentString+='\n Summary_1: z=%.4f with flag=NONE; Summary_2: z=%.4f with flag=NONE\n' % (zValue,z2Value)
                        commentTableString='%.4f  NONE  %.4f  NONE  %s / %s' % (zValue,z2Value,sum1Objs[ii][5],sum2Objs[ii][5])

                    sum1NewComments[slitNum].append((objNo, objID,commentString))
                    sum1NewCommentsTable[slitNum].append((objNo, objID,commentTableString))


        # writing of new summary and 2 comments files
        newSum=open(newSummaryName,'w')
        newCom=open(newCommentsName1,'w')
        newComTable=open(newCommentsName2,'w')

        for ii in range(4):
            newSum.write(sum1Cont[ii])

        newComTable.write('slit obj  ID       z_1   flag_1  z_2   flag_2  comment_1  / comment_2\n')

        # write the slits part
        for ii in range(1,len(sum1Slits)+1):
            currentSlit=sum1NewSlits[str(ii)]
            for objData in currentSlit:
                summaryString=('   %3d  %3s  %10s ' % (ii,objData[0],objData[1]),objData[6],'%7.4f' % objData[2],'%3s' % objData[4],'%5d  ' % objData[3],objData[5],'\n')
                newSum.write(string.join(summaryString,' '))

            if sum1NewComments.has_key(str(ii)):
                currentComm=sum1NewComments[str(ii)]
                for commData in currentComm:
                    commentString=('Slit %3d ' % ii, 'Object', commData[0],' ID',commData[1],':', commData[2],'\n')
                    newCom.write(string.join(commentString))
                currentComm2=sum1NewCommentsTable[str(ii)]
                for commData in currentComm2:
                    commentString=('%4d ' % ii, commData[0], commData[1], commData[2],'\n')
                    newComTable.write(string.join(commentString))


        newSum.close()
        newCom.close()
        newComTable.close()
        print ' Matched %d slits; all done !! \n' % (len(sum1Slits))


if __name__ == "__main__":
    main()
