#!/usr/bin/env python
# Program: deimos_guider_dss
# - Generates DEIMOS guider image overlay on DSS a image given a dsimulator
# ascii file output. Results are rendered in an html page.
# Usage:
#       Change to directory with your mask designs
#       deimos_guider_dss *.mask
# External modules needed:
#       PIL - http://www.pythonware.com/products/pil/
#
# DKM 2003-03-28

import httplib, urllib
import Image, ImageDraw, ImageFont, ImageEnhance, ImageChops
import math

class selectedObject:
    def __init__(self, objectlist):
        self.id = objectlist[0]
        self.ra = objectlist[1]
        self.dec = objectlist[2]
        self.equinox = objectlist[3]
        self.magnitude = objectlist[4]
        self.passband = objectlist[5]
        self.priority_code = objectlist[6]
        self.sample = objectlist[7]
        self.select_flag = objectlist[8]
        self.pa_slit = objectlist[9]
        self.l1 = objectlist[10]
        self.l2 = objectlist[11]
        self.slitwidth = objectlist[12]

class guideStarObject(selectedObject):
    def __init__(self, objectlist):
        selectedObject.__init__(self, objectlist)
        self.xTV = None
        self.yTV = None

class Mask:
    def __init__(self):
        self.selectedObjects = []
        self.alignmentStars = []
        self.guideStars = []

    def readMaskFile(self, maskfile):
        self.file = maskfile
        f = open(self.file,"r")
        l = f.readlines()
        f.close()
        c = l[1].split()
        self.name = c[0]
        self.ra = c[1]
        self.dec = c[2]
        self.equinox = float(c[3])

	print 'Name='+self.name
	print ' RA='+self.ra
	print ' Dec='+self.dec
	print ' Eq=',self.equinox

	# mod 2002-may-20
	if c[4] == 'PA=':
	    self.pa = float(c[5])
	else:
	    self.pa = float(c[4].split('=')[1])

        c = l[3].split()
        self.guider_ra = c[3]
        self.guider_dec = c[4]
        a = l.index("# Selected Objects:\n")+2
        b = l.index("# Selected Guide Stars:\n")-1
        for r in l[a:b]:
            c = r.split()
            n = len(c)
            if n < 13:
                for i in range(13-n):
                    c.append(None)
            fc = [3, 4, 10, 11, 12]
            ic = [6, 7, 8]
            for i in range(n):
                if i != None:
                    if i in fc:
                        c[i] = float(c[i])
                    if i in ic:
                        c[i] = int(c[i])
                    if i == 9:
                        if c[i] == 'INDEF':
                            c[i] = None
                        else:
                            c[i] = float(c[i])
            so = selectedObject(c)
            if so.priority_code == -1:
                self.guideStars.append(guideStarObject(c))
            elif so.priority_code == -2:
                self.alignmentStars.append(selectedObject(c))
            else:
                self.selectedObjects.append(selectedObject(c))
        a = l.index("# Selected Guide Stars:\n")+2
	try:
	    b = l.index("# Non-Selected Objects:\n")-1
	except ValueError:
	    b = len(l)-1
        for r in l[a:b]:
            c = r.split()
            for gs in self.guideStars:
                if gs.id == c[1]:
                    gs.xTV = float(c[6])
                    gs.yTV = float(c[7])
        for gs in self.guideStars:
            if gs.xTV == None or gs.yTV == None:
                self.guideStars.remove(gs)
                    
def drawbox(pil_draw_obj, x, y, w, l):
    x1 = x - w/2
    y1 = y - w/2
    x2 = x + w/2
    y2 = y + w/2
    pil_draw_obj.rectangle((x1,y1,x2,y2))

def drawcircle(pil_draw_obj, x, y, r):
    pil_draw_obj.arc((x-r, y-r, x+r, y+r), 0, 360)

def drawcompass(pil_draw_obj, x, y, angle):
    d2r = math.pi/180.0
    if angle < 0.0:
        angle = angle + 360.0
    pa = (180 + angle)*d2r
    r = 25
    # North vector
    dx = r*math.cos(pa)
    dy = r*math.sin(pa)
    x1 = x + dx
    y1 = y + dy
    tx1 = x + dx*1.5
    ty1 = y + dy*1.5
    pil_draw_obj.line((x, y, x1, y1))
    pil_draw_obj.text((tx1, ty1), 'N')
    # East vector
    dx = r*math.cos(pa+90*d2r)
    dy = r*math.sin(pa+90*d2r)
    x2 = x - dx
    y2 = y - dy
    tx2 = x - dx*1.5
    ty2 = y - dy*1.5
    pil_draw_obj.line((x, y, x2, y2))
    pil_draw_obj.text((tx2, ty2), 'E')

def rotxy(x, y, angle):
    # angle must be in radians
    rx = x*math.cos(angle) - y*math.sin(angle)
    ry = x*math.sin(angle) + y*math.cos(angle)
    return [rx, ry]

colors = {'red':        (255,   0,   0),
          'yellow':     (255, 255,   0),
          'green':      (  0, 255,   0),
          'cyan':       (  0, 255, 255),
          'blue':       (  0,   0, 255),
          'pink':       (255,   0, 255),
          'white':      (255, 255, 255),
          'black':      (  0,   0,   0),
          'light_grey': (224, 224, 224),
          'grey':       (200, 200, 200),
          'dark_grey':  ( 96,  96,  96), 
          'cbu_red':    (146,  21,  47),
          'navy_blue':  (  0,   0, 128)}

if __name__ == '__main__':
    import os, sys, glob
    import dss
    import math
    import fits
    import fits2pil
    import re

    if len(sys.argv) == 1:
        print 'Usage: deimos_guider_dss *.mask'
        sys.exit()
    else:
        mlist = sys.argv[1:]
    slf = open('starlist','w')
    fontpath = '/sol/apps2/kroot/instr/python/deimos_guider/Fonts'

    guider_scale = 0.207           # guider camera scale arcsec/pix
    guider_ccd = [212, 212]        # guider camera size in arcsec
    
    # build html for master guider image list
    gdoc = []
    gdoc.append('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">\n')
    gdoc.append('<HTML>\n<HEAD>\n<TITLE>Guider Images</TITLE>\n</HEAD>\n')
    gdoc.append('<BODY BGCOLOR="#FFFFFF">\n<H1>Guider Images</H1>\n')
    gdoc.append('<OL type="square">\n<OL type="square">')
    dss = dss.DSS()
    for ml in mlist:
        input = ml
        # make mask instanace
        m = Mask()
        try:
            m.readMaskFile(input)
        except Exception, err:
            print 'Unable to read mask file: '+ml
            print err

        # set output file names
        output = m.name
        fitsout = output+'_dss.fits'
        gifout = output+'_dss.gif'
        guider_gifout = output+'_guider_dss.gif'
        htmlout = output+'_dss.html'
        
        # add mask name to guider master list
        gdoc.append('<LI><A HREF="%s">%s</A>' % (htmlout, m.name))
        
        # build starlist
        sra = m.ra.split(':')
        sdec = m.dec.split(':')
        srah = int(sra[0])
        sram = sra[1]
        sras = sra[2]
        sdech = int(sdec[0])
        sdecm = sdec[1]
        sdecs = sdec[2]
        if sdech == 0:
            sdech = -00
        seqnx = str(m.equinox).split('.')[0]
        slist = (m.name,srah,sram,sras,'',sdech,sdecm,sdecs,seqnx)
        if sdech < 0:
            sformat = '%-16s %02i %-2s %-4s %3s %03i %-2s %-4s %10s\n'
        else:
            sformat = '%-16s %02i %-2s %-4s %4s %02i %-2s %-4s %10s\n'
        slf.write(sformat % slist)
        
        # get DSS image, draw guider, mark stars
        # Note: Assumed that DSS images are from 2nd generation red images
        # which are scanned at a resolution of 1"/pix.
        gra = m.guider_ra
        gdec = m.guider_dec
        try:
            dss.getDSSImage(gra, gdec, fitsout)
        except IOError, error:
            print error
            sys.exit()
        dss.getWCS(fitsout)
        fim = fits.FITS(fitsout, 'r')
        imfits2pil = fits2pil.arrayToGreyImage(fim.data)
        im = imfits2pil.convert('RGB')
        imskypa = dss.skyPA()
        rotate = 91.4 - m.pa
        gxy = (im.size[0]/2, im.size[1]/2)
        im = im.rotate(rotate, Image.BICUBIC)
        draw = ImageDraw.Draw(im)
        font=ImageFont.load(fontpath+"/helvR08.pil")
        draw.setfont(font)
        draw.setink(colors['black'])
        draw.line((gxy[0]-106, gxy[1]+23, gxy[0]+106, gxy[1]+23))
        drawbox(draw, gxy[0], gxy[1], 212, 212)
        for gs in m.guideStars:
            gsx, gsy = dss.rd2xy(gs.ra, gs.dec)
            radrot = rotate*(math.pi/180.0)
            gsrxy = rotxy(gsx - gxy[0], gsy - gxy[1], radrot)
            gsrxy[0] = gsrxy[0] + gxy[0]
            gsrxy[1] = im.size[1] - (gxy[1] + gsrxy[1])
            draw.setink(colors['red'])
            draw.text((gsrxy[0]+20, gsrxy[1]-10), gs.id.upper())
            drawcircle(draw, gsrxy[0], gsrxy[1], 10)
        draw.setink(colors['blue'])
        drawcompass(draw, gxy[0]-116, gxy[1]-116, m.pa-imskypa)
        font=ImageFont.load(fontpath+"/helvR12.pil")
        draw.setfont(font)
        im = im.crop((gxy[0]-160, gxy[1]-160, gxy[0]+160, gxy[1]+160))
        im.save(guider_gifout)
        
        # build html for guider image
        doc = []
        doc.append('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">\n')
        doc.append('<HTML>\n<HEAD>\n<TITLE>%s</TITLE>\n</HEAD>\n' % m.name)
        doc.append('<BODY BGCOLOR="#FFFFFF">\n')
        doc.append('<H1 align="center">%s</H1>\n' % m.name)
        doc.append('<H3 align="center">Mask Coordinates</H3>\n')
        doc.append('<center><TABLE border=1 cellpadding=4 cellspacing=1 width="95%">\n')
        doc.append('<center><TABLE border=1 cellpadding=4 cellspacing=1 \
        width="95%"><TR Align=center> <TH ColSpan=1 \
        bgcolor="#B0C4DE">RA</TH><TH ColSpan=1 \
        bgcolor="#B0C4DE">DEC</TH><TH ColSpan=1 \
        bgcolor="#B0C4DE">Equinox</TH><TH ColSpan=1 \
        bgcolor="#B0C4DE">PA</TH></TR>\n')
        doc.append('<TR><TD Align=center  bgcolor="#E0F4FF">%s</TD>\n' % m.ra)
        doc.append('<TD Align=center  bgcolor="#E0F4FF">%s</TD>\n' % m.dec)
        doc.append('<TD Align=center  bgcolor="#E0F4FF">%4.1f</TD>\n' % m.equinox)
        doc.append('<TD Align=center  bgcolor="#E0F4FF">%3.1f</TD>\n' % m.pa)
        doc.append('</TR>\n</TABLE><P>\n</center>\n')
        doc.append('<H3 align="center">Guider Image</H3>\n')
        doc.append('<center><IMG src="%s" height="320" \
        width="320" alt="%s"></center>\n' % (guider_gifout, guider_gifout))
        doc.append('<H3 align="center">Guider Stars</H3>\n')
        doc.append('<center><TABLE border=1 cellpadding=4 cellspacing=1 \
        width="95%"> <TR Align=center> <TH ColSpan=1 \
        bgcolor="#B0C4DE">ID</TH><TH ColSpan=1 \
        bgcolor="#B0C4DE">RA</TH><TH ColSpan=1 bgcolor="#B0C4DE">DEC</TH><TH \
        ColSpan=1 bgcolor="#B0C4DE">Equinox</TH><TH ColSpan=1 \
        bgcolor="#B0C4DE">Mag</TH><TH ColSpan=1 bgcolor="#B0C4DE">Band</TH><TH ColSpan=1 \
        bgcolor="#B0C4DE">xTV</TH><TH ColSpan=1 bgcolor="#B0C4DE">yTV</TH></TR>\n')
        # mark guider stars
        for gs in m.guideStars:
            doc.append('<TR><TD Align=center  bgcolor="#E0F4FF">%s</TD>\n' % gs.id)
            doc.append('<TD Align=center  bgcolor="#E0F4FF">%s</TD>\n' % gs.ra)
            doc.append('<TD Align=center  bgcolor="#E0F4FF">%s</TD>\n' % gs.dec)
            doc.append('<TD Align=center  bgcolor="#E0F4FF">%4.1f</TD>\n' % gs.equinox)
            doc.append('<TD Align=center  bgcolor="#E0F4FF">%2.1f</TD>\n' % gs.magnitude)
            doc.append('<TD Align=center  bgcolor="#E0F4FF">%s</TD>\n' % gs.passband)
            doc.append('<TD Align=center  bgcolor="#E0F4FF">%4.1f</TD>\n' % gs.xTV)
            doc.append('<TD Align=center  bgcolor="#E0F4FF">%4.1f</TD></TR>\n' % gs.yTV)
        doc.append('</TABLE><P>\n</center>\n</BODY> </HTML>')
        maskdoc = open(htmlout, 'w')
        for l in doc:
            maskdoc.write(l)
        maskdoc.close()
    gdoc.append('<LI><A HREF="starlist">starlist</A>\n')
    gdoc.append('</OL>\n</OL>\n</BODY> </HTML>')
    guiderdoc = open('guider_images.html', 'w')
    for l in gdoc:
        guiderdoc.write(l)
    guiderdoc.close()
    cdir = os.getcwd()
    print 'Point your browser to -> file://'+cdir+'/guider_images.html'
