/* ***********************************************************************
 * *                                                                     *
 * *  Function to convert a HDF file to an IRIS USER product             *  
 * *                                                                     *
 * ***********************************************************************
 * File: utils/pipes_in/HDFSatToIris.C
 *
 *                    COPYRIGHT (c) 2002, 2003  BY
 *          SIGMET INCORPORATED, WESTFORD MASSACHUSETTS, U.S.A.
 * 
 * THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
 * ONLY  IN  ACCORDANCE WITH  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
 * INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE  OR  ANY OTHER
 * COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
 * OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
 * TRANSFERED.
 */

/* This program is a pipe which takes a HDF file and converts it into 
 * an IRIS USER product containing that data.
 * 
 * NOTE: Make sure in the setup utility under Input, that HDFSatToIris 
 * Command line syntax is set to Pathnames.
 *
 * Note if you are modifying this program, and wish to insert a diagnostic
 * printf, be sure to write it to the error output.
 */

#include <locale.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>

#include "sigtypes.h"
#include "projection.h"
#include "headers.h"
#include "product.h"
#include "dsp_lib.h"
#include "himath_lib.h"
#include "misc_lib.h"
#include "user_lib.h"

struct command_line
{
  char  sInFile[FILENAME_SIZE];
  char  sInPath[PATHNAME_SIZE];
  char  sOutPath[PATHNAME_SIZE];
};

static char  sPathSDSImage[PATHNAME_SIZE];

/* This holds information to customize the convertor */
struct projection_summary8
{
  FLT8  fPerspectiveCorrection; /* Perspective Correction */
  BIN4  iRadarLat;              /* Latitude of the radar */
  BIN4  iRadarLon;              /* Longitude */
  BIN4  iCenterLat;             /* Latitude of center of product */
  BIN4  iCenterLon;             /* Longitude */
  UINT1 iType;                  /* Type of projection */
  BIN4  iReferenceLat;          /* Latitude of reference point */
  BIN4  iReferenceLon;          /* Longitude */
  SINT4 iXSize, iYSize;         /* Sizes in pixels */
  SINT4 iXScale, iYScale;       /* Scales in cm/pixel */
  FLT8  fXRes, fYRes;           /* Resolution */
  SINT4 iXRadPos, iYRadPos;     /* Radar positions in 1/1000 of pixels */
};

struct convert_config
{
  UINT1  lLogToFile;
  UINT1  lLogToTerm;
  UINT1  lVerbose;              /* Log more details */
  FILE   *iLogFile;             /* Open file descriptor to log file */
  char   sIngSitename[16];      /* Ingest sitename to use, space padded */
  struct projection_summary8 Projection;
};
struct convert_config CSetup_c;

/* Local function prototypes
 */
static void  ProcessCommandLine (int iArgc, char *sArgv[], 
  struct command_line *pCommand_a ); 
static void  Usage( void );
static void  LoadSetup(struct convert_config *pCSetup_a );
static void  LoadHDF(struct command_line *cmd_a,
   struct ymds_time *time_a, struct projection_summary8 *pProjSum_a);
static UINT2 ProcessConfigLine(char *sline_a,struct convert_config *pCSetup_a );
static void ConvertHDFToIris(struct command_line *cmd_a, 
  struct ymds_time *time_a, struct projection_summary8 *pProjSum_a);
static void ExitHandler(void);
static void  Lprintf(const char *sString_a);
static void FillProjectionNumbers(struct projection_summary8 *pProj_a );

#define MAX_LINELENGTH (120)
/* ===============================================================
 * Main program starts here.
 */
int main(int iArgc, char *sArgv[])
{
  struct command_line cmd;
  struct ymds_time time;

  setlocale( LC_ALL, "" ) ;

  /* Process the command line arguments */
  ProcessCommandLine( iArgc, sArgv, &cmd );

  /* Process the setup file,if any.  */
  LoadSetup(&CSetup_c);

  LoadHDF(&cmd, &time, &CSetup_c.Projection);
  /* Starting here we need to remove the data and image file on exit */
  atexit( ExitHandler );

  /* Open the logging file, if any */
  if (CSetup_c.lLogToFile)
    {
      char *sptr;
      char sLogPath[PATHNAME_SIZE];
      sptr = getenv( "IRIS_LOG" );
      if (sptr)
	{
	  strncpy( sLogPath, sptr, PATHNAME_SIZE-20 );
	  sLogPath[PATHNAME_SIZE-20] = 0;
	}
      else
	strcpy( sLogPath, "/tmp/" );
      strcat( sLogPath, "HDFSatToIris.log" );
      CSetup_c.iLogFile = fopen( sLogPath, "w" );
      if (NULL == CSetup_c.iLogFile)
	{
	  fprintf( stderr, "Can not open log file: '%s'\n", sLogPath );
	  exit(EXIT_FAILURE);
	}
    }

  /* Starting here we can use the Lprintf function */
  if (CSetup_c.lVerbose)
     Lprintf( "Verbose Logging On.\n");

  /* Now check for missing data in the command line */
  if (cmd.sInPath[0]==0)
  {
    Lprintf("ERROR: missing -ip command line option\n" );
    exit(EXIT_FAILURE);
  }
  if (cmd.sOutPath[0]==0)
  {
    Lprintf("ERROR: missing -op command line option\n" );
    exit(EXIT_FAILURE);
  }
    
  /* Read in the header */
  ConvertHDFToIris(&cmd, &time, &CSetup_c.Projection);
}
static void ConvertHDFToIris(struct command_line *cmd_a, 
  struct ymds_time *time_a, struct projection_summary8 *pProjSum_a)
{

  int    istatus;
  SINT4  ifilesize = 0;
  UINT1  *pbufr;
  SINT4  ichannel;
  FILE   *fp;
  char   *sptr;
  char   sname[16];
  struct full_time_spec Time;
  struct product_hdr prod_hdr;

  istatus = imapopen(sPathSDSImage, FALSE, (void**)&pbufr, &ifilesize,
             &ichannel);
  if (istatus!=SS_NORMAL)
  {
    Lprintf("ERROR: Can't map file to a buffer \n");
    exit(EXIT_FAILURE);
  }

  /*********************************
  ** Fill in the Projection Numbers 
  **********************************/

  FillProjectionNumbers(pProjSum_a);

  /*********************************
  ** Setup the product header 
  **********************************/
  strncpy(sname, cmd_a->sInFile, 16);

  sname[15] = '\0';
  if ((sptr = strrchr(sname, '.')) != NULL) *sptr = '\0';

  STR_UPPER(sname, 16);
  GetTimeFull( &Time, TIME_FLG_GMT );
  Time.Ymds = *time_a;
  HeaderFromScratch( &prod_hdr, &Time, CSetup_c.sIngSitename,
                     CSetup_c.sIngSitename, sname );

  prod_hdr.pcf.iptype    = PROD_USER;
  prod_hdr.pcf.ixscale   = pProjSum_a->iXScale;
  prod_hdr.pcf.iyscale   = pProjSum_a->iYScale;
  prod_hdr.pcf.izscale   = 0;
  prod_hdr.pcf.ixsize    = pProjSum_a->iXSize;
  prod_hdr.pcf.iysize    = pProjSum_a->iYSize;
  prod_hdr.pcf.izsize    = 1;
  prod_hdr.pcf.ixrad     = pProjSum_a->iXRadPos;
  prod_hdr.pcf.iyrad     = pProjSum_a->iYRadPos;
  prod_hdr.pcf.izrad     = 0;

  prod_hdr.pcf.idata_out = DB_USER;
  prod_hdr.pcf.idata_in  = DB_USER;
  
  prod_hdr.pcf.iprojection_type = pProjSum_a->iType;
  prod_hdr.pcf.colors.iflags = (COLOR_SCALE_TOP_SAT | COLOR_SCALE_BOT_SAT);
  prod_hdr.pcf.colors.istart = 160;
  prod_hdr.pcf.colors.istep  = 160;
  prod_hdr.pcf.colors.icolcnt = 16;
  prod_hdr.pcf.colors.iset_and_scale = 0x0104;


  prod_hdr.end.ilat_center = pProjSum_a->iCenterLat;
  prod_hdr.end.ilon_center = pProjSum_a->iCenterLon;

  prod_hdr.end.ilat_ref = pProjSum_a->iReferenceLat;
  prod_hdr.end.ilon_ref = pProjSum_a->iReferenceLon;

  prod_hdr.hdr.ibytes = PRODUCT_HDR_SIZE + 
     (prod_hdr.pcf.ixsize*prod_hdr.pcf.iysize);

  fp = fopen(cmd_a->sOutPath, "w");
  if (fp)
    {
      int    ix, iy;
      int    ioff;      
      fwrite( &prod_hdr, sizeof(struct product_hdr), 1, fp );
      // Need to flip the Y axis
/*************************************************
**  This is for flipping the image
**      for (iy = (prod_hdr.pcf.iysize - 1); iy >= 0; iy--)
**************************************************/
      for (iy = 0; iy < prod_hdr.pcf.iysize; iy++)
      {
        // Check for area not scanned, which is value 255.
        // If found replace with 254
        for (ix = 0; ix < prod_hdr.pcf.ixsize; ix++)
        {
	   ioff = (iy * prod_hdr.pcf.ixsize) + ix;
	   if (pbufr[ioff] == 255)
	      pbufr[ioff] = 254;
        }
	fwrite(&pbufr[iy * prod_hdr.pcf.ixsize], prod_hdr.pcf.ixsize, 1, fp );
      }
      fclose(fp);
    }
  else
    {
      Lprintf("ERROR: Can't open output file\n");
      exit(EXIT_FAILURE);
    }
  
  if (CSetup_c.lVerbose)
    {
      char   sLog[200];
      sprintf( sLog, "Wrote %d bytes, \n", prod_hdr.hdr.ibytes);
      Lprintf( sLog);
    }
}


/* ======================================================================
 * Function to process the command line arguments.
 */
static void ProcessCommandLine
(int iArgc_a, char *sArgv_a[],  struct command_line *pCommand_a )
{
  int iArg;
  memset( pCommand_a, 0, sizeof(*pCommand_a) );

  /* Parse command line options
  */
  for( iArg=1 ; iArg<iArgc_a ; iArg++ )
    {
      const char *sArg = sArgv_a[iArg];
      /* fprintf( stderr, "Processing %d: '%s'\n", iArg, sArg ); */

      if (0 == strncmp( sArg, "-h", 2 ))
        {
          Usage();
        }
      else if (0 == strncmp( sArg, "-if:", 4 ))
        {
          strncpy( pCommand_a->sInFile, &sArg[4], FILENAME_SIZE-1 );
        }
      else if (0 == strncmp( sArg, "-ip:", 4 ))
        {
          strncpy( pCommand_a->sInPath, &sArg[4], PATHNAME_SIZE-1 );
        }
      else if (0 == strncmp( sArg, "-op:", 4 ))
        {
          strncpy( pCommand_a->sOutPath, &sArg[4], PATHNAME_SIZE-1 );
        }
    }
}
/* ==================================================
 */
static void Usage( void )
{
  fprintf( stderr, "Options: -help\n" );
  fprintf( stderr, "         (all other arguments ignored)\n" );
  exit(EXIT_FAILURE) ;
}

/***********************************************************
**
** Get date, time and x, y size
** Also store image in a temp file
***********************************************************/

static void LoadHDF(struct command_line *cmd_a,
   struct ymds_time *time_a, struct projection_summary8 *pProjSum_a)
{ 
  char sline[81];
  FILE* stream;
  pid_t pid;
  int  ierror;
  char *sptr;
  const char *params[5];
  char exe_path[PATHNAME_SIZE];
  char temp_path[PATHNAME_SIZE];
  char outcmdstr[200];
  char spath_vd_data[PATHNAME_SIZE];
  char spath_sds_data[PATHNAME_SIZE];

  sptr = getenv( "IRIS_ROOT" ) ;
  if( !sptr )
    {
      sig_signal_va( USER_NO_ENV, 1, "IRIS_BIN" );
      exit(EXIT_FAILURE);
    }
  sprintf(exe_path,"%s/config_template/extras/hdp", sptr);

  sptr = getenv( "IRIS_TEMP" ) ;
  if( !sptr )
    {
      sig_signal_va( USER_NO_ENV, 1, "IRIS_TEMP" );
      exit(EXIT_FAILURE);
    }
  strcpy(temp_path, sptr);

  pid = getpid();

  /**************************************************************
  **
  ** Decode vdata data for projection type, Ref Lon, and Ref Lat
  **
  **************************************************************/
  params[0] = "dumpvd";                     //dump vdata
  params[1] = "-n \"proj4\"";               //data name 
  params[2] = "-d";                         //dump data only (Ascii).No header
  sprintf(spath_vd_data,"%shdf_to_iris_vd%d.dat", temp_path, pid); 

  sprintf(outcmdstr, "%s %s %s %s %s > %s",
    exe_path, params[0], params[1], params[2], 
    cmd_a->sInPath, spath_vd_data);
  ierror = system(outcmdstr);
  if (ierror != 0)
    fprintf( stderr, "Error executing <%s>\n", outcmdstr);
  else
  {
    int  ii;
    char proj_type[11];
    char slon[20];
    char slat[20];
    FLT4 flon;
    FLT4 flat;

    stream = fopen(spath_vd_data, "r" );

    /* Don't worry about a missing config file */
    if (NULL == stream)
    {
       fprintf( stderr, "Error opening  <%s>\n", spath_vd_data);
       return;
    }

    ///////////////////////////
    // Proj Type
    //////////////////////////
    // Read proj= 
    for (ii = 0; ii < 5; ii++)
      sptr = fgets(sline, 81, stream );

    // Read  the type now (merc, azm, nsper)
    for (ii = 0; ii < 10; ii++)
    { 
       sptr = fgets(sline, 81, stream );
       if ((sline[0] == '\n') || (sline[0] == ' '))
          break;
       proj_type[ii] = sline[0];
    }
    proj_type[ii] = '\0';
    if (strstr(proj_type, "nsper"))
      pProjSum_a->iType =  MAPROJ_PERSPECTIVE;
    else if (strstr(proj_type, "merc"))
      pProjSum_a->iType =  MAPROJ_MERCATOR;
    else if (strstr(proj_type, "az"))
      pProjSum_a->iType =  MAPROJ_AZIMUTHAL;
    else if (strstr(proj_type, "gnom"))
      pProjSum_a->iType =  MAPROJ_GNOMONIC;
    else
      pProjSum_a->iType =  MAPROJ_AZIMUTHAL;
//    printf("proj type %s  TYPE %d\n", proj_type,       pProjSum_a->iType);

    ///////////////////////////
    // Longitude 
    //////////////////////////
    // Read lon_0= 
    for (ii = 0; ii < 6; ii++)
      sptr = fgets(sline, 81, stream );

    // Read longitude 
    for (ii = 0; ii < 19; ii++)
    { 
       sptr = fgets(sline, 81, stream );
       if ((sline[0] == '\n') || (sline[0] == ' '))
          break;
       slon[ii] = sline[0];
    }
    slon[ii] = '\0';
    flon = strtod(slon, &sptr);
    pProjSum_a->iReferenceLon = iBin4FromFDeg(flon);
//    printf("F Lon Ref %6.5f\n", flon);


    ///////////////////////////
    // Latitude 
    //////////////////////////
    // Read lat_0= 
    for (ii = 0; ii < 6; ii++)
      sptr = fgets(sline, 81, stream );

    // Read lat
    for (ii = 0; ii < 19; ii++)
    { 
       sptr = fgets(sline, 81, stream );
       if ((sline[0] == '\n') || (sline[0] == ' '))
          break;
       slat[ii] = sline[0];
    }
    slat[ii] = '\0';
    flat = strtod(slat, &sptr);
    pProjSum_a->iReferenceLat = iBin4FromFDeg(flat);
//    printf("F Lat Ref %6.5f\n", flat);


    fclose( stream );
    if (spath_vd_data[0]) 
      unlink(spath_vd_data);
  }


  /**************************************************************
  **
  ** Decode vdata data for date and time then convert to ymds_time
  **
  **************************************************************/
  params[0] = "dumpvd";                     //dump vdata
  params[1] = "-n \"acquisition time\"";     //data name 
  params[2] = "-d";                         //dump data only (Ascii).No header
  sprintf(spath_vd_data,"%shdf_to_iris_vd%d.dat", temp_path, pid); 

  sprintf(outcmdstr, "%s %s %s %s %s > %s",
    exe_path, params[0], params[1], params[2], 
    cmd_a->sInPath, spath_vd_data);
  ierror = system(outcmdstr);
  if (ierror != 0)
    fprintf( stderr, "Error executing <%s>\n", outcmdstr);
  else
  {
    char sday[3];
    char smon[4];
    char syear[5];
    char shour[3];
    char smin[3];
    SINT4 iday;
    SINT4 imon;
    SINT4 iyear;
    SINT4 ihour;
    SINT4 imin;
    struct tm LocalTm;
    struct timeval tval;

    stream = fopen(spath_vd_data, "r" );

    /* Don't worry about a missing config file */
    if (NULL == stream)
    {
       fprintf( stderr, "Error opening  <%s>\n", spath_vd_data);
       return;
    }

    // Day
    sptr = fgets(sline, 81, stream );
    sday[0] = sline[0];
    sptr = fgets(sline, 81, stream );
    sday[1] = sline[0];
    sday[2] = '\0';
    iday = strtol(sday, &sptr, 10);

    // skip -
    sptr = fgets(sline, 81, stream );

    //Mon 
    sptr = fgets(sline, 81, stream );
    smon[0] = sline[0];
    sptr = fgets(sline, 81, stream );
    smon[1] = sline[0];
    sptr = fgets(sline, 81, stream );
    smon[2] = sline[0];
    smon[3] = '\0';
    imon = imonth_from_txt(smon);

    // skip -
    sptr = fgets(sline, 81, stream );

    //Year
    sptr = fgets(sline, 81, stream );
    syear[0] = sline[0];
    sptr = fgets(sline, 81, stream );
    syear[1] = sline[0];
    sptr = fgets(sline, 81, stream );
    syear[2] = sline[0];
    sptr = fgets(sline, 81, stream );
    syear[3] = sline[0];
    syear[4] = '\0';
    iyear = strtol(syear, &sptr, 10);

    // skip space
    sptr = fgets(sline, 81, stream );

    //Hour
    sptr = fgets(sline, 81, stream );
    shour[0] = sline[0];
    sptr = fgets(sline, 81, stream );
    shour[1] = sline[0];
    shour[2] = '\0';
    ihour = strtol(shour, &sptr, 10);

    // skip :
    sptr = fgets(sline, 81, stream );

    //Min
    sptr = fgets(sline, 81, stream );
    smin[0] = sline[0];
    sptr = fgets(sline, 81, stream );
    smin[1] = sline[0];
    smin[2] = '\0';
    imin = strtol(smin, &sptr, 10);

/*
    printf("iday %d imon %d iyear %d ihour %d imin %d\n", iday, imon, iyear, ihour, imin);
*/
    time_a->iyear = iyear;
    time_a->imon = imon;
    time_a->iday = iday;
    time_a->isec = iPackTime(ihour, imin, 0); 

/*
   Modified by Fritz on 22 Aug 2003.  Get the isdst variable from
   Operating System.  If isdst then add three hours to convert from
   UTC.  If not, then add only two hours.
*/
    gettimeofday( &tval, NULL);
    localtime_r( &tval.tv_sec, &LocalTm );
    if (LocalTm.tm_isdst>0)
    {
      time_a->imills = YMDS_FLG_LDST;
      ymds_add_seconds ( (3600 * 3), time_a); 
    }
    else
    {
      time_a->imills = 0;
      ymds_add_seconds ( (3600 * 2), time_a); 
    }

    fclose( stream );
    if (spath_vd_data[0]) 
      unlink(spath_vd_data);
  }

  /**************************************************************
  **
  ** Decode vdata data for product center latitude 
  **
  **************************************************************/
  params[0] = "dumpvd";                         //dump vdata
  params[1] = "-n \"product center latitude\""; //data name 
  params[2] = "-d";                           //dump data only (Ascii).No header
  sprintf(spath_vd_data,"%shdf_to_iris_vd%d.dat", temp_path, pid); 

  sprintf(outcmdstr, "%s %s %s %s %s > %s",
    exe_path, params[0], params[1], params[2], 
    cmd_a->sInPath, spath_vd_data);
  ierror = system(outcmdstr);
  if (ierror != 0)
    fprintf( stderr, "Error executing <%s>\n", outcmdstr);
  else
  {
    FLT8 flat;

    stream = fopen(spath_vd_data, "r" );
    /* Don't worry about a missing config file */
    if (NULL == stream)
    {
       fprintf( stderr, "Error opening  <%s>\n", spath_vd_data);
       return;
    }
    // Latitiude 
    sptr = fgets(sline, 81, stream );
    flat = strtod(sline, &sptr);
    pProjSum_a->iCenterLat =  iBin4FromFDeg(flat);
    
//    printf("flat %6.2f\n", flat);

    fclose( stream );
    if (spath_vd_data[0]) 
      unlink(spath_vd_data);
  }

  /**************************************************************
  **
  ** Decode vdata data for product center longitude
  **
  **************************************************************/
  params[0] = "dumpvd";                         //dump vdata
  params[1] = "-n \"product center longitude\""; //data name 
  params[2] = "-d";                           //dump data only (Ascii).No header
  sprintf(spath_vd_data,"%shdf_to_iris_vd%d.dat", temp_path, pid); 

  sprintf(outcmdstr, "%s %s %s %s %s > %s",
    exe_path, params[0], params[1], params[2], 
    cmd_a->sInPath, spath_vd_data);
  ierror = system(outcmdstr);
  if (ierror != 0)
    fprintf( stderr, "Error executing <%s>\n", outcmdstr);
  else
  {
    FLT8 flon;

    stream = fopen(spath_vd_data, "r" );
    /* Don't worry about a missing config file */
    if (NULL == stream)
    {
       fprintf( stderr, "Error opening  <%s>\n", spath_vd_data);
       return;
    }
    // Latitiude 
    sptr = fgets(sline, 81, stream );
    flon = strtod(sline, &sptr);
    pProjSum_a->iCenterLon =  iBin4FromFDeg(flon); 

//    printf("flon %6.2f\n", flon);

    fclose( stream );
    if (spath_vd_data[0]) 
      unlink(spath_vd_data);
  }

  /**************************************************************
  **
  ** Decode vdata data for resolution 
  **
  **************************************************************/
  params[0] = "dumpvd";                         //dump vdata
  params[1] = "-n \"resolution\""; //data name 
  params[2] = "-d";                           //dump data only (Ascii).No header
  sprintf(spath_vd_data,"%shdf_to_iris_vd%d.dat", temp_path, pid); 

  sprintf(outcmdstr, "%s %s %s %s %s > %s",
    exe_path, params[0], params[1], params[2], 
    cmd_a->sInPath, spath_vd_data);
  ierror = system(outcmdstr);
  if (ierror != 0)
    fprintf( stderr, "Error executing <%s>\n", outcmdstr);
  else
  {
    FLT8 fres;

    stream = fopen(spath_vd_data, "r" );
    /* Don't worry about a missing config file */
    if (NULL == stream)
    {
       fprintf( stderr, "Error opening  <%s>\n", spath_vd_data);
       return;
    }
    // Resolution X and Y
    sptr = fgets(sline, 81, stream );
    fres = strtod(sline, &sptr);
    pProjSum_a->fXRes = fres; 

    sptr = fgets(sline, 81, stream );
    fres = strtod(sline, &sptr);
    pProjSum_a->fYRes =  fres;

//    printf("fres %6.2f\n", fres);

    fclose( stream );
    if (spath_vd_data[0]) 
      unlink(spath_vd_data);
  }

  /**************************************************************
  **
  ** Decode SDS Header data for width and height of image
  **
  **************************************************************/

  params[0] = "dumpsds";                     //dump sds data. Scientific Data
  params[1] = "-n \"IMAGE\"";               //data name 
  params[2] = "-h";                         //dump header only. No image data 
  sprintf(spath_sds_data,"%shdf_to_iris_sds%d.dat", temp_path, pid); 

  sprintf(outcmdstr, "%s %s %s %s %s > %s",
    exe_path, params[0], params[1], params[2], 
    cmd_a->sInPath, spath_sds_data);
  ierror = system(outcmdstr);
  if (ierror != 0)
    fprintf( stderr, "Error executing <%s>\n", outcmdstr);
  else
  {
    char sx[81], sy[81];

    stream = fopen( spath_sds_data, "r" );

    /* Don't worry about a missing config file */
    if (NULL == stream)
    {
       fprintf( stderr, "Error opening  <%s>\n", spath_sds_data);
       return;
    }
    sx[0] = '\0';
    sy[0] = '\0';
    while(1)
    {
      if (fgets( sline, 81, stream ) == NULL)
         break;

      if (strstr(sline, "Name=y"))
      {
        fgets( sline, 81, stream );
        if ((sptr = strstr(sline, "Size =")) != NULL)
        {
          strcpy(sy, &sptr[7]);
          if ((sptr = strchr(sy, '\n')) != NULL)
            *sptr = '\0';
          pProjSum_a->iYSize = strtol(sy, &sptr, 10); 
        }
      }
      else if (strstr(sline, "Name=x"))
      {
        fgets( sline, 81, stream );
        if ((sptr = strstr(sline, "Size =")) != NULL)
        {
          strcpy(sx, &sptr[7]);
          if ((sptr = strchr(sx, '\n')) != NULL)
            *sptr = '\0';
          pProjSum_a->iXSize = strtol(sx, &sptr, 10); 
        }
      }
      if ((sx[0] != '\0') && (sy[0] != '\0'))
         break;
    }
    
    if (spath_sds_data[0])
      unlink(spath_sds_data);
/*
    printf("WID <%s>, HGT <%s>\n", sx, sy);
*/
    fclose( stream );
  }

  /****************************************************
  **
  ** Save image to a temp file
  ** 
  ****************************************************/
  params[0] = "dumpsds";                  //dump sds data. Scientific Data
  params[1] = "-n \"IMAGE\"";             // data name
  params[2] = "-d";                       // dump data only. No header info.
  params[3] = "-b";                       // dump in binary.
  sprintf(sPathSDSImage,"%shdf_to_iris_sds%d.img", temp_path, pid); 

  sprintf(outcmdstr, "%s %s %s %s %s %s > %s",
    exe_path, params[0], params[1], params[2], params[3], 
    cmd_a->sInPath, sPathSDSImage);
  ierror = system(outcmdstr);
  if (ierror != 0)
    fprintf( stderr, "Error executing <%s>\n", outcmdstr);
}

/* ============================================================
 * Function to load the convert setup from a configuration file.
 */
static void LoadSetup( struct convert_config *pCSetup_a )
{
  char sPath[PATHNAME_SIZE];
  char sline[81], *sptr;
  FILE* stream;
  SINT4 iline;
  UINT2 lerror;

  /* Initialize the data to the default values */
  memset( pCSetup_a, 0, sizeof(*pCSetup_a) );
  spacify_ncpy( pCSetup_a->sIngSitename, "UNKNOWN", 16 );
  /* Default location is 0 0 latlon, AED, max range=100 km */
  pCSetup_a->Projection.iType = MAPROJ_AZIMUTHAL;
  pCSetup_a->Projection.fPerspectiveCorrection = 1.014296;
  
  /* Generate the file name and open the file */
  sptr = getenv( "IRIS_CONFIG" );
  if (NULL == sptr) 
    {
      sig_signal_va( USER_NO_ENV, 1, "IRIS_CONFIG" );
      exit(EXIT_FAILURE);
    }

  strncpy( sPath, sptr, 140 );
  strcat( sPath, "HDFSatToIris.conf" );
  stream = fopen( sPath, "r" );

  /* Don't worry about a missing config file */
  if (NULL == stream) return;

  /* now loop through the file reading and parsing lines */
  iline = 1;
  sptr = fgets( sline, 81, stream );
  while (NULL != sptr)
    {
      lerror = ProcessConfigLine( sptr, pCSetup_a );
      if (lerror) fprintf( stderr, "Syntax error on config file line %d\n", iline );
      iline +=1;
      sptr = fgets( sline, 81, stream );
    }

  fclose( stream );
  return;
}

/* ===============================================================
 * Process one line from the configuration file.  Returns nonzero if there
 * is a syntax error.
 *
 * The config can contain the following commands.  All blank lines and
 * lines beginning with "#" are ignored.  Commands can be in any order.
 * Commands take effect in the order received.  For example, syntax errors
 * before the LOG command will not be logged.
 *
 * LOG           <FILE TERM BOTH NONE>
 * SITENAME      <name>
 * VERBOSE
 *
 */
static UINT2 ProcessConfigLine
(char *sline_a,
 struct convert_config *pConfig_a )
{
  char *stokens[9], *sptr;
  UINT4 icount, ioffset;
  
  ioffset = 0;
  icount  = 0;
  /* Process up to 9 tokens, stop when the line is exhausted. */
  while (icount<9) 
    {
      stokens[icount] = sigtok( sline_a, &ioffset );
      if (NULL == stokens[icount])
	break;
      else
	icount++;
    }
  
  /* Blank lines are allowed and skipped */
  if (icount == 0) return FALSE;
  
  /* Skip commented lines */
  if (stokens[0][0] == '#') return FALSE;

  /* See if the line contains the LOG file command */
  if ( 0 == strcmp( "LOG", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      if      ( 0 == strcmp( "BOTH", stokens[1] ) ) 
	{pConfig_a->lLogToFile=TRUE;  pConfig_a->lLogToTerm=TRUE;}
      else if ( 0 == strcmp( "FILE", stokens[1] ) ) 
	{pConfig_a->lLogToFile=TRUE;  pConfig_a->lLogToTerm=FALSE;}
      else if ( 0 == strcmp( "TERM", stokens[1] ) )
	{pConfig_a->lLogToFile=FALSE; pConfig_a->lLogToTerm=TRUE;}
      else if ( 0 == strcmp( "NONE", stokens[1] ) )
	{pConfig_a->lLogToFile=FALSE; pConfig_a->lLogToTerm=FALSE;}
      else
	return TRUE;
      return FALSE;
    }

  /* See if the line contains the PERSPECTIVE_CORRECTON command */
  if ( 0 == strcmp( "PERSPECTIVE_CORRECTON", stokens[0] ) )
    {
      FLT8 fcorrection;
      if ( icount < 2 ) return TRUE;

      fcorrection = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

/* DOUG
      if (fRMax <     1.0 ) return TRUE;
      if (fRMax > 10000.0 ) return TRUE;
*/
      pConfig_a->Projection.fPerspectiveCorrection = fcorrection;
      return FALSE;
    }


  /* See if the line contains the RADAR_LATLON command */
  if ( 0 == strcmp( "RADAR_LATLON", stokens[0] ) )
    {
      FLT8 fLatitude, fLongitude;
      if ( icount < 3 ) return TRUE;
      
      fLatitude = strtod( stokens[1], &sptr );
      if (sptr == stokens[1]) return TRUE;

      fLongitude = strtod( stokens[2], &sptr );
      if (sptr == stokens[2]) return TRUE;

      if (fLatitude  <  -90.0 ) return TRUE;
      if (fLatitude  >   90.0 ) return TRUE;
      if (fLongitude < -180.0 ) return TRUE;
      if (fLongitude >  180.0 ) return TRUE;

      pConfig_a->Projection.iRadarLat = iBin4FromFDeg(fLatitude);
      pConfig_a->Projection.iRadarLon = iBin4FromFDeg(fLongitude);
      return FALSE;
    }

  /* See if the line contains the SITENAME command */
  if ( 0 == strcmp( "SITENAME", stokens[0] ) )
    {
      if ( icount < 2 ) return TRUE;
      
      spacify_ncpy( pConfig_a->sIngSitename, stokens[1], 16 );
      return FALSE;
    }
  
  
  if ( 0 == strcmp( "VERBOSE", stokens[0] ) )
    {
      pConfig_a->lVerbose = TRUE;
      return FALSE;
    }

  /* Unrecognized lines will generate a syntax error */
  return TRUE;
}

/* ===========================================
 * Print string to log and terminal, if desired.
 */
static void Lprintf
( const char *sString_a )
{
  if (CSetup_c.lLogToTerm) fputs( sString_a, stderr );
  if (CSetup_c.lLogToFile)
    {
      fputs( sString_a, CSetup_c.iLogFile );
      fflush( CSetup_c.iLogFile );
    }
}


/* ===============================================
 * Fill in the radar position in pixels*1000, etc., from other information
 * in the setup file.
 */
static void FillProjectionNumbers
( struct projection_summary8 *pProj_a )
{ 
  MESSAGE istatus;
  struct mpj_projection8 mpj;
  struct mpj_region8     region;
  FLT8  fypix_org; 

  /* As a default, set reference to center */
  pProj_a->iReferenceLat = pProj_a->iCenterLat;
  pProj_a->iReferenceLon = pProj_a->iCenterLon;

  /* Initialize outputs in case of an error return
   */
  pProj_a->iXRadPos = 0;
  pProj_a->iYRadPos = 0;

  mpj.iprojection_type = pProj_a->iType;
  mpj.Ref.fLat         = fRadianFromBin4( pProj_a->iReferenceLat );
  mpj.Ref.fLon         = fRadianFromBin4( pProj_a->iReferenceLon );

  region.Loc1.fLat = fRadianFromBin4( pProj_a->iCenterLat );
  region.Loc1.fLon = fRadianFromBin4( pProj_a->iCenterLon );
  region.fxpix = (FLT8)pProj_a->iXSize;
  fypix_org = (FLT8)pProj_a->iYSize;
  region.fde  = pProj_a->fXRes * (region.fxpix/2);
  region.fdn  = pProj_a->fYRes * (fypix_org/2);

  /* Apply various correction factors */
  switch ( pProj_a->iType )
    {
    case MAPROJ_PERSPECTIVE:
      /* Mysterious correction factor */
      region.fde *= pProj_a->fPerspectiveCorrection;
      region.fdn *= pProj_a->fPerspectiveCorrection;
      break;
    case MAPROJ_MERCATOR:
      /* Mercator requires correcting by the cosine of the reference latitude */
      region.fde *= cos(mpj.Ref.fLat);
      region.fdn *= cos(mpj.Ref.fLat);
      break;
    }

  istatus = mpj_pin_region( &mpj, &region, MPJ_LOC1|MPJ_FDE|MPJ_FDN );
  if (istatus != SS_NORMAL)
    {
      sig_signal( istatus );
      return;
    }
//  printf("FRES %8.5f\n", region.fde); 

  /* Now rescale to product the correct Y-size. It may be correct already
  ** for some AED projections
  */
  if ((fabs(region.fypix - fypix_org)) > .5)
  {
    FLT8 fratio;
    fratio = fypix_org/region.fxpix;
    istatus = mpj_rescale_region(&mpj, &region, MPJ_LOC1|MPJ_FDE, fratio);
    if (istatus != SS_NORMAL)
    {
      sig_signal( istatus );
      return;
    }
  }

  /* Fill in the final X & Y sizes and scales
   */
  pProj_a->iXSize  = NINT( region.fxpix );
  pProj_a->iYSize  = NINT( region.fypix );
  pProj_a->iXScale = NINT( 200000.0*region.fde/region.fxpix);
  pProj_a->iYScale = NINT( 200000.0*region.fdn/region.fypix);
  
  /* Fill in the radar location in fractional pixels within the
   * data array.  If pointer is NULL, then use the center.
   */
  {
    struct latlon8 RadarEarth;
    struct XYPoint8 Pix; UINT1 lValid;
    RadarEarth.fLat = fRadianFromBin4( pProj_a->iRadarLat ) ;
    RadarEarth.fLon = fRadianFromBin4( pProj_a->iRadarLon ) ;
    
    mpj_earth_to_pixel( &mpj, &region, &RadarEarth, &Pix, &lValid ) ;
    
    pProj_a->iXRadPos = NINT( 1000.0 * Pix.fX ) ;
    pProj_a->iYRadPos = NINT( 1000.0 * Pix.fY ) ;
  }
  return;
}
/* ==============================
 * Exit handler to remove the temporary file, if any.
 */
static void ExitHandler(void)
{
  if (sPathSDSImage[0]) unlink(sPathSDSImage);
}


