#include "soleph.h"
/*
############################################################
           ROUTINES TO HANDLE TELESCOPE FLEXURE

           by: Anders Johannesson

           part of the PDP-REPLACEMENT project 1997

           Created: 1997-11-01 by AJO
               Mod: 1997-11-03 by AJO Include ephemeris calc
                                      in get_flexure_LUT
               Mod: 1997-11-06 by AJO Include ephemeris calc
############################################################
*/

/*
###########################################################
  INTEGRATE FLEXURE 
###########################################################
This routine integrates the flexure given in the standard
format with 2 hour bins centered on hour angles -5 - +5.
For each bin the measured drift is given in arcsec/hour.
The output is given as accumulated flexure since hour angle
-6 in 5 minute bins. The output arrays in X and Y are
145 elements (12 hours) long. 
###########################################################
*/                                       
void integrate_flexure(double xflex[6], double yflex[6],
                       double int_flex[2][145]) 
{

   /* DECLARATIONS */
   double dth,H,xoff,yoff,dx,dy,TimeStep;
   short counter=0, index=0;

   /* INIT FLEXURE OFFSET VALUES */
   xoff=0.0;
   yoff=0.0;

   /* SET TIME STEP */
   TimeStep=1.0;                     /* seconds */
   dth=TimeStep/3600.0;              /* decimal hours */

   /* LOOP OVER HOUR ANGLES */
   for (H=-6.0; H<=6.0; H+=dth)  /* decimal UT time */
   {

      /* FLEXURE ACCUMULATION */
      if ( (H>=-6.0) && (H<-4.0) )
      {
         dx=xflex[0]*dth;
         dy=yflex[0]*dth;
      }
      else if ( (H>=-4.0) && (H<-2.0) )
      {
         dx=xflex[1]*dth;
         dy=yflex[1]*dth;
      }
      else if ( (H>=-2.0) && (H<0.0) )
      {
         dx=xflex[2]*dth;
         dy=yflex[2]*dth;
      }
      else if ( (H>=0.0) && (H<2.0) )
      {
         dx=xflex[3]*dth;
         dy=yflex[3]*dth;
      }
      else if ( (H>=2.0) && (H<4.0) )
      {
         dx=xflex[4]*dth;
         dy=yflex[4]*dth;
      }
      else if ( (H>=4.0) && (H<6.0) )
      {
         dx=xflex[5]*dth;
         dy=yflex[5]*dth;
      }
      /* outside the intervals */
      else if ( (H<-6.0) && (H>-12.0) )
      {
         dx=xflex[0]*dth;
         dy=yflex[0]*dth;
      }
      else
      {
         dx=xflex[5]*dth;
         dy=yflex[5]*dth;
      }

      /* INTEGRATE */
      xoff=xoff+dx;
      yoff=yoff+dy;
     
      /* STORE VALUE EVERY 5 MINUTES */
      if ((counter % (300/(short)TimeStep) ) == 0) 
      { 
        /* printf("%d  %8.4f     %9.3f  %9.3f \n",index, H,xoff,yoff); */
         int_flex[0][index]=xoff;
         int_flex[1][index]=yoff;
         index++;
      }
      counter++;

   }

}


/*
###########################################################
  GET FLEXURE LUT
###########################################################
  To read flexure data points from file. The filename is
  specified in the soleph.h header file. The result is
  a look-up-table (LUT) with flexure since Hour Angle -6
  in 5 min bins. this is used by the routine flexure_since
  that calculates the flexure since the given reference
  Hour Angle.
  Returns 0 in case of error, 1 otherwise.
###########################################################
*/                                       
short get_flexure_LUT(short telescope, double flex_LUT[2][145])
{

   /* DECLARATIONS */
   FILE *LUN;
   char line[72], xstring[3], ystring[3];
   double xflex[6], yflex[6], declination;
   short ierr, i, decl, decl_now, error_code;
   struct tm *Current_Time_UT;
   time_t Current_Time;
   TimeType Etime;
   EphType Ephem;

   /* SET ERROR STATUS */
   error_code=OK;

   /* WHAT TELESCOPE? */
   if (telescope == TELESCOPE_26INCH)
   {
      sprintf(xstring,"%s","26X");
      sprintf(ystring,"%s","26Y");
   }
   else if (telescope == TELESCOPE_10INCH)
   {
      sprintf(xstring,"%s","10X");
      sprintf(ystring,"%s","10Y");
   }
   else
   {
      error_code=NOTELESCOPE;
   }

   /* GET CURRENT TIME */
   time(&Current_Time);
   Current_Time_UT=gmtime(&Current_Time);
   Etime.iy=Current_Time_UT->tm_year+1900;
   Etime.im=Current_Time_UT->tm_mon+1;
   Etime.id=Current_Time_UT->tm_mday;
   Etime.ih=Current_Time_UT->tm_hour;
   Etime.imi=Current_Time_UT->tm_min;
   Etime.is=Current_Time_UT->tm_sec;

   /* CALCULATE EPHEMERID */
   soleph(Etime,&Ephem);
   declination=Ephem.decl;

   /* WHAT DECLINATION? */
   if (declination < -18)
      decl_now=1;
   else if ( (declination >= -18) && (declination < -6) ) 
      decl_now=2;
   else if ( (declination >= -6) && (declination < 6) ) 
      decl_now=3;
   else if ( (declination >= 6) && (declination < 18) ) 
      decl_now=4;
   else 
      decl_now=5;

   /* #  READ FLEXURE DATA FROM FILE ####################### */
   if( (LUN = fopen(FLEXFILE, "r" )) == NULL ) 
      error_code=FLEX_FILE_ERR;
   ierr=0;
   decl=1;
   while (ierr != EOF) 
   {
      ierr=fscanf(LUN,"%s",line);
      if (strcmp(xstring,line) == 0) 
      {
         for (i=0; i<6; i++)
         {
            ierr=fscanf(LUN,"%s",line);
            if (decl == decl_now)
            {
               xflex[i]=atof(line);
               /* printf("XXX   %d %d  %s   \n",decl,i,line); */
            }
         }
      }
      if (strcmp(ystring,line) == 0) 
      {
         for (i=0; i<6; i++)
         {
            ierr=fscanf(LUN,"%s",line);
            if (decl == decl_now)
            {
               yflex[i]=atof(line);
               /* printf("YYY   %d %d  %s    \n",decl,i,line); */ 
            }
         }
         decl++;
      }
   }

   /* Close */
   if( fclose( LUN ) )
      error_code=FLEX_FILE_ERR; 

   /* INTEGRATE FLEXURE DATA */
   integrate_flexure(xflex,yflex,flex_LUT); 

   return(error_code);

}

/*
###########################################################
  FLEXURE SINCE
###########################################################
Calculates the accumulated flexure since the given ref-
erence by using the look_up_table (LUT) created by the
routine: get_flexure_LUT. Hour angles are expected in
decimal hours.
###########################################################
*/                                       
void flexure_since(double H_ref,double H_now,double flex_LUT[2][145],
                   double *xoff, double *yoff) 
{

   /* DECLARATIONS */
   short ref_index, now_index;
   double TimeStep;

   /* WHAT INDEX POSITION IN THE LUT WILL THIS BE? */
   TimeStep=5.0/60.0; /* 5 minutes in decimal hours */
   ref_index=(short)((H_ref-(-6.0))/TimeStep);
   now_index=(short)((H_now-(-6.0))/TimeStep);

   /* CHECK IF WITHIN THE LUT AND AVOID ERROR */
   if (ref_index < 0) 
      ref_index=0;
   if (now_index < 0) 
      now_index=0;
   if (ref_index > 144) 
      ref_index=144;
   if (now_index > 144) 
      now_index=144;

   /* SUBTRACT THE REFERENCE FLEXURE FROM THE CURRENT FLEXURE */
   *xoff=flex_LUT[0][now_index]-flex_LUT[0][ref_index];
   *yoff=flex_LUT[1][now_index]-flex_LUT[1][ref_index];

}
