#!/opt/conda/envs/ciao-4.17.0/bin/python3
# coding: utf-8
# 
#  Copyright (C) 2012,2017  Smithsonian Astrophysical Observatory
#
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License along
#  with this program; if not, write to the Free Software Foundation, Inc.,
#  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#


# 11/2012 - initial version
# 3/1/2017- bug JIRA CIAO-14 :  problem with python 3.5.1 ( byte .vs. string ; etc.. )

import os
import sys
import paramio as pio
from math import sqrt
from cxcdm import *       

class _TCMD() :
   def get_params( s, tool, mode="rw", args=None ):
       if None != args:
          try:
             pf = pio.paramopen( tool, mode, args )
          except:
             s.error_out("ERROR: problem with paramopen.\n")
       else:
          try:
             pf = pio.paramopen( tool, mode )
          except:
             s.error_out("ERROR: problem with paramopen.\n")
       tpars = pio.plist( pf )

       values = []
       [ values.append( pio.pget(pf, pp ) ) for pp in tpars ]

       s.pars = {}
       s.pars = dict(zip(tpars,values))
       pio.paramclose( pf )

   ## display message
   def display_msg( s, msg ) :
      sys.stderr.write( msg +"\n" )

   ## error out w/ message
   def error_out( s, msg ) :
      s.display_msg( msg )
      os._exit(1)

   ## 2.3.3. read key values from the input file src1a ( produced by tg_findzo)
   def src1aKeys( s ) :
     try :
        s.inBlk = dmTableOpen( s.pars["infile"])
     except :
        s.error_out("ERROR: can't open the table file "+s.pars["infile"]+".\n" )

     s.k_v = {}
     list_s = ["HDUCLAS3"]
     list_f = ["TIMEDEL","NET_COUNTS","COUNT_TG","COUNT_ST"]
     for kp in list_s+list_f :
       try :
          _dd, _vv  = dmKeyRead( s.inBlk, kp )
          if kp in list_f :
             s.k_v[ kp ] = (float)(_vv)
          else :    # list_s :
             s.k_v[ kp ] = _vv.upper().decode(encoding='UTF-8')     # byte->str ; 3/1/2017
       except :
          s.error_out("ERROR: "+kp+" is missing from '"+ s.pars["infile"] +"'\n" )   # 3/1/2017

     s.verify_src1a_keys()

     # set exptime
     try :
        _dd, _vv  = dmKeyRead( s.inBlk, "EXPOSURE" )  
     except :
        try :
           _dd, _vv  = dmKeyRead( s.inBlk, "LIVETIME" )
        except :
           _vv = 1.0
     s.exptime = _vv
     dmDatasetClose( dmBlockGetDataset( s.inBlk ))
   # end: src1aKeys

   ## 2.3.1 Error out if HDUCLAS3 is not "FINDZO"
   def verify_src1a_keys ( s ) :
      uv = s.k_v[ "HDUCLAS3" ]
      if  uv!="FINDZO" :
         s.error_out("ERROR: the value of HDUCLAS3 in the file '"+s.pars["infile"]+"' must be 'FINDZO'.\n" )
         s._exit(1)

#end: _TCMD


class TCMD(_TCMD) :
   def __init__(s, tname ) :
      ## 2.3.2. constants
      s.snr_streak_min = 20.0      # below this, don't use tg_findzo
      s.snr_grating_min = 100.0    # signal-to-noise limit for grating spectrum
      s.cpf_fzo_tg_limit_01 = 0.90 # below this => tgdetect
      s.cpf_fzo_zo_limit_02 = 0.55 # below this => tgdetect
      s.cpf_fzo_tg_limit_02 = 6.00 # above this => tg_findzo # * UNUSED *
      s.cpf_fzo_zo_limit_01 = 0.90 # above this => tg_findzo # * UNUSED *

      s.cpf_ratio_zo_tg_limit = 0.06

      s.snr_streak_to_grating_min = 0.37
      s.snr_streak_to_grating_max = 0.99
      s.snr_grating_01 = 84.0
      s.snr_grating_02 = 245

      s.get_params( tname, "rwL", sys.argv )       
      s.tname = tname
      pio.pset( s.tname, "method","unknown")
#end: TCMD


# --- main code 
def main() :
   p = TCMD("tg_choose_method")

   ## 2.3.3. Read the header and data of the tg_findzo src1a file
   #  ( including TIMEDEL, EXPSOURE, NET_COUNTS, COUNT_TG )
   #  and set exposure, counts, and rate values:
   p.src1aKeys()
        
   ## compute the following values :
   K_rate = p.k_v["TIMEDEL"] / p.exptime  # rate constant, from header keywords
   R_zo = p.k_v["NET_COUNTS"] * K_rate    # zo rate, from src1a binary table column
   C_tg = p.k_v["COUNT_TG"]               # grating counts, from header keyword
   R_tg = C_tg * K_rate                   # grating rate
   C_st = p.k_v["COUNT_ST"]               # streak counts, from header keyword
   R_st = C_st * K_rate                   # streak rate

   if ( sqrt( C_st ) < p.snr_streak_min ) :
      ## 2.3.4.  If the streak is too faint, use tgdetect:
      pio.pset( p.tname, "method", "tgdetect" )  
   else :
      ## 2.3.5.  Otherwise, estiblish additional conditions :
      cond_01 = R_tg > p.cpf_fzo_tg_limit_01         # tg rate high enough
      cond_02 = R_zo > p.cpf_fzo_zo_limit_02         # zo rate high enough
      cond_03 = (R_zo / R_tg) <= p.cpf_ratio_zo_tg_limit    # zo/tg rate limit
      cond_04 = sqrt( C_tg ) > p.snr_grating_min     # grating SNR high enough
      cond_04b = sqrt( C_tg ) > p.snr_grating_02     # grating SNR high enough, alt
      cond_05 = not (sqrt(C_st/C_tg) > p.snr_streak_to_grating_min and sqrt(C_st/C_tg) <= p.snr_streak_to_grating_max )
      if ( cond_01 and ( cond_02 or cond_03 ) and ( ( cond_05 and cond_04 ) or cond_04b ) ):
         pio.pset( p.tname, "method", "tg_findzo" )  
      else :
         pio.pset( p.tname, "method", "tgdetect" )  
   os._exit(0)
   
if __name__=="__main__":
    main()
