/******************************************************************************
*
*  NSSDC/CDF           Create an example CDF (without using a skeleton table).
*
*  Version 1.2, 5-Jan-94, Hughes STX
*
*  Modification history:
*
*   V1.0  13-Nov-91, J Love    Original version (for CDF V2.1 Primer chapter).
*   V1.1  10-Feb-92, J Love    Typo city.
*   V1.2   5-Jan-94, J Love    CDF V2.4 (long constants for IBM PC).
*
******************************************************************************/

/******************************************************************************
*
* Note(s):
*
*   This program would have to be modified to run on a DEC Alpha because the
* C language `long' data type is 8 bytes rather than 4 (the CDF data type of
* CDF_INT4 is always 4 bytes).
*
******************************************************************************/

/******************************************************************************
* Necessary include files.
******************************************************************************/

#include <stdio.h>
#include <stdlib.h>

#include "cdf.h"

/******************************************************************************
* Function prototypes.
******************************************************************************/

void StatusHandler ();

/******************************************************************************
* MAIN.
******************************************************************************/

main () {
CDFid id;            /* CDF identifier. */
CDFstatus status;    /* CDF completion status. */

FILE *fp;            /* File pointer - used to read input data file. */

long numDims = 2;                  /* Number of dimensions, rVariables. */
static long dimSizes[2] = {2,2};   /* Dimension sizes, rVariables. */

long dimVarys[2];    /* Dimension variances. */
long indices[2];     /* Dimension indices. */
long recNum;         /* Record number. */
long attrNum;        /* Attribute number. */

long TimeVarNum;     /* 'Time' rVariable number. */
long LonVarNum;      /* 'Longitude' rVariable number. */
long LatVarNum;      /* 'Latitude' rVariable number. */
long TmpVarNum;      /* 'Temperature' rVariable number. */

long Time;           /* 'Time' rVariable value. */
float Lat;           /* 'Latitude' rVariable value. */
float Lon;           /* 'Longitude' rVariable value. */
float Tmp;           /* 'Temperature' rVariable value. */

long TimeValidMin = 0;          /* 'Time' valid minimum (0000). */
long TimeValidMax = 2359;       /* 'Time' valid maximum (2359). */
long TimeScaleMin = 100;        /* 'Time' scale minimum (0100). */
long TimeScaleMax = 200;        /* 'Time' scale maximum (0200). */
long TimeFillValue = 9999;      /* 'Time' fill value. */

float LonValidMin = -180.0;     /* 'Longitude' valid minimum. */
float LonValidMax = 180.0;      /* 'Longitude' valid maximum. */
float LonScaleMin = -165.0;     /* 'Longitude' scale minimum. */
float LonScaleMax = -150.0;     /* 'Longitude' scale maximum. */
float LonFillValue = -999.9;    /* 'Longitude' fill value. */

float LatValidMin = -90.0;      /* 'Latitude' valid minimum. */
float LatValidMax = 90.0;       /* 'Latitude' valid maximum. */
float LatScaleMin = 30.0;       /* 'Latitude' scale minimum. */
float LatScaleMax = 40.0;       /* 'Latitude' scale maximum. */
float LatFillValue = -999.9;    /* 'Latitude' fill value. */

float TmpValidMin = -40.0;      /* 'Temperature' valid minimum. */
float TmpValidMax = 50.0;       /* 'Temperature' valid maximum. */
float TmpScaleMin = 17.0;       /* 'Temperature' scale minimum. */
float TmpScaleMax = 24.0;       /* 'Temperature' scale maximum. */
float TmpFillValue = -999.9;    /* 'Temperature' fill value. */

/******************************************************************************
* Create the CDF.
******************************************************************************/

status = CDFcreate ("example1", numDims, dimSizes, NETWORK_ENCODING, ROW_MAJOR,
                    &id);
if (status != CDF_OK) StatusHandler (status);

/******************************************************************************
* Create rVariables.
******************************************************************************/

dimVarys[0] = NOVARY;
dimVarys[1] = NOVARY;
status = CDFvarCreate (id, "Time", CDF_INT4, 1L, VARY, dimVarys,
                       &TimeVarNum);
if (status != CDF_OK) StatusHandler (status);

dimVarys[0] = VARY;
dimVarys[1] = NOVARY;
status = CDFvarCreate (id, "Longitude", CDF_REAL4, 1L, NOVARY, dimVarys,
                       &LonVarNum);
if (status != CDF_OK) StatusHandler (status);

dimVarys[0] = NOVARY;
dimVarys[1] = VARY;
status = CDFvarCreate (id, "Latitude", CDF_REAL4, 1L, NOVARY, dimVarys,
                       &LatVarNum);
if (status != CDF_OK) StatusHandler (status);

dimVarys[0] = VARY;
dimVarys[1] = VARY;
status = CDFvarCreate (id, "Temperature", CDF_REAL4, 1L, VARY, dimVarys,
                       &TmpVarNum);
if (status != CDF_OK) StatusHandler (status);

/******************************************************************************
* Create attributes.
******************************************************************************/

status = CDFattrCreate (id, "TITLE", GLOBAL_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "FIELDNAM", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "VALIDMIN", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "VALIDMAX", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "SCALEMIN", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "SCALEMAX", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "UNITS", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "FORMAT", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "MONOTON", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrCreate (id, "FILLVAL", VARIABLE_SCOPE, &attrNum);
if (status != CDF_OK) StatusHandler (status);

/******************************************************************************
* Write TITLE gAttribute gEntry.
******************************************************************************/

status = CDFattrPut (id, CDFattrNum(id,"TITLE"), 0L, CDF_CHAR, 50L,
                     "An example CDF (1).                               ");
if (status != CDF_OK) StatusHandler (status);

/******************************************************************************
* Write vAttribute rEntries for 'Time' rVariable.
******************************************************************************/

status = CDFattrPut (id, CDFattrNum(id,"FIELDNAM"),
                     CDFvarNum(id,"Time"), CDF_CHAR, 20L,
                     "Time of observation ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"VALIDMIN"),
                     CDFvarNum(id,"Time"), CDF_INT4, 1L, &TimeValidMin);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"VALIDMAX"),
                     CDFvarNum(id,"Time"), CDF_INT4, 1L, &TimeValidMax);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"SCALEMIN"),
                     CDFvarNum(id,"Time"), CDF_INT4, 1L, &TimeScaleMin);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"SCALEMAX"),
                     CDFvarNum(id,"Time"), CDF_INT4, 1L, &TimeScaleMax);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"UNITS"),
                     CDFvarNum(id,"Time"), CDF_CHAR, 20L,
                     "Hour/Minute         ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"FORMAT"),
                     CDFvarNum(id,"Time"), CDF_CHAR, 8L, "I4      ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"MONOTON"),
                     CDFvarNum(id,"Time"), CDF_CHAR, 8L, "INCREASE");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"FILLVAL"),
                     CDFvarNum(id,"Time"), CDF_INT4, 1L, &TimeFillValue);
if (status != CDF_OK) StatusHandler (status);

/******************************************************************************
* Write vAttribute rEntries for 'Longitude' rVariable.
******************************************************************************/

status = CDFattrPut (id, CDFattrNum(id,"FIELDNAM"),
                     CDFvarNum(id,"Longitude"), CDF_CHAR, 20L,
                     "Longitude           ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"VALIDMIN"),
                     CDFvarNum(id,"Longitude"), CDF_REAL4, 1L,
		     &LonValidMin);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"VALIDMAX"),
                     CDFvarNum(id,"Longitude"), CDF_REAL4, 1L,
		     &LonValidMax);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"SCALEMIN"),
                     CDFvarNum(id,"Longitude"), CDF_REAL4, 1L,
		     &LonScaleMin);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"SCALEMAX"),
                     CDFvarNum(id,"Longitude"), CDF_REAL4, 1L,
		     &LonScaleMax);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"UNITS"),
                     CDFvarNum(id,"Longitude"), CDF_CHAR, 20L,
                     "Degrees east        ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"FORMAT"),
                     CDFvarNum(id,"Longitude"), CDF_CHAR, 8L,
		     "F6.1    ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"MONOTON"),
                     CDFvarNum(id,"Longitude"), CDF_CHAR, 8L,
		     "INCREASE");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"FILLVAL"),
                     CDFvarNum(id,"Longitude"), CDF_REAL4, 1L,
		     &LonFillValue);
if (status != CDF_OK) StatusHandler (status);

/******************************************************************************
* Write vAttribute rEntries for 'Latitude' rVariable.
******************************************************************************/

status = CDFattrPut (id, CDFattrNum(id,"FIELDNAM"),
                     CDFvarNum(id,"Latitude"), CDF_CHAR, 20L,
                     "Latitude            ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"VALIDMIN"),
                     CDFvarNum(id,"Latitude"), CDF_REAL4, 1L,
		     &LatValidMin);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"VALIDMAX"),
                     CDFvarNum(id,"Latitude"), CDF_REAL4, 1L,
		     &LatValidMax);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"SCALEMIN"),
                     CDFvarNum(id,"Latitude"), CDF_REAL4, 1L,
		     &LatScaleMin);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"SCALEMAX"),
                     CDFvarNum(id,"Latitude"), CDF_REAL4, 1L,
		     &LatScaleMax);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"UNITS"),
                     CDFvarNum(id,"Latitude"), CDF_CHAR, 20L,
                     "Degrees north       ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"FORMAT"),
                     CDFvarNum(id,"Latitude"), CDF_CHAR, 8L, "F6.1    ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"MONOTON"),
                     CDFvarNum(id,"Latitude"), CDF_CHAR, 8L, "DECREASE");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"FILLVAL"),
                     CDFvarNum(id,"Latitude"), CDF_REAL4, 1L,
		     &LatFillValue);
if (status != CDF_OK) StatusHandler (status);

/******************************************************************************
* Write vAttribute rEntries for 'Temperature' rVariable.
******************************************************************************/

status = CDFattrPut (id, CDFattrNum(id,"FIELDNAM"),
                     CDFvarNum(id,"Temperature"), CDF_CHAR, 20L,
                     "Temperature value   ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"VALIDMIN"),
                     CDFvarNum(id,"Temperature"), CDF_REAL4, 1L,
		     &TmpValidMin);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"VALIDMAX"),
                     CDFvarNum(id,"Temperature"), CDF_REAL4, 1L,
		     &TmpValidMax);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"SCALEMIN"),
                     CDFvarNum(id,"Temperature"), CDF_REAL4, 1L,
		     &TmpScaleMin);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"SCALEMAX"),
                     CDFvarNum(id,"Temperature"), CDF_REAL4, 1L,
		     &TmpScaleMax);
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"UNITS"),
                     CDFvarNum(id,"Temperature"), CDF_CHAR, 20L,
                     "Degrees celsius     ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"FORMAT"),
                     CDFvarNum(id,"Temperature"), CDF_CHAR, 8L,
		     "F4.1    ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"MONOTON"),
                     CDFvarNum(id,"Temperature"), CDF_CHAR, 8L,
		     "FALSE   ");
if (status != CDF_OK) StatusHandler (status);

status = CDFattrPut (id, CDFattrNum(id,"FILLVAL"),
                     CDFvarNum(id,"Temperature"), CDF_REAL4, 1L,
		     &TmpFillValue);
if (status != CDF_OK) StatusHandler (status);

/******************************************************************************
* Read input values for rVariables and write them to the CDF.  Not
* every value must be written to the CDF - many of the values are redundant.
* The 'Time' value only has to be written once per CDF record (every 4 input
* records).  The 'Longitude' and 'Latitude' values are only written to the
* first CDF record (and only at the appropriate indices).  Each 'Temperature'
* value read is written to the CDF.
******************************************************************************/

fp = fopen ("example.dat", "r");
if (fp == NULL) {
  printf ("Error opening input file.\n");
  exit (-1);
}

for (recNum = 0; recNum < 24; recNum++) {
   for (indices[0] = 0; indices[0] < 2; indices[0]++) {
      for (indices[1] = 0; indices[1] < 2; indices[1]++) {
         fscanf (fp, "%d %f %f %f", &Time, &Lon, &Lat, &Tmp);

         if (indices[0] == 0 && indices[1] == 0) {
           status = CDFvarPut (id, TimeVarNum, recNum, indices, &Time);
           if (status != CDF_OK) StatusHandler (status);
         }

         if (recNum == 0 && indices[1] == 0) {
           status = CDFvarPut (id, LonVarNum, recNum, indices, &Lon);
           if (status != CDF_OK) StatusHandler (status);
         }

         if (recNum == 0 && indices[0] == 0) {
           status = CDFvarPut (id, LatVarNum, recNum, indices, &Lat);
           if (status != CDF_OK) StatusHandler (status);
         }

         status = CDFvarPut (id, TmpVarNum, recNum, indices, &Tmp);
         if (status != CDF_OK) StatusHandler (status);
      }
   }
}

fclose (fp);

/******************************************************************************
* Close CDF.
******************************************************************************/

status = CDFclose (id);
if (status != CDF_OK) StatusHandler (status);

return;
}

/******************************************************************************
* Status handler.
******************************************************************************/

void StatusHandler (status)
CDFstatus status;
{
char message[CDF_ERRTEXT_LEN+1];

if (status < CDF_WARN) {
  printf ("An error has occurred, halting...\n");
  CDFerror (status, message);
  printf ("%s\n", message);
  exit (status);
}
else
  if (status < CDF_OK) {
    printf ("Warning, function may not have completed as expected...\n");
    CDFerror (status, message);
    printf ("%s\n", message);
  }
  else
    if (status > CDF_OK) {
      printf ("Function completed successfully, but be advised that...\n");
      CDFerror (status, message);
      printf ("%s\n", message);
    }       
return;
}
