/* 
@(#) File name: fci2_sw.c	Release: 1.2	Date: 1/13/94, 10:02:19
*/

/****************************************************************************
PROGRAM:
	fci2_sw

PURPOSE/DESCRIPTION:

	Program fci2_sw contains the sample read routines for all FIRE Cirrus 
	II data sets in ASCII format.  The functions in this program are 
	named closely after the applicable data sets.  For example, function 
	noaa_wndprfl() is the sample read routine for the NOAA windprofiles 
	data set.  This program will produce the following C executables: 
	class_sonde, csu_prt6, csu_sondes, csu_station1, csu_station2, 
	csu_wndprfl, doplr_lidar, maps, noaa_wndprfl, nws_sonde, pams, and 
	raman_lidar.
	All executables allow multiple input files as input arguments and 
	process them in sequence.  With the exception of doplr_lidar, all 
	output are sent to the standard output device.  The output can be 
	redirected to a file for reviewing.  The doplr_lidar has two parts 
	of data: profile directory and the profile records.  The profile 
	directory are written to the standard output device, but the profile 
	records are written to a file.  Any error in reading the data will 
	be written to the standard error device.
	
ALGORITHM: None.

INVOCATION:
	prgram_name [-s] data_file1 data_file2 ...

   WHERE
	<prgram_name> 
	   is one of the 12 executable files mentioned in the purpose section.
	<data_file1 data_file2 ...> 
	   are the data file names (not granule names) of an applicable data set.
	<-s> 
	   is an optional option that is ONLY applied to the maps data set.  It
	   has to be the first argument in the argument list, if invoked.

FILE/RECORD REFERENCES: None.

EXTERNAL ROUTINES:  None.

NOTES:
	The rationale behind these read routines are to provide a flexible 
	and easy to use read routine for the user.  Hopefully, this program 
	can allow users to know the format of the variables in the ASCII 
	files, and customize to suit their own needs in viewing the data
	with the graphics tools.

*****************************************************************************/

#include  <values.h>
#include "fci2_sw.h"

/**** Since HP 300/400 series does not support rint(), and nint() functions, 
      these function are defined as macros when this program module is run 
      under the HP UX.  When the user compile this module, add "-D hpux" in 
      the compilation command.  
 ****/
 
#ifdef HPUX
#   define rint(x)  ((int) (x < 0.0) ? (x - 0.5) : (x + 0.5))
#else
extern double rint();
#endif 

#ifdef HPUX
#   define nint(x)  ((int) rint(x))
#endif 


    /****  Local library functions, provided in fci2_lib.c file.  ****/
extern int  julian_day(), str_trim();
extern void  interrupt_cat(), hd_sondes();
extern char  *strdup();


main (argc, argv)
int  argc;
char **argv;
{
    void  class_sonde(), csu_prt6(), csu_sondes(), csu_station(), csu_wndprfl ();
    void  doplr_lidar(), maps(), noaa_wndprfl(), nws_sonde(), pams(), raman_lidar();

    
    if (signal (SIGINT, SIG_IGN) != SIG_IGN)
        signal (SIGINT, interrupt_cat);

    (void) signal (SIGTERM, interrupt_cat);

#ifdef CLASS_SONDE
    (void) class_sonde (argc, argv);
#endif

#ifdef CSU_PRT6
    (void) csu_prt6 (argc, argv);
#endif

#ifdef CSU_SONDES
    (void) csu_sondes (argc, argv);
#endif

#ifdef STATION1
    (void) csu_station (argc, argv);
#endif

#ifdef STATION2
    (void) csu_station (argc, argv);
#endif

#ifdef CSU_WND
    (void) csu_wndprfl (argc, argv);
#endif

#ifdef DOPLR_LIDAR
    (void) doplr_lidar (argc, argv);
#endif

#ifdef MAPS
    (void) maps (argc, argv);
#endif

#ifdef NOAA_WND
    (void) noaa_wndprfl (argc, argv);
#endif

#ifdef NWS_SONDE
    (void) nws_sonde (argc, argv);
#endif

#ifdef PAMS
    (void) pams (argc, argv);
#endif

#ifdef RAMAN_LIDAR
    (void) raman_lidar (argc, argv);
#endif

    exit (0);

}

/****************************************************************************
FUNCTION:
	class_sonde ()

PURPOSE/DESCRIPTION:
	Function class_sonde reads in NCAR class sondes data.  Note that among 
	the three versions of a given sounding that NCAR class data have, 
	Langley DAAC has only "i" version, which is the sounding data with 
	data interpolated to every 5mb level.
	
INVOCATION:
	(void)  class_sonde (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple class 
	   sonde data files.  For example,  
	         class_sonde ib252317.iol ib291343.cof
	   will read two files: ib252317.iol, and ib291343.cof.
  
FILE/RECORD REFERENCES:
	Each class sonde file is named `imddhhMM.sta',  where m is the month 
	(values [1-9, a-c];b=Nov), dd the day of month, hh the hour sounding 
	start (GMT was used for CaPE), MM the minute for sounding start (hhMM 
	is approximate), and sta the 3-letter station ID.

EXTERNAL ROUTINES:  None.

NOTES: 
1.)     There are 21 variables defined in the data structure class_data in 
        fci2_sw.h file.  Also, see README.fci2 for variables descriptions. 
2.)	Output format string for the 21 variables are as follows:
	"%7.2f%8.3f%6.1f%7.2f%7.2f%6.1f%6.1f%9.4f%7.2f%7.2f%6.1f%6.1f
	 %6.1f%6.1f%8.0f%7.2f%7.2f%8.3f%8.3f%9.4f%9.4f" 
	
*****************************************************************************/

void  class_sonde (argc, argv)
int  argc;
char **argv;
{

    FILE  *fptr;
    char  filename[200], buf[250], ddhhmm[7];
    char  *base, *head[3], *lines[12], comma;
    char  datatype[20], project[40], sitetype[20], site_id[20], sys_opr[40];
    char  wnd_type[20], processor[30], wnd_smooth[30], obs_src[50];
    char  lon_str[20], lat_str[20], lon[20], lat[20], alt[20], comment[250];
    int  year, month, day, hour, minute, second;
    int  i, j, k, l, nrec;
    class_data  dat;                     /* Defined in file fci2_sw.h */
    
    
    i = 0;
    while (i++ < (argc-1))    {
        l = 0;
        strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr, "ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
            
        base = strrchr (filename, '/');
        base = (base == NULL) ? filename : (++base);

	/* Read in HEADER information. */
	for (j = 0; j < 12; j++)    {
            fgets (buf, sizeof(buf), fptr);
            str_trim (buf, 0);    lines[l++] = strdup (buf);
        }
        
        /* Decode field info. in each line, comma (,) is used to be a 
         * field separator. */
         
	    /* Read in Data Type, the first line in the file */
        strcpy (datatype, &lines[0][PARAM_POS]);
            /* Read in project ID, the second line in the file */
        strcpy (project, &lines[1][PARAM_POS]);
        
	    /* Read in launch site type and site ID, the 3rd line in the file */
        sscanf (&(lines[2][PARAM_POS]), "%[^,]%c%s", sitetype, &comma, site_id);
	    /* Read in launch location (lon, lat, alt), the 4th line in the file */
        sscanf (&(lines[3][PARAM_POS]), "%[^,]%c%[^,]%c%[^,]%c%[^,]%c%s", 
             lon_str, &comma, lat_str, &comma, lon, &comma, lat, &comma, alt);
	    /* Read in gmt launch time (y,m,d,hh:mm:ss), the 5th line in the file */
        sscanf (&(lines[4][PARAM_POS]), "%4d%c%2d%c%2d%c%2d%c%2d%c%2d", 
             &year, &comma, &month, &comma, &day, &comma, &hour, &comma, 
             &minute, &comma, &second);
        sprintf (ddhhmm, "%02d%02d%02d", day, hour, minute);
        if (strncmp (&(base[2]), ddhhmm, 6) != 0)    {
            fprintf (stderr,"WARNING: Time in the data file = %s, but file name is %s\n", 
                ddhhmm, base);
/**            continue;      **/
        }

	/* Skip the 6th line in the file containing Sonde Type, Sonde ID, 
	 * Sensor ID/Tx frequency; and the 7th line in the file containing 
	 * Met Processor/Met Smoothing. 
	 */
        
	    /* Read in Winds Type/Processor/Smoothing, the 8th line in the file */
        sscanf (&(lines[7][PARAM_POS]), "%[^,]%c%[^,]%c%[^,]", wnd_type, 
               &comma, processor, &comma, wnd_smooth);
	    /* Read in Pre-launch Surface Obs Source, the 9th line in the file */
        strcpy (obs_src, &lines[8][PARAM_POS]);
            /* Read in System Operator/Comments, the 10th line in the file */
        sscanf (&(lines[9][PARAM_POS]), "%[^,]", sys_opr);
        strcpy (comment, &(lines[9][PARAM_POS+strlen(sys_opr)+1]));
        
        /* Skip two lines (l1th and 12th lines) containing only / */

        for (j = 0, k = 0; j < 3; j++)    {
            fgets (buf, sizeof (buf), fptr);
            str_trim (buf, 0);    head[k++] = strdup (buf);
        }

        nrec = 0;

	    /***** Read in data record. ****/
        while (fgets (buf, sizeof (buf), fptr) != NULL)    {
            str_trim (buf, 0);
            sscanf (buf, "%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%d", 
		&dat.sec, &dat.pressure, &dat.c_temp, &dat.dewpoint, 
		&dat.rhumidity, &dat.uwind, &dat.vwind, &dat.wnd_speed, 
		&dat.wnd_dir, &dat.dz, &dat.longitude, &dat.latitude, 
		&dat.range, &dat.angle, &dat.altitude, &dat.qp, &dat.qt,
		&dat.qh, &dat.qu, &dat.qv, &dat.quv);

/**  Commented out the following two lines if the column headings are not 
 **  desired in the output page. 
 **/        
            if ((nrec++) % 40 == 0)
               (void) hd_sondes (filename, l, lines, k, head);

/*            printf ("%s\n", buf);  */ 
            printf (CLASS_FMT, dat.sec, dat.pressure, dat.c_temp, dat.dewpoint,
                dat.rhumidity, dat.uwind, dat.vwind, dat.wnd_speed,   
                dat.wnd_dir, dat.dz, dat.longitude, dat.latitude, 
                dat.range, dat.angle, dat.altitude, dat.qp, dat.qt, 
                dat.qh, dat.qu, dat.qv, dat.quv); 
        } 
        printf ("** Total records read in file %s = %d **\n", filename, nrec);
            /*  Clear the buffer  */
        for (j = 0; j < l; j++)
            free (lines[j]); 
        for (j = 0; j < k; j++)
            free (head[j]); 
        fclose (fptr);
    }
}


/****************************************************************************
FUNCTION:
	csu_prt6 ()

PURPOSE/DESCRIPTION:
	CUS_PRT6 reads in CSU PRT-6 data taken during the FIRE cirrus IFO 
	Phase II Experiment.  This program reads the record one at a time 
	in the data file, validates julian day and time (hour-second) values   
	within each record, then sends the validated record to the standard 
	output device.  The PRT-6 was not run in a continuous mode.  Data 
	was collected during the period from Nov. 18, 1991 (day 322) to 
	Dec. 7, 1991 (day 341) when operating.  Data was sampled at 5 seconds 
	interval.  The site was at 37 deg 18 min N and 95 deg 07 min W.
	
	WARNING: There are temporal gaps in the data.  When there are 
	temporal gaps in the data, a '+' sign will be added to the end 
	of the brightness temperature value.  
	
INVOCATION:
	(void) csu_prt6 (argc, argv);
	
   WHERE 
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple csu 
	   prt6 data files.  For example, if the executable is csu_prt6, 
	   then,         csu_prt6 ci2_prt6_911118 ci2_prt6_911203
	   will read two files: ci2_prt6_911118, and ci2_prt6_911203.

FILE/RECORD REFERENCES:
	The data files are named ci2_prt6_yymmdd, where yy is the year, 
	mm the month (only 11 and 12 are valid), and dd the day (UTC) when 
	the data were collected.

EXTERNAL ROUTINES:  None.

NOTES:
	There are four input variables in the PRT-6 data files.  They are:
	1) julian day (UTC), 2) hour-minute (UTC), 3) second (UTC), 
	4) equivalent brightness temperature (K)
	
	The output file has the following information on each page: 
	line 1: csu prt6 file name, e.g., ci2_prt6_911118
	line 2: column header
	line 3: blank
	line 4 through 54: data.  The data field and its data type are:
	    1) day (UTC), integer;
	    2) HHmm (UTC), where HH is the hour, mm is the minute, integer;
	    3) second (UTC), float, up to 4 digits precision
	    4) equivalent brightness temperature (K), float, up to 3 digits
	       precision.
	
*****************************************************************************/

void  csu_prt6 (argc, argv)
int  argc;
char **argv;
{

    FILE  *fptr;
    void  hd_csu_prt6();
    char  filename[200], hr_min[16];
    int  i=0, day, hour, minute, nrec;
    float  second, float_day, bright_temp, last_time, curr_time;
    
    
    while (i++ < (argc-1))    {
	strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr, "ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
        nrec = 0;    last_time = 0.0;
            /****  Read the data record one by one.  ****/
        while (fscanf (fptr, "%f %s %f %f", &float_day, hr_min, &second, &bright_temp) != EOF)    {
            if (atoi(hr_min) >= 100)    {   /* Has hour and minute values. */
                hour = atoi(hr_min) / 100;
                minute = atoi (hr_min) % 100;
            } else    {
                hour = 0;
                minute = atoi (hr_min);
            }
            day = (int)float_day; 
                       
            curr_time = hour * 3600 + minute * 60 + second;
            
/**  Commented out the following line if the three header lines are not  
 **  desired in the output.
 **/
            if (nrec % 55 == 0)    (void) hd_csu_prt6 (filename);
            
/**  The following printf statement prints out the 4 data fields.
 **/ 
            if ((nrec++ > 0) && (nint (curr_time - last_time) != 5))      
                printf ("%03d %8d  %07.4f    %.3f +\n", day, atoi(hr_min), 
                     second, bright_temp);
            else
                printf ("%03d %8d  %07.4f    %.3f\n", day, atoi(hr_min), 
                     second, bright_temp);
            
            last_time = curr_time;
        }
        printf ("Total records read in file %s = %d\n", filename, nrec);
        fclose (fptr);
    }
}

void  hd_csu_prt6 (filename)
char  *filename;
{

    printf ("File name: %s\n", filename);
    printf ("%3s %8s %7s %s\n\n","DAY","HHmm","SECOND","BRIGHTNESS_TEMP");
    
}

/****************************************************************************
FUNCTION:
	csu_sondes ()
  
PURPOSE/DESCRIPTION:
	CUS_SONDES reads in FIRE-II CSU Rawindsonde data at Parsons KG&E Power 
	Plant.  Sondes were launched primarily in support of surface radiation 
	measurements for the period from Nov 13, 1991 (Julian day 317) to 
	Dec. 6, 1991 (Julian day 340).  The site was at 37 deg 18 min N and 
	95 deg 07 min W.  Data points with values of -9999.0 are bad.

	WARNING: Because of problems tracking the sonde, the angles of the 
	tracking antenna should be used with caution.  They are provided to 
	allow a calculation of an approximate location of the sonde.

INVOCATION:
	(void) csu_sondes (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple csu 
	   sondes data files.  For example, if the executable is csu_sondes, 
 	   then,         csu_sondes 911113.1828s 911205.1425s
	   will read two files: 911113.1828s and 911205.1425s.

FILE/RECORD REFERENCES:
	Data files are named YYMMDD.hhmms where YY is the year, MM the month, 
	DD the day, hh the hour, and mm the minute of the launch time.  The 
	first record in the file should start with the same time as the 
	launch time.
	
EXTERNAL ROUTINES:  julian_day()

NOTES:
1.)	There are 10 variables in the input file.  They are:
	julian day (UTC), hour (UTC), minute (UTC), second (UTC),
	geopotential height (km), pressure (mb), temperature (K),
	relative humidity (%), azimuth angle (deg), elevation angle (deg)
	
2.)	The output file has the following format: 
	line 1: csu sondes file name, e.g., 911125.0009s
	line 2: Bad data value, which is -9999.00
	line 3: blank
	line 4 through 54: data.  The same ten fields as in the input file. 

3.)	Except for the time values, format for the other six variables are F9.3.

*****************************************************************************/

void  csu_sondes (argc, argv)
int  argc;
char **argv;
{

    FILE  *fptr;
    void  hd_csu_sondes();
    char  filename[200], *s, *str;
    int  i=0, jul, year, month, day, doy, hr, min, nrec;
    float  sec, geo_height, pressure, temp, humidity, azimuth, elevation;
    
    while (i++ < (argc-1))    {
        strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr, "ERROR: Can't open file:\t %s\n", argv[i]);
            continue;
        }
        nrec = 0;
        s = strrchr (filename, '/');
        str = (s == NULL) ? &(filename[0]) : (++s);
        sscanf (str, "%2d%2d%2d", &year, &month, &day);
        jul = julian_day (year, month, day);
        
            /****  Read the csu_sondes data records.   ****/
        while (fscanf (fptr, "%d%d%d %f %f%f%f%f%f%f", &doy, &hr, &min, &sec, 
          &geo_height, &pressure, &temp, &humidity, &azimuth, &elevation) != EOF)
        {
            if (doy != jul)    {
                if ((doy * 24 * 60 + hr * 60 + min) <= (jul * 24 * 60))
                    printf ("ERROR?? file %s, Rec. num = %d, Julian day = %d; doy=%d\n", 
                       filename, nrec, jul, doy);
                /* Otherwise, the data coverage cross the midnight. */
            }

/**  Commented out the following line if the column heading is not desired 
 **  in the output.
 **/
            if ((nrec++) % 55 == 0)    (void) hd_csu_sondes (filename);
            
/**  The following 3 printf statements print out all ten data fields. 
 **/
            printf ("%-4d %-2d %-02d %5.2f ", doy, hr, min, sec);
            printf ("%9.3f %9.3f %9.3f ", geo_height, pressure, temp);
            printf ("%9.3f %9.3f %9.3f\n", humidity, azimuth, elevation);

        }
        printf ("** Total records read in file %s = %d **\n\f", filename, nrec); 
        fclose (fptr);
    }
}

void  hd_csu_sondes (filename)
char  *filename;
{

    int  i;
    static char  *fields[2][10] = {
       {"Day", "Hr", "Min", "Sec. ", "Geop.", "Pressure", "Temp", 
        "Relative", "Azimuth", "Elev."},
       {" ", " ", " ", " ", "height(km)", "(mb)", "(K)", 
        "hum. (%)", "(degree)", "(degree)"}  };   /** Column headings **/

       
    printf ("\f\nFile name: %s\nBad data value: %.1f\n", filename, BAD_DATA);
   
    printf ("%3s %2s %3s %5s ",fields[0][0],fields[0][1],fields[0][2],fields[0][3]);
    for (i = 4; i < 10; i++)    printf("%9s ", fields[0][i]);
    
    printf ("\n%3s %2s %3s %5s ",fields[1][0],fields[1][1],fields[1][2],fields[1][3]);
    for (i = 4; i < 10; i++)    printf("%9s ", fields[1][i]);

    printf ("\n\n");
    
}

/****************************************************************************
FUNCTION:
	csu_station ()

PURPOSE/DESCRIPTION:
	Function csu_station reads the Fire CI2 CSU Station1 and CSU Station2 
	data.  Instantaneous values of the parameters were collected every 2 
	minutes for the period from 11 Nov 1991 (day 315) to 8 Dec 1991 (day 
	342).  The site was at 37 deg 18 min N and 95 deg 07 min W.
	
	Since station1 and station2 has different number of variables (19 vs. 
	11), conditional compilation is needed to generate two executables 
	(one for reading station1 data, the other for reading station2 data) 
	from the same source code (See NOTES 1 below).  NOTE that the 
	executable for station1 can read multiple station1 data files, but not 
	the combinations of station1 and station2 data files.  Same statements 
	apply to the station2 executable.  This program reads the record one 
	at a time in the data file, validates julian day and the time (hour-
	minute) values within each record, then sends the validated record 
	to the standard output device.
	
INVOCATION:
	(void) csu_station1 (argc, argv); or  (void) csu_station2 (argc, argv);

   WHERE 
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple Par 
	   station data file names.  For example, if the executable is 
	   csu_station1, then, 
	        csu_station1 ci2_s1kge_911113 ci2_s1kge_911121
	   will read two files: ci2_s1kge_911113, and ci2_s1kge_911121.

FILE/RECORD REFERENCES:
	Station1 data files are named ci2_s1kge_yymmdd, where yy is the year, 
	mm the month, and dd the day.  
	Station 2 data files are named ci2_s2tri_yymmdd, where yy is the year, 
	mm the month, and dd the day.
	Missing data and extreme values are marked with -9999.0.

EXTERNAL ROUTINES:  None.

NOTES:
1.)   To build executable for csu_station1:
      cc -DSTATION1 -o csu_station1 ...
And, To build executable for station2:
      cc -o csu_station2 .... 
	
2.)	There are 19 variables in the CSU station1 data file, and 11 varaibles
        in the CSU station2 data file.  The variables with units and estimated 
        precision (in units) are listed under section 5 of the README.fci2 file.  

3.)	The output file has the following format: 
	line 1: station1 or station2 file name, e.g., ci2_s1kge_911113
	line 2: Bad data value, which is -9999.0
	line 3: blank
	line 4: column heading
	line 5: units for the variables
	line 6: blank
	line 7 through 44: data.  The same fields as in the input file. 
	
*****************************************************************************/

/**********************************************************************
 *   There are 8 direct solar filters related variables for CSU station1 
 *   data.  They are put in a data structure called "dir_solar". 
 **********************************************************************/

void  csu_station (argc, argv)
int  argc;
char  **argv;
{

    dir_solar  st;               /** Defined in fci2_sw.h file **/
    FILE  *fptr;
    void  hd_stations();
    float  ftime, wnd_spd, wnd_dir, temp, humidity, sol_irr; 
    float  ninf_irr, inf_irr, dome_tmp, sink_tmp, hr, min;
    char  filename[200], buf[400], *s;
    int  i=0, nrec, day, hhmm, hour, minute;

     
    while (i++ < (argc-1))    {
	strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr, "ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
        nrec = 0;
        
    /** Read in all 19 variables for station1, or 11 variables for station2. **/
        while (fgets (buf, sizeof (buf), fptr) != NULL)    {
        
#ifdef STATION1
            sscanf (buf, "%f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %d",
                &ftime, &wnd_spd, &wnd_dir, &temp, &humidity, &sol_irr, &ninf_irr, 
                &inf_irr, &dome_tmp, &sink_tmp, &st.yfilter, &st.rfilter, 
                &st.drfilter, &st.n90filter, &st.n0filter, &st.n30filter, 
                &st.n60filter, &st.nfilter, &hhmm);
#else 
            sscanf (buf, "%f %f %f %f %f %f %f %f %f %f %d", &ftime, 
                &wnd_spd, &wnd_dir, &temp, &humidity, &sol_irr, &ninf_irr, 
                &inf_irr, &dome_tmp, &sink_tmp, &hhmm);
#endif
            
/**  Commented out the following line if the header printout is not necessary.
 **/   
            if (nrec % 45 == 0)    (void) hd_stations (filename);

            
/*  Check the first column value (ftime) and the last column value (hhmm). */

            hour = (hhmm >= 100) ? (hhmm/100) : 0;
            minute = (hhmm >= 100) ? (hhmm % 100) : hhmm;
        
            hr = (ftime - (int)ftime) * 24; 
            min = (float) rint ((hr - (int)hr) * 60);
            /* Because of floating point rounding and truncation, the following 
             * two lines of codes are used to smoothe possible margin of errors.
             */
            hr = (int)hr + (min / 60);
            min = (min >= 60.0) ? (min - 60.0) : min;
        
            /*  Check the hour and minute values. */
            if (hhmm != (int)MISSING)    {
                if (((int)hr != hour) || ((int)min != minute))
                    fprintf (stderr,"ERROR: Rec.# = %d, Julian time =%f, hr/min =%2d2%d\n", 
                             nrec+1, ftime, hour, minute);
            }
            
            printf ("%10.6f %10.6f %10.6f %10.6f ", ftime, wnd_spd, wnd_dir, temp);
            printf ("%10.6f %10.6f %10.6f ", humidity, sol_irr, ninf_irr);
            printf ("%10.6f %10.6f %10.6f ", inf_irr, dome_tmp, sink_tmp);                       

#ifdef STATION1
            printf ("%12.6f %12.6f %12.6f ",st.yfilter,st.rfilter,st.drfilter);  
            printf ("%12.6f %12.6f %12.6f ",st.n90filter,st.n0filter,st.n30filter);  
            printf ("%12.6f %12.6f ",st.n60filter,st.nfilter);  
#endif
            
            printf ("%4d\n", hhmm);

            nrec++;
        }
        printf ("Total %d lines processed in file %s\n", nrec, filename); 
        fclose (fptr);
    }
}


void  hd_stations (filename)
char  *filename;
{
    int i;
    static char *fields[2][10] = {
        {"Time","Wnd Speed","Wnd Dir","  Temp","Humidity","SolTot IRR",
         "NI_IRR","INF_IRR","Dome Temp","Sink Temp"}, 
        {"UTC"," (m/s) ","degrees"," (C) "," (%) ","W/m**2","W/m**2","W/m**2",
         " (K) "," (K) "}  };
#ifdef STATION1
    static char *st1_fld[2][8] = {
        {"Y_filter","R_filter","DR_filter","90_sec NF","0_sec NF","30_sec NF",
         "60_sec NF","90_sec NF"},  {"W/m**2","W/m**2","W/m**2",
        "W/m**2","W/m**2","W/m**2","W/m**2","W/m**2"}  };
#endif


    printf("\fFile Name: %s\nMissing data value: %.1f\n\n", filename, MISSING);
    for (i = 0; i < 10; i++)    printf("%10s ", fields[0][i]);

#ifdef STATION1
    for (i = 0; i < 8; i++)    printf("%12s ", st1_fld[0][i]);
#endif

    printf("%-10s\n", "HourMinute");
                
    for (i = 0; i < 10; i++)    printf("%10s ", fields[1][i]);
    
#ifdef STATION1
    for (i = 0; i < 8; i++)    printf("%12s ", st1_fld[1][i]);
#endif
    printf("%-10s\n\n", "HHMM");
    
}


/****************************************************************************
FUNCTION:
	csu_wndprfl ()
	
PURPOSE/DESCRIPTION:
	Funciton csu_wndprfl reads in CSU wind profiler data, which are single 
	cycle data collected at Parsons, KS from 2 Nov 1991 7 Dec 1991.

INVOCATION:
	(void) csu_wndprfl (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple CSU 
	   windprofiles data file names.  For example,  
	       csu_wndprfl 91120410.wp 91120422.wp
	   will read two files: 91120410.wp, and 91120422.wp.

FILE/RECORD REFERENCES:
	The file names of the data is YYMMDDHH.wp where YY is the year, MM the 
	month, DD the day, and HH the hour the data were collected. 
	BAD data value for u and v variables: -9999.0.
	
EXTERNAL ROUTINES:  None.

NOTES:
        This data has been through a quality control program using the 
        Weber and Wuertz QC subroutines.  Thresholds of 4m/s and 5% size of 
        largest pattern was used on combined-low/high-mode-opposing-beams 
        profile.  Note vertical velocity was assumed to be zero. (28% of 
        the dataset was marked as "bad".)  
        
        There are four input variables in the CSU wind profiler data files.  
        They are listed in order as follows:
	1) minute, 2) height (km above MSL), 3) u (m/s), 4) v (m/s)
	The first line in the file is the header line, which contains year, 
	month, day, hour information.  See README.fci2 file for the variable 
	formats.
	
	The output of the CSU wind profiler data has the following format
	on each page (assuming 56 lines per page output):
	line 1: file name; e.g., 91120410.wp
	line 2: YY:MM:DD:HH
	line 3: blank
	line 4: column heading
	line 5: blank
	line 6 through 56: data 
	1) dd:hh:mm:ss, where dd is the julian day, hh is the hour, mm is 
	   the minute, ss is the second.
	2) equivalent brightness temperature (K)

*****************************************************************************/


void  csu_wndprfl (argc, argv)
int  argc;
char **argv;
{

    FILE  *fptr;
    void  hd_csu_wnd ();
    char  filename[200], header_str[100], date_str[16], *s;
    int  i=0, year, month, day, hour, second, nrec;
    float  height, u_wnd, v_wnd;
    
    
    while (i++ < (argc-1))    {
	strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr, "ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
        nrec = 0;
        
        s = strrchr (filename, '/');
        s = (s == NULL) ? filename : ++s;
        fgets (header_str, sizeof(header_str), fptr);
        str_trim (header_str, 0);
        
        if (strncmp (header_str, s, strlen (header_str)) != 0)
            fprintf (stderr,"File (%s) NOT consistent with the header (%s).\n", 
                     filename, header_str);
        
        sscanf (header_str, "%2d%2d%2d%2d", &year, &month, &day, &hour);
        sprintf (date_str, "%02d:%02d:%02d:%02d", year, month, day, hour);
         
        while (fscanf(fptr,"%d %f %f %f",&second,&height,&u_wnd,&v_wnd) != EOF) 
        {
/**  Commented out the following line if the column headings are not 
 **  desired in the output page. 
 **/
            if ((nrec++) % 55 == 0)    (void) hd_csu_wnd (filename, date_str);
            
            printf ("%2d %7.3f %9.3f %9.3f\n", second, height, u_wnd, v_wnd);
            
        }
        printf ("Total of %d records read in file %s\n", nrec, filename); 
        fclose (fptr);
    }
}

void hd_csu_wnd (filename, date_time)
char  *filename, *date_time;
{

    int  i;
    static char  *fields[4] = {"Min.", "Height", "U_WND (m/s)", "V_WND (m/s)"};
    
    
    printf ("\fFilename: %s\ndate_time: %s\n\n", filename, date_time);
    for (i = 0; i < sizeof (fields[0]); i++)
        printf ("%s ", fields[i]);
    printf ("\n");
    
}


/****************************************************************************
FUNCTION:
	doplr_lidar ()

PURPOSE/DESCRIPTION:
	Function doplr_lidar reads the doppler lidar data sets.  The Doppler 
	lidar experiment objective was to obtain lidar measurements of relative 
	backscatter signal intensity and radial velocity from cirrus clouds to 
	study their microphysical and radiative properties.  This data set 
	provides Vertical profiles (approx. 1.5 - 20.0 km AGL) data.
	
	The profile directory are written to the standard output device, but 
	the profile records are written to a file.  The profile records are 
	processed by the function "read_vad_profile".  This will allow the 
	easier implementation of extracting subsets of the profile records. 
	
INVOCATION:
	(void) doplr_lidar (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple doppler 
	   lidar data file names.  For example,  
	       doplr_lidar fire2vad28nova fire2vad21nova
	   will read two files: fire2vad28nova, and fire2vad21nova.
 
FILE/RECORD REFERENCES:
	All except one doppler lidar data file is named `fire2vadDDMMMa', where 
	DD is the day of month, and MMM the month (either nov or dec).  The 
	one file is named fire2vad91a, which contains the annual data.  Each 
	file contains the directory of all profiles in this file, followed by 
	the profile records.
	
EXTERNAL ROUTINES:  None.

NOTES:
1.      See README.fci2 file for a list of variables in the directory line, 
        and the variables in each profile record. 

*****************************************************************************/

void  doplr_lidar (argc, argv)
int  argc;
char **argv;
{
    FILE  *fptr;
    void  hd_doplr_lidar ();
    char  filename[200], buf[120], *s;
    int  i=0, beg_num=0, end_num;
	/* The following belongs to VAD profile file directory line. */
    int  prof_num, date, time;
    float  elevation, beg_azimuth, end_azimuth;
    int  sweep_num, sweep_dir, qa_flag, site_num, beg_rec_num, end_rec_num;
    char  mswitch[12];
    int  beg_gate, end_gate, noisegate, energy_flg, process_date, process_time;
    float  mean_vel, mean_power, threshold, range_noisegate, noise_in_gate;


    while (i++ < (argc-1))    {
	strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr,"ERROR: Can't open file:\t %s\n", filename);
            continue;
        }

        /**  Read the directory section  **/
        printf ("\n\nDirectory of profiles within the file \"%s\"\n", filename);
        for (i = 0; i < 3; i++)    {
            fgets (buf, sizeof (buf), fptr);
            str_trim (buf, 0);
            (void) hd_doplr_lidar ((int)PROFILE_DESC, buf, (FILE *)NULL);
        }
        while (fgets (buf, sizeof (buf), fptr) != NULL)    {
            str_trim (buf, 0);
            for (s = &buf[0]; (*s == ' ') && (*s != '\0'); s++)  ;
            if (!isdigit (*s))   break;   
            sscanf (s, "%d%d%d%f%f%f%d%d%d%d%d%d", &prof_num, &date, &time, 
               &elevation, &beg_azimuth, &end_azimuth, &sweep_num, &sweep_dir,
               &qa_flag, &site_num, &beg_rec_num, &end_rec_num);
            (void) hd_doplr_lidar ((int)PROFILE_DESC, buf, (FILE *)NULL);
        }
        end_num = prof_num;

        /* Skip over file contents descriptions. */
        while (fgets (buf, sizeof (buf), fptr) != NULL)    {      
            for (s = &buf[0]; (*s == ' ') && (*s != '\0'); s++)    ;
            if (isdigit (*s))   break;   
            str_trim (buf, 0);
            (void) hd_doplr_lidar ((int)PROFILE_DESC, buf, (FILE *)NULL);
        } 

        read_vad_profile (fptr, filename, buf, beg_num, end_num);

        fclose (fptr);
    }
}

/****************************************************************************
FUNCTION:
	read_vad_profile ()

PURPOSE/DESCRIPTION:
	Function read_vad_profile reads all profile records in the input file.  
	All profile records are sent to an output file.  The output file is 
	automatically generated with the name containing the input file name 
	and the process id as the file name extension.  NOTE: Because the 
	process id for each invocation of the executable is different under 
	Unix system, the output file name will be different at each run.

INVOCATION:
	status = read_vad_profile (fptr, fname, s, beg_num, end_num)

   WHERE 
	<fptr> - I
	   is the pointer of the doppler lidar data file.
	<fname> - I
	   is the file name of the doppler lidar data file.  This parameter is
	   used to construct the output file name for the profile records.  For
	   example, if the process id is 9360, the output file name will be 
	   fname.9360.
	<s> - I
	   holds the contents of the directory line.
	<beg_num> - I
	   is the begining profile number to start reading the profile records.
	<end_num> - I
	   is the end profile number for reading the profile records.
	<status> - O
	   return 0 when there is no error, otherwise a -1 is returned.

FILE/RECORD REFERENCES:
	A profile record starts with one directory line, followed by two header 
	lines, followed by multiple profile records.

EXTERNAL ROUTINES:  None.

NOTES:
1.      Except for the quality flag, output format for the other eight 
        profile parameters are "%9.3f".  Parameters are defined in the data
        structure vad_profile in the fci2_sw.h header file. 

2.      In order to keep the same command line invocation convention the same 
        across all FIRE-CI2 data sets, subsetting on the profile records were 
        deleted from the original codes.
        
*****************************************************************************/

int  read_vad_profile (fptr, fname, s, beg_num, end_num)
FILE  *fptr;
char  *fname, *s;
int  beg_num, end_num;
{
    
    vad_profile  vad;                /* Defined in fci2_sw.h file */
    void  hd_doplr_lidar ();
    FILE  *outptr;
    char  buf[120], out_file[200], *str;
    int  prof_num, date, time, i;
    float  elevation, beg_azimuth, end_azimuth;
    int  sweep_num, sweep_dir, qa_flag, site_num, beg_rec, end_rec;


    if (fptr == (FILE *)NULL)    {
        fprintf (stderr,"ERROR: Invalid file pointer.  CAN'T continue.\n");
        return (-1);
    }
    strcpy (buf, s);
    
    str = strrchr (fname, '/');
    str = (s == NULL) ? fname : str++;
    sprintf (out_file, "%s.%d", str, getpid());
    if ((outptr = fopen (out_file, "w")) == NULL)
        outptr = stdout;
    
    do    {
            /* Extract the Directory line of a profile. */
        sscanf (buf, "%d%d%d%f%f%f%d%d%d%d%d%d", &prof_num, &date, &time, 
               &elevation, &beg_azimuth, &end_azimuth, &sweep_num, &sweep_dir,
               &qa_flag, &site_num, &beg_rec, &end_rec);

        
        if ((beg_num > prof_num) || (end_num < prof_num))  {
                /* Skip over header line 1 and 2, and the records. */
            for (i = 0; i < (end_rec - beg_rec + 2); i++)
                fgets (buf, sizeof (buf), fptr);
        } else    {
                /* Print directory line */
            str_trim (buf, 0);
            (void) hd_doplr_lidar ((int)PROFILE_DAT, buf, outptr);
                /* Read the header line 1 and header line 2. */
            for (i = 0; i < 2; i++)    {
                fgets (buf, sizeof (buf), fptr);
                str_trim (buf, 0);
                (void) hd_doplr_lidar ((int)PROFILE_DESC, buf, outptr);
            }
            (void) hd_doplr_lidar ((int) PROFILE_FLD, outptr);
                /**** Read the profile records. ****/
            for (i = 0; i < (end_rec - beg_rec); i++)    {
                fgets (buf, sizeof (buf), fptr);
                sscanf (buf, "%f%f%f%f%f%f%f%d%f", &vad.altitude, 
                    &vad.wndspeed, &vad.wnd_dir, &vad.sig2noise, &vad.good_pts, 
                    &vad.rms_err, &vad.vvelocity, &vad.qa_flag, &vad.energy); 
                str_trim (buf, 0);
                (void) hd_doplr_lidar ((int)PROFILE_DAT, buf, outptr);
            }
        }
    } while ((fgets (buf, sizeof (buf), fptr) != NULL) && (prof_num < end_num));
    fclose (outptr);
    return (0);

}


void  hd_doplr_lidar (va_alist)
va_dcl
{

    va_list  var_str;
    
    int  i, ndx;
    FILE  *ptr;
    char  *s;
    static char  *fields[2][9] = {
         {"Altitude", "Wind", "Wind", "Signal/", "Good pts", 
          "RMS", "Velocity", " Flag", "Energy"}, 
         {" ", "Speed", "Dir.", "Noise", " (%)", "error", 
          "Diverg.", " ", "Per Alt."}   };
    
    
    va_start (var_str);
    
    ndx = va_arg (var_str, int);
    
    switch (ndx)    {
    case (int)PROFILE_DESC:
        s = va_arg (var_str, char *);
        ptr = va_arg (var_str, FILE *);
        if (ptr == NULL)    printf ("%s\n", s);
        else 
            fprintf (ptr, "%s\n", s);
        break;
    case (int)PROFILE_FLD:
        ptr = va_arg (var_str, FILE *);
        for (i = 0; i < 7; i++)    fprintf (ptr, "%9s", fields[0][i]);
        fprintf (ptr, "%5s%9s\n", fields[0][i++], fields[0][i]);
    
        for (i = 0; i < 7; i++)    fprintf (ptr, "%9s", fields[1][i]);
        fprintf (ptr, "%5s%9s\n\n", fields[1][i++], fields[1][i]);
        break;
    case (int)PROFILE_DAT:
        s = va_arg (var_str, char *);
        ptr = va_arg (var_str, FILE *);
        fprintf (ptr, "%s\n", s);
        break;
    }
    
    va_end (var_str); 

}
/****************************************************************************
FUNCTION:
        maps ()

PURPOSE/DESCRIPTION:
        Function maps reads FIRE-CI2 maps data, and optionally reads the 
        terrain and the latlon data files.  Functions maps(), maps_
        terrain(), and maps_latlon() together perform these functions.  
        Function maps prints out 6 variables at different level as the 
        data are read and the min. max. values for each variables at the end
        of processing.  Function maps_terrain prints out the min. max. values
        for the terrain data.  Function maps_latlon prints out the min. max. 
        values of all variables's latitude and longitude.  MAPS uses an 
        81 (x direction) x 62 (y direction) horizontal Cartesian mesh with 
        60 km grid spacing on an Arakawa-A grid which has all variables 
        defined at each grid node.  The information for each horizontal field 
        consists of a header line containing the name of the variable and the 
        vertical coordinate, followed by 62 groups of 81 field values.
        
        Each group of 81 field values represents one x direction row of grid 
        node values, beginning with the southernmost row in the domain, and 
        proceeding northward with succeeding groups.  The 81 values are 
        ordered from the west to the east edges of the grid domain, and are 
        listed in the file using 13 numbers per line, with the last line in 
        each group containing 3 values.  There are 10 characters per field 
        value, and each value is right-justified with 3 decimal digits 
        following an explicit decimal point, as in Fortran f10.3 format.  
        Hence, the very first field value will be the pressure on the sigma=1 
        surface at the southwest corner of the domain.  The very last field 
        value will be the V wind component on the virtual theta=410K surface 
        at the northeast corner of the domain.
        See README.fci2 file for the descriptions of 6 data variables.

INVOCATION:
        (void) maps (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name, multiple pams 
	   data files, and an optional argument "-s".  For example,  
	       maps ci2_maps_911124_03 ci2_maps_911118_00
	   will read two files: ci2_maps_911124_03, and ci2_maps_911118_00
	       maps -s ci2_maps_911124_03 ci2_maps_911118_00
	   will prompt the user to enter the file names of the terrain and 
	   latitude/longitude data.  After the user enters the file names, it 
	   will print out the min. max. of the terrain file and the min. max.
	   of the latlong file.  It then reads two files: ci2_maps_911124_03, 
	   and ci2_maps_911118_00.

FILE/RECORD REFERENCES:
        Each MAPS analysis file contains 65250 lines and 7608900 bytes in 
        ASCII format.  The file naming convention for the MAPS analysis 
        files is:  ci2_maps_yymmdd_hh, where yy is the year, mm the month, 
        dd the day, and hh the starting hour when the data were collected.

EXTERNAL ROUTINES:  None.

NOTES:
        Sorting each variable's field values can also get the min, max values 
        with the standard function qsort() and customized comparison function 
        floatcomp().  After sorting, the 1st and the last elements will be 
        the minimum and maximum value, respectively.  The drawbacks are the
        processing speed is much slower and the contents of the array that 
        stores the field values will be overwritten because qsort() writes 
        in the same array.  In this case, if the original order of field 
        values are desired, they should be placed in another array to avoid 
        being overwritten.  The following line of codes demonstrate this
        method:
        (void) qsort ((void *)&(var[j].fld[0][0][0]), total, 
                  sizeof (float), floatcomp);
                  
*****************************************************************************/

static int  floatcomp();

void  maps (argc, argv)
int  argc;
char  **argv;
{

    map_var  *var;     /* Array for the field values of all variables */
    char  filename[MAXPATHLEN+1], stars[80], equal, buf[200];
    char  fnames[400], flatlon[200], fterrain[200];
    static char  optflag[]={"-s"};
    int  i, j, x, y, z, total;
    FILE  *fptr;
    float  maximum, minimum;


    total = PTS_X * PTS_Y * PTS_Z;
    var = (map_var *) calloc (NUM_VAR, sizeof (map_var));

    i = 0;
        /** Process the terrain and latlon data file to get the min, max 
         ** values for the maps data set.
         **/
    strcpy (filename, argv[1]);
    if (strcmp (filename, optflag) == 0)    {
        i++;
        printf ("Enter MAPS terrain file name, space, followed by ");
        printf ("MAPS latitude/longitude file name, then hit a return.\n");
        gets (fnames);
        sscanf (fnames, "%s %s", flatlon, fterrain);
        maps_terrain (flatlon);
        maps_latlon (fterrain);
    }
    
        /***  Process MAPS 3-D fields for 6 variables   ***/
    while (i++ < (argc-1))    {
        strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr,"ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
/** MAPS data files is organized as follows:
 ** line 1: *********  varialbe 1 at sigma (or theta) = v_coord1 **********
 ** line 2 - 435: every 7 lines contain 81 values in X direction for variable 1
 ** line 436: ********  variable 2 at sigma (or theta) = v_coord1 **********
 ** line 437 - 870: every 7 lines contain 81 values in X direction for variable 2
 **    .....
 ** line 2616: *******  variable 1 at sigma (or theta) = v_coord2 **********
 ** line 2617 - 3051: every 7 lines contain 81 values in X direction for variable 1
 **    .....
 **/
        for (z = 0; z < PTS_Z; z++)    {
            for (j = 0; j < NUM_VAR; j++)    {
                fgets (buf, sizeof(buf), fptr);
                sscanf (buf, "%[ *]%8c%[^=]%c%g%s", stars, var[j].var_name, 
                        stars, &equal, &(var->vcoord), stars);
                printf ("Input %s at vertical %.3f\n", var[j].var_name, var->vcoord);
                for (y = 0; y < PTS_Y; y++)    { /* Grid points in Y dir. */
                    for (x = 0; x < PTS_X; x++)    { /* Grid points in X dir. */
                        fscanf (fptr, "%g", &(var[j].fld[x][y][z]));
                    }
                }
                fgets (buf, sizeof(buf), fptr);
            }
        }

        for (j = 0; j < NUM_VAR; j++)    {
	    minimum = MAXFLOAT;
	    maximum = MINFLOAT;
            for (x = 0; x < PTS_X; x++)    {
                for (y = 0; y < PTS_Y; y++)    {
	            for (z = 0; z < PTS_Z; z++)    {
			minimum = fmin (minimum, var[j].fld[x][y][z]);
			maximum = fmax (maximum, var[j].fld[x][y][z]);
                    }
                }
            }
            printf ("%s, minimum = %g, maximum = %g\n", var[j].var_name, minimum,
		   maximum);
        }
        fclose (fptr);
    }
    free (var);
    exit (0);
}
static int  floatcomp (a, b)
float  *a, *b;
{
    if ((*a - *b) < 0.0)
        return (-1);
    else if ((*a - *b) == 0.0)
        return (0);
    else if ((*a - *b) > 0.0)
        return (1);
}
/****************************************************************************
FUNCTION:
	maps_terrain ()

PURPOSE/DESCRIPTION:
	Function maps_terrain reads in terrain height 2-D field.  It computes 
	and report min, max of terrain height field.
	
INVOCATION:
	status = maps_terrain (filename);

   WHERE
	<filename> - I
	   the file name of the maps terrain data file.
	<status> - O
	   returns 0 when there is no error, otherwise, a -1 is returned.

FILE/RECORD REFERENCES:

EXTERNAL ROUTINES:  None.

NOTES: 
	
*****************************************************************************/

int  maps_terrain (filename)
char  *filename;
{

    FILE  *fptr;
    float  terr_ht[PTS_X][PTS_Y];
    int  x, y, total;


    total = PTS_X * PTS_Y;
    if ((fptr = fopen (filename, "r")) == NULL)    {
        fprintf (stderr,"ERROR: Can't open terrain file:\t %s\n", filename);
        return (-1); 
    }
    for (y = 0; y < PTS_Y; y++)    {
        for (x = 0; x < PTS_X; x++)    {
            fscanf (fptr, "%g", &(terr_ht[x][y]));
        }
    }
      /**  Compute and report min, max of terrain height field **/
    (void) qsort ((void *)&(terr_ht[0][0]), total, sizeof (float), floatcomp);
    printf ("Terrain height min = %g, max = %g\n", terr_ht[0][0], 
             terr_ht[PTS_X-1][PTS_Y-1]);
    fclose (fptr);
    return (0);
}

/****************************************************************************
FUNCTION:
	maps_latlon ()

PURPOSE/DESCRIPTION:
	Function maps_latlon reads in latitude and longitude 2-D fields.  The
	input file is organized as the first 434 lines are the latitude data, 
	next 434 lines are the longitude data.  It computes and report min, 
	max of latitude and longitude field.
	
INVOCATION:
	status = maps_latlon (filename);

   WHERE
	<filename> - I
	   the file name of the maps latitude and longitude data file.
	<status> - O
	   returns 0 when there is no error, otherwise, a -1 is returned.

FILE/RECORD REFERENCES:

EXTERNAL ROUTINES:  None.

NOTES: 
	
*****************************************************************************/

int  maps_latlon (filename)
char  *filename;
{

    FILE  *fptr;
    float  lat[PTS_X][PTS_Y], lon[PTS_X][PTS_Y];
    int  x, y, total;


    total = PTS_X * PTS_Y;
    if ((fptr = fopen (filename, "r")) == NULL)    {
        fprintf (stderr,"ERROR: Can't open latlon file:\t %s\n", filename);
        return (-1); 
    }

    for (y = 0; y < PTS_Y; y++)    {
        for (x = 0; x < PTS_X; x++)
            fscanf (fptr, "%g", &(lat[x][y]));
    }
    for (y = 0; y < PTS_Y; y++)    {
        for (x = 0; x < PTS_X; x++)
            fscanf (fptr, "%g", &(lon[x][y]));
    }
      /**  Compute and report min, max of latitude and longitude fields  **/
    (void) qsort ((void *)&(lat[0][0]), total, sizeof (float), floatcomp);
    (void) qsort ((void *)&(lon[0][0]), total, sizeof (float), floatcomp);
    printf ("Latitude min  = %g, max = %g\n", lat[0][0], lat[PTS_X-1][PTS_Y-1]);
    printf ("Longitude min = %g, max = %g\n", lon[0][0], lon[PTS_X-1][PTS_Y-1]);
    fclose (fptr);
    return (0);
}

/****************************************************************************
FUNCTION:
	nws_sonde ()

PURPOSE/DESCRIPTION:
	NWS_SONDE reads in FIRE-II NWS_IN and NWS_OUT sondes data.  This 
	function reads the data, one level at a time, then prints out to the 
	standard output device.  Both nws_in_sonde, and nws_out_sonde data 
	sets have the same file and record organizations, and contains the 
	same variables.  Thus, they share this read routine.

INVOCATION:
	(void) nws_sonde (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple Par 
	   station data file names.  For example,  
	        nws_sonde ELP.1687 OUN.1655
	   will read two files: ELP.1687, and OUN.1655.

FILE/RECORD REFERENCES:
	Data files are named SSS.aaaa where SSS is the station name, and 
	aaaa is the ascent number.

EXTERNAL ROUTINES: str_trim(), hd_sondes();

NOTES:
1.)	The input and output files are organized as follows: 9 lines of header 
 	information, followed by a blank line, followed by a line of field 
 	headings, followed by a line of field units.  The nws sonde data starts 
 	with the 13th line in the file.  See README.fci2 file for the detailed 
 	descriptions of variables.
	The header variables are listed in order as follows:
        project name, principle investigator, WMO station indentifier, station 
        call letters, station name and state, ascent number, nominal time of 
        ascent, nominal date of ascent, launch time, launch date, radiosonde 
        manufacture, radiosonde type, balloon size, weather at time of launch,
        number of levels in sonde, quality control flag.
        
        A nws_in_sonde, or nws_out_sonde record starts with the number of level, 
        followed by 21 variables, and ends with the same number of level.  
        Except for two "number of level" variables, the rest of the 21 variables 
        are grouped in a data structure.  All of the data variables have data 
        type 'float'.  The purpose of defining them in a data structure is to 
        make sure data will be stord in the consecutive memory.
        
2.)	The output format for the data is defined as follows: 
	"%3d%7.2f%8.3f%6.1f%7.2f%7.2f%6.1f%6.1f%9.4f%7.2f%7.2f%6.1f%6.1f%6.1f
	%6.1f%8.0f%7.2f%7.2f%8.3f%8.3f%9.4f%9.4f%3d\n"  

*****************************************************************************/
/* There are 21 data variables, which are defined in the nws_data data structure
 * in the fci2_sw.h file */

void  nws_sonde (argc, argv)
int  argc;
char **argv;
{

    FILE  *fptr;
    char  filename[200], buf[180], unuse[25], colon;
    char  *ext, *base, *lines[10], *head[2];
    char  project[20], author[80], station[30], wmo_id[10], stn_id[10];
    char  asc_date[9], asc_time[10], nom_time[10], nom_date[9];
    char  sonde_maker[6], sonde_type[6], ssize[6], qa_label[10];
    int  i=0, j, k, l, m, nrec;
    int  asc_num, weather, nlevel;
    nws_data  dat;
    
    
    while (i++ < (argc-1))    {
        l = 0;
        strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr, "ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
        ext = strrchr (filename, '.');
        if (ext == NULL)
            printf ("ERROR: File name (%s) missing ascent number.\n");
            
        base = strrchr (filename, '/');
        base = (base == NULL) ? filename : (++base);
        

	/* Read in header information. */
	/* Read in project title and principle investigator. */
	for (k = 0; k < 10; k++)    {
            fgets (buf, sizeof(buf), fptr);
            str_trim (buf, 0);    lines[l++] = strdup (buf);
        }
        strcpy (project, &lines[0][10]);
        strcpy (author, &lines[1][10]);
        
	/* Read in WMO identification number and station call letters. */

        sscanf (lines[2], "%*10c %s%s%[ ]%n", wmo_id, stn_id, unuse, &j);
        strcpy (station, &lines[2][j]);
        
        if (strncmp (stn_id, base, strlen(base)-strlen(ext)-1) != 0)
            printf ("ERROR: File (%s), station call letters (%s) unmatch\n",
                 filename, stn_id);
        
        /* Read in ascent number, as well as nominal time and date. */
        sscanf (lines[3], "%*10c %d %s %s", &asc_num, nom_time, nom_date);
        
        /* Read in ascent number, as well as ascent time and date. */
        sscanf (lines[4], "%*10c %d %s %s", &asc_num, asc_time, asc_date);
        
        /* Read in radiosonde manufacture, radiosonde type, and balloon size */
        sscanf (lines[5], "%*10c %s %s %s", sonde_maker, sonde_type, ssize);
        
        /* Read in observed weather conditions */
        sscanf (lines[6], "%*10c%d", &weather);
        
        /* Read in number of levels */
        sscanf (lines[7], "%[^:]%c%d", unuse, &colon, &nlevel);
        
        /* Read in quality control label */
        sscanf (lines[8], "%[^:]%c%s", unuse, &colon, qa_label);
        
        for (j = 0, m = 0; j < 2; j++)    {
            fgets (buf, sizeof (buf), fptr);
            str_trim (buf, 0);    head[m++] = strdup (buf);
        }

        nrec = 0;

	/* Read in data record. */
        while (fgets (buf, sizeof (buf), fptr) != NULL)    {
            str_trim (buf, 0);
            sscanf (buf, "%d%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%d", &k,
		&dat.min, &dat.height, &dat.pressure, &dat.c_temp, &dat.k_temp,
		&dat.rh_water, &dat.rh_ice, &dat.humidity, &dat.dewpoint,
		&dat.frost_pt, &dat.wnd_speed, &dat.wnd_dir, &dat.zonal, 
		&dat.meridional, &dat.asc_rate, &dat.lapse_rate, &dat.tmp_lapse,
		&dat.lon_dist, &dat.lat_dist, &dat.lon_pos, &dat.lat_pos, &k);

/**  Commented out the following two lines if the column headings are not 
 **  desired in the output page. 
 **/        
            if ((nrec++) % 40 == 0)
               (void) hd_sondes (filename, l, lines, m, head);

/***            printf ("%s\n", buf);  ***/
            printf (NWS_FMT, k, dat.min, dat.height, dat.pressure, dat.c_temp, 
                dat.k_temp, dat.rh_water, dat.rh_ice, dat.humidity, dat.dewpoint,  
                dat.frost_pt, dat.wnd_speed,dat.wnd_dir, dat.zonal, 
                dat.meridional, dat.asc_rate, dat.lapse_rate, dat.tmp_lapse, 
                dat.lon_dist, dat.lat_dist, dat.lon_pos, dat.lat_pos, k); 
  
        } 
        if (nrec != nlevel) 
            fprintf (stderr,"WARNING: Rec. num = %d, in the file %s", nrec, filename);
        printf ("** Total records read in file %s = %d **\n", filename, nrec);
        /*  Clear the buffer  */
        for (j = 0; j < l; j++)
            free (lines[j]); 
        for (j = 0; j < m; j++)
            free (head[j]);
        fclose (fptr);
    }
}


/****************************************************************************
FUNCTION:
	pams ()

PURPOSE/DESCRIPTION:
	PAMS reads in pams data taken during the FIRE-II Experiment.  
	FIRE-II was approximately 25 days long, hence 25 data sets for each 
	of 6 sites where pams data were collected.  The data are in ASCII.
	This function can process multiple input files.  For each input file, 
	reading in the header line, followed by the records.  For each record,
	reading in the observation # (record #), followed by 12 parameters, 
	and quality flag (QA) for each parameter.

INVOCATION:
	(void) pams (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple pams 
	   data files.  For example, if the executable is pams, then, 
	        pams st6nov18.data st1nov17.data st4dec07.data
	   will read three files: st6nov18.data, st1nov17.data, st4dec07.data.
 
FILE/RECORD REFERENCES:
	Data files are named stNMMMDD.data, where N is the station number, 
	MMM is the month (3-letter code, either nov or dec), and DD is the 
	day.  Each file starts with a header line followed by 1440 data 
	records.  Missing value code is -99.00 for all parameters.

EXTERNAL ROUTINES: None.

NOTES:
1.)	The Fortran format for the header line is: (a8,i2,2x,3(i2),3(f10.4)), 
        See README.fci2 for the variables in header line and the in data 
        records.  The meanings of the quality flags for the 12 parameters are 
        explained in the footnote of the README.fci2 file.

2.)	The output file has the following format: 
        line1: file name
        line2: header, including station number, latitude, logitude, and the 
               elevation data
        line3: blank 
        line4: fields heading
        line5: units for the fields
        line6: blank
        line7 through line 44: data.  The same fields as in the input file.

*****************************************************************************/

void  pams (argc, argv)
int  argc;
char **argv;
{

    pams_param  dat[12];
    FILE  *fptr;
    void  hd_pams();
    char  stat_key[20], filename[200];
    int  i=0, j, observ_num, station_num, nrec;
    float  lat, lon, elevation;
    
    
    while (i++ < (argc-1))    {
	strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr, "ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
        nrec = 0;
        fscanf (fptr,"%s %d %*7c %f %f %f", stat_key,&station_num,&lat,&lon,&elevation);
        
        if (strcmp(stat_key, STATION_KEY) != 0)    continue;
        while (fscanf (fptr, "%d%f%f%f%f%f%f%f%f%f%f%f%f%hd%hd%hd%hd%hd%hd%hd%hd%hd%hd%hd%hd",
           &observ_num, &(dat[0].param),&(dat[1].param),&(dat[2].param),&(dat[3].param),
           &(dat[4].param),&(dat[5].param),&(dat[6].param),&(dat[7].param),
           &(dat[8].param),&(dat[9].param),&(dat[10].param),&(dat[11].param),
           &(dat[0].flag),&(dat[1].flag),&(dat[2].flag), &(dat[3].flag),
           &(dat[4].flag),&(dat[5].flag),&(dat[6].flag),&(dat[7].flag),
           &(dat[8].flag),&(dat[9].flag),&(dat[10].flag),&(dat[11].flag)) != EOF)    {
           
/**  Commented out the following two lines if the column headings are not 
 **  desired in the output page. 
 **/ 
            if (nrec % 45 == 0)
                (void) hd_pams (filename,stat_key,station_num,lat,lon,elevation);
            
            printf ("%4d  ", ++nrec);
            for (j = 0; j < 12; j++)    {
                switch (dat[j].flag)    {
                case 0:
                    dat[j].id = 'G';
                    break;
                case 8:		/* suspected spurious data that wasn't flagged*/
                    dat[j].id = 'B';
                    break;
                case 7:		/* equivalent to NCAR's outlier data (=2) */
                    dat[j].id = '?';
                    break;
                case 9:		/* NCAR flag as missing or bad data */
                    dat[j].id = 'B';
                    break;
                case 2:		/* NCAR flag as outlier (possible bad) data */
                    dat[j].id = '?';
                    break;
                default:
                    printf ("ERROR: Rec. Num: %d, Flag = %hd\n", nrec, dat[j].flag);
                    break; 
                }             
            }

            for (j = 0; j < 12; j++)     /* Print the 12 variables values */
                printf ("%7.2f ", dat[j].param);
            printf ("   ");
            for (j = 0; j < 12; j++)
                printf ("%d ", dat[j].flag); 
            /* An alternative way of printing each parameter, immediately 
             * followed by a character indicating the dat quality can be 
             * done as follows:
                   for (j = 0; j < 12; j++)
                       printf ("%.2f (%c) ", dat[j].param, dat[j].id);
             */
            printf ("\n"); 
        }
        printf ("Total records read in file %s = %d\n", filename, nrec); 
        fclose (fptr);
    }
}

void  hd_pams (filename, stat_key, stat_num, lat, lon, elevation)
char  *filename, *stat_key;
int  stat_num;
float  lat, lon, elevation;
{

    int  i;
    static char  *fields[2][13] = { {"Rec #", "Press.","temp", 
           "wbtemp", "rh", "ratio", "temp","u_wnd", "v_wnd",
           "avg_sp", "wnd_dir","max_sp","sol_irr"},
          {" ", " (mb) ","(C) ","(C) ","(%) ","(g/kg)","(K) ","(m/s) ",
           " (m/s)","(m/s)","(deg)", "(m/s)", "(W/m**2)"}  } ;


    printf ("\fFilename: %s\n", filename);
    printf ("Missing data value: %.2f\n", MISSING_DATA);

    printf ("%s %d, latitude=%.4f, longitude=%.4f, elevation=%.4f\n\n",  
               stat_key, stat_num, lat, lon, elevation);
               
    printf ("%5s", fields[0][0]);
    for (i = 1; i < 13; i++) 
        printf ("%8s", fields[0][i]);
    printf ("\n%5s", fields[1][0]);
    for (i = 1; i < 13; i++) 
        printf ("%8s", fields[1][i]);
    printf ("\n\n");
    
}
   

/****************************************************************************
FUNCTION:
        raman_lidar ()

PURPOSE/DESCRIPTION:
	Function raman_lidar reads the GSFC raman_lidar water vapor mixing 
	ratio (wvmr) data with altitudes and times.  Data is summed for one 
	minute in the detectors and saved to a file.  For the 10 minute averaged 
	data, the data is summed for 10 minutes before the calculations are 
	performed.  Each profile has 75 meter resolution from 0.4135 to 
	10.299 kilometers.  Zero (0) km means sea level.  The site altitude 
	is 0.229 km and the first data point is at 0.1845 km above ground 
	level.  See READEM.fci2 file for the variables and record organization.

INVOCATION:
        (void) raman_lidar (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple pams 
	   data files.  For example,
	       raman_lidar ci2_wv911125_1m ci2_wv911126_10m
	   will read two files: ci2_wv911125_1m, and ci2_wv911126_10m.

FILE/RECORD REFERENCES:
        Each is named ci2_wvYYMMDD_Xm, where YY is the year, MM the month, and 
        DD the day.  X in the file name can only be either 1 or 10, indicating 
        the 1 minute summed data or 10 minutes averaged data.  

EXTERNAL ROUTINES: None.

NOTES:
    If no output is desirable, comment out the "printf" lines in the function.

*****************************************************************************/

void  raman_lidar (argc, argv)
int argc;
char **argv;
{

    char  filename[MAXPATHLEN+1], buf[250], comma;
    char  beg_time[15], end_time[15], text[90];
    int  iwvmr, i=0, j, k, nprofile, itime, nalt, ialt; 
    FILE  *fptr;
    float  rwvmr, rerr;
    
    
    while (i++ < (argc-1))    {
        strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr, "ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
        fgets (buf, sizeof (buf), fptr);
        sscanf (buf, "%[^,]%c%s", beg_time, &comma, end_time);
        fgets (text, sizeof (text) - 1, fptr);
        fgets (buf, sizeof (buf), fptr);
        fgets (buf, sizeof (buf), fptr);
        sscanf (buf, "%d", &nprofile);
        printf ("%s,%s\n%s\n\n%d = # profiles\n", beg_time, end_time, text, nprofile);
        for (k = 0; k < nprofile; k++)    {
            fgets (buf, sizeof (buf), fptr);
            sscanf (buf, "%d", &itime);         /* Time of profile. */
            fgets (buf, sizeof (buf), fptr);
            sscanf (buf, "%d", &nalt);
            printf ("%d = time (secs)\n%d = # alts (m)\n", itime, nalt);
            for (j = 0; j < nalt; j++)   {
                if (fgets (buf, sizeof (buf), fptr) == NULL)
                    break; 
                sscanf (buf, "%d %g %g", &ialt, &rwvmr, &rerr);
                printf ("%d %g %g\n", ialt, rwvmr, rerr);
            }
            if (j != nalt)
                fprintf (stderr,"ERROR: Total heights specified = %d, but %d are read\n",
                    nalt, j);
        }
        if (k != nprofile)
            fprintf (stderr, "ERROR? Total profiles read = %d\n", k);

        fclose (fptr);
    }
}


/****************************************************************************
FUNCTION:
        noaa_wndprfl ()

PURPOSE/DESCRIPTION:
        Function noaa_wndprfl reads NOAA windprofiles data collected during the 
        period from Nov. 13, 1991 to Dec. 7, 1991.  The original NOAA 
        windprofiles data were stored in the Enhanced Binary Universal Form 
        (EBUF) format.  These data files were processed and provided in ASCII 
        format by the Langley DAAC.  The same data in EBUF format are available 
        off-line.  NOTE:  It is assumed that the height increment on the 
        observation station remains the same in a windprofiles record.  These
        ASCII files range from 17 to 37 MB size.  Expect to take a while to read.

INVOCATION:
        (void) noaa_wndprfl (argc, argv);

   WHERE
	<argc> - I
	   the number of arguments from the command line invocation.
	<argv> - I
	   the argument list, including the program name and multiple pams 
	   data files.  For example,  
	       noaa_wndprfl ci2_noawnd_911127_6m ci2_noawnd_911118_6m
	   will read two files: ci2_noawnd_911127_6m, and ci2_noawnd_911118_6m

FILE/RECORD REFERENCES:
        Each file is named ci2_noawnd_yymmdd_6m, where yy is the year, mm the 
        month, and dd the day.  A NOAA windprofiles record starts with three 
        header lines, followed by three lines of column headings, followed by 
        windprofile data, and ends with the parameter "Profiler in checkout 
        mode flag" line. 

EXTERNAL ROUTINES:  None.

NOTES:
    If no output is desirable, comment out the "printf" lines in the function.

*****************************************************************************/

void  noaa_wndprfl (argc, argv)
int argc;
char **argv;
{

    char  filename[MAXPATHLEN+1], buf[250], keys[80], letter, *lines[10];
    FILE  *fptr;
    int  i=0, j, k, recnum, year, month, day, hour, minute;
    float  lat, lon, stat_ht, increment, height, ck_flg;
    float  nsig_power, esig_power, vsig_power, nmean_vel;
    float  emean_vel, vmean_vel, nvel_sigma2, evel_sigma2, vvel_sigma2;


    /** Open the data file **/

    while (i++ < (argc-1))    {
        strcpy (filename, argv[i]);
        if ((fptr = fopen (filename, "r")) == NULL)    {
            fprintf (stderr,"ERROR: Can't open file:\t %s\n", filename);
            continue;
        }
          /** HEADER lines: 1st line, date and time fields; 2nd line, statioin 
           ** latitude and longitude fields; 3rd line, Height of station above 
           ** sea level, and height increment fields.  Next 3 lines are column
           ** headings.  
           **/
        for (j = 0; fgets (buf, sizeof (buf), fptr) != NULL; j = 0)    {
            lines[j++] = strdup (buf);
	    for (k = 0; (k < 5) && (fgets (buf, sizeof(buf), fptr) != NULL);
	         k++)    {
                lines[j++] = strdup (buf);
            }
            sscanf (lines[0], "%s%d%c%2d%c%2d%s%d", keys, &year, &letter, 
                &month, &letter, &day, keys, &hour, &letter, &minute);
            sscanf (lines[1], "%[^:]%c%g%[^:]%c%g", keys, &letter, &lat, keys, 
                &letter, &lon); 
            sscanf (lines[2], "%[^:]%c%g%[^:]%c%g", keys, &letter, &stat_ht, 
                keys, &letter, &increment); 
                
            if ((lat < -90.0) || (lat > 90.0))
                fprintf (stderr, "ERROR: latutude in %4d/%02d/%02d = %g\n", 
                        year, month, day, lat);
            if ((lon < -180.0) || (lon > 180.0))
                fprintf (stderr, "ERROR: longitude in %4d/%02d/%02d = %g\n", 
                        year, month, day, lon);

            for (k = 0; k < j; k++)
                printf ("%s", lines[k]);
            for (recnum = 0; (recnum < MAX_NOAA) &&
                   (fgets (buf, sizeof (buf), fptr) != NULL); recnum++)   {
                sscanf (buf, "%g %g%g%g %g%g%g %g%g%g", &height, &nsig_power, 
                  &esig_power, &vsig_power, &nmean_vel, &emean_vel, &vmean_vel, 
                  &nvel_sigma2, &evel_sigma2, &vvel_sigma2);
                printf ("%-8g %-8g %-8g %-8g %-8g %-8g %-8g %-8g %-8g %-8g \n", 
                  height, nsig_power, esig_power, vsig_power, nmean_vel, 
                  emean_vel, vmean_vel, nvel_sigma2, evel_sigma2, vvel_sigma2);
            }
              /* Every record ends with "Profiler in checkout mode flag". */
            if (recnum == MAX_NOAA)    {
                if (fgets (buf, sizeof (buf), fptr) != NULL)   {
                    sscanf (buf, "%[^:]%c%g", keys, &letter, &ck_flg);
                    printf ("%-s%c %-8g\n\n", keys, letter, ck_flg);
                }
                if (fgets (buf, sizeof (buf), fptr) == NULL)   
                    break;
            }
	    for (k = 0; k < j; k++) 
                free (lines[j]); 
        }
        fclose (fptr);
    }
}


