#!/usr/bin/python3

# Use astrometry to guide a CDK20 with Apogee U16 camera science images
# Fast astrometry depends on previously known image scale and approximate image center
# Outputs to status files and uses xpatel to correct pointing
# Requires hard-coded tmp directory and image scales:  see line 57


# Copyright (c) 2017 observer Kielkopf and Rhodes Hart        
# kielkopf@louisville.edu                                                  
#                                                                          
#                                                                          
# Date: September 24, 2017                                              
# Version: 1.2                                                           
#                                                                          
# This file is part of XmCCD and XmTel for the CDK20                                             


# History 
#   2017-02-24  1.0 First code optimized for CDK20S guide feedback
#   2017-05-14  1.1 Python 3 version for CDK20N
#   2017-05-19  1.1 Seed from telcoords and write rahr decdeg to telcenter
#   2017-09-24  1.2 Modified for the CDK20N
#   2017-09-30  1.3 Modified not to update files.  Uses previous guidecoords and guiderotate as reference.

import sys
import os
from subprocess import Popen, PIPE
import string
import time
import math
import re
import glob

# These lines have to be set for pointing correction control
# Also check astrometry shell command in line 65

pixscale = 0.53
del_dec_max = 40
del_ra_max = 40
verbose = True

if len(sys.argv) == 1:
  telcoordsfp = open("/usr/local/observatory/status/guidecoords", 'r')
  telcoordstext = telcoordsfp.readlines()
  for line in telcoordstext:
    try:
      entry = line.strip().split()
      rahr = float(entry[0])
      radeg = 15.*rahr
      decdeg = float(entry[1]) 
    except:
      radeg = 0.
      decdeg = 0.
else:
  print (" ")
  print ("Usage with decimal coordinate hints: guide_by_astrometry.py image.fits [rahr dec]")
  print ("Reads system /usr/local/observatory/status/telcoords unless given hints")
  print ("Issues guiding correction commands")
  sys.exit("Updates status files from center of image field")  

# Talk to astrometry and find coordinates
# Requires temporary working file directory /home/observer/data/tmp

file_name = max(glob.iglob('*.fits'), key=os.path.getctime)

print ("Running astrometry on ", file_name, " seeded from guidecoords status file")
print ("")

astrometry = "/usr/local/astrometry/bin/solve-field  --no-plots  -z 2" \
  " --dir /home/john/data/tmp/" \
  " --scale-units arcsecperpix --scale-low 0.52 --scale-high 0.55" \
  " --radius 1.0 --ra %f --dec %f"  \
  " --overwrite --new-fits none  %s" % (radeg, decdeg, file_name)


p1 = Popen( astrometry , shell=True, stdout=PIPE)
p1.wait()
output = str(p1.communicate()[0], 'utf-8')


# Parse stdout in phases

scratch, center = output.split("Dec D:M:S) = (",1)

ratxt = center.split()[0]
dectxt = center.split()[1]
rotationtxt = center.split()[13]

rahr =  re.findall(r"[-+]?\d*\.\d+|\d+",ratxt.split(":")[0])
ramin = re.findall(r"[-+]?\d*\.\d+|\d+",ratxt.split(":")[1])
rasec = re.findall(r"[-+]?\d*\.\d+|\d+",ratxt.split(":")[2])

decdeg = re.findall(r"[-+]?\d*\.\d+|\d+",dectxt.split(":")[0])
decmin =  re.findall(r"[-+]?\d*\.\d+|\d+",dectxt.split(":")[1])
decsec =  re.findall(r"[-+]?\d*\.\d+|\d+",dectxt.split(":")[2])

rotation = re.findall(r"[-+]?\d*\.\d+|\d+",rotationtxt)

decsign = 1.
if ( float(decdeg[0]) < 0. ):
  decsign = -1.
  
ra = (float(rahr[0]) + float(ramin[0])/60. + float(rasec[0])/3600.)
dec = decsign*(abs(float(decdeg[0])) + float(decmin[0])/60. + float(decsec[0])/3600.)
rot = float(rotation[0])


# Read target center from guide coords status file or another file of choice

teltargetfp = open("/usr/local/observatory/status/guidecoords", 'r')
teltargettext = teltargetfp.readlines()
for line in teltargettext:
  try:
    entry = line.strip().split()
    ra_ref = float(entry[0])
    dec_ref = float(entry[1])
    teltargetfp.close()
  except:
    teltargetfp.close()
    print ("Complete target entry not available.  Check /usr/local/observatory/status/guidecoords rahr decdeg .")
    print ("Telescope pointing has not been updated.")
    exit()
    

# Read target rotation from guide rotate status file

telrotatefp = open("/usr/local/observatory/status/guiderotate", 'r')
telrotatetext = telrotatefp.readlines()
for line in telrotatetext:
  try:
    entry = line.strip().split()
    rot_ref = float(entry[0])      
    telrotatefp.close()
  except:
    telrotatefp.close()
    print ("Complete target rotation not available.  Check /usr/local/observatory/status/guiderotate rotdeg .")
    print ("Telescope rotation will not be  be updated.")
    rot_ref = rot 


# Find coordinate pointing errors in arcseconds for use in telescope controls
# Start with current and reference ra in hours and dec in degrees
    
del_ra_hrs = ra - ra_ref

# Handle instance where the correction or reference is sitting at 0 hr

del_ra = -(ra - ra_ref)*60.*60.*15.
del_dec = -(dec - dec_ref)*60.*60.

# Find rotation error in degrees

del_rot_deg = rot - rot_ref
         
# Use a guiding scale for telescope corrections from arcseconds per pixel

del_ra_pix = int( del_ra / pixscale )
del_dec_pix = int( del_dec /pixscale )

# Print diagnostics 

if verbose:
  print ("delta ra (pixels)  : ", del_ra_pix )
  print ("delta dec (pixels) : ", del_dec_pix  )
  print ("delta rot (deg)   : ", del_rot_deg )

# Block out of range error
  
if ( abs(del_ra_pix) > del_ra_max ) or ( abs(del_dec_pix) > del_dec_max ):
  print ("Warning: guiding errors exceed allowed limits.")
  print ("No corrections will be made.")
  exit()
  


rasteps = abs(del_ra_pix)
decsteps = abs(del_dec_pix)

# Nudge the telescope back to guidecenter  based on new center of field
# Rotation corrections are not set in this program but would go here if needed

if (del_dec > 0):
  # Image center appears to be north of the reference
  guidecmd = 'xpaset -p tel move north %d' % (decsteps,) 
  Popen(guidecmd, shell=True, stdout=PIPE).wait()
elif (del_dec < 0):
  # Image center appears to be south of the reference
  guidecmd = 'xpaset -p tel move south %d' % (decsteps,) 
  Popen(guidecmd, shell=True, stdout=PIPE).wait()
else:
  pass  

if (del_ra > 0):
  # Image center appears to be east of the reference
  guidecmd = 'xpaset -p tel move east %d' % (rasteps,) 
  Popen(guidecmd, shell=True, stdout=PIPE).wait()
elif (del_ra < 0):
  # Image center appears to be west of the reference
  guidecmd = 'xpaset -p tel move west %d' % (rasteps,) 
  Popen(guidecmd, shell=True, stdout=PIPE).wait()
else:
  pass  




