themis_fgm2nc.c 12.8 KB
 /************************************************************/
 /*               THEMIS FGM CDF -> DD netCDF               */
/*                            NaN -> -1.e31                  */
 /*                           12.10.2007                    */
 /*                             V 1.0                       */
 /***********************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <netcdf.h>
#include <cdf.h>
#include <DD.h>
#include <string.h>
#include <time.h>
#include <math.h>

#define TimeGap  1800000.0
#define Source "themis@cdpp2"
#define MAX_FILE_NAME_LEN  250                   // Max. file name length
#define MAX_VARS           250                   // Max # of VARS in CDF


/*************************************
   Global variables and structures
**************************************/
long   CDFDims,                                         // Number of dimensions in a CDF file
       CDFVars,                                            // Number of variables in a CDF file
       CDFDimSizes[CDF_MAX_DIMS],      // Dimension Sizes in a CDF file
       CDFencoding,                                    // Data encoding
       CDFmajority,                                      // Variable majority
       CDFmaxRec,                                     // max Record number
       CDFAttrs;                                          // number of CDF Attributes


struct cdfvar {                               // CDF variable structure
     char name[CDF_VAR_NAME_LEN+1];
     long num;                                //variable number
     long datatype;
     long numElem;                            // variable dimensionality
     long recVariance;                        // variable rec Variance
     long dimVariances[CDF_MAX_DIMS];         // # of data values in dimSizes
} cdfVar[MAX_VARS];


int  ncID;
char ncFile[] = "fgmh000000000.nc";
int TimeDimID, TimeLengthID, DataID;         // ID of netCDF dimensions
int TimeDimVector[2], DataDimVector[2];      // netCDF Dim vectors
size_t Start[2] = {0L,0L};
size_t TimeCount[2] = {1L,TIMELENGTH};
size_t DataCount[2] = {1L,3L};

char Version[]="v01";
char ThemisID[]="tha\0";
char ThemisTime[]="tha_fgh_time";
char PAR0[]="tha_fgh_gse";
float FillValue[3] = {-1.e31,-1.e31,-1.e31};  

int StartTimeID, StopTimeID;
int FGMID;                         // Data netCDF Variables
int TimeID;                                                           // Time netCDF variable

char StartT[TIMELENGTH]; // Start time from  data
char StopT[TIMELENGTH];  // Stop time from  data
/**************************
   Function prototypes
**************************/
void usage();
void cdf_handle_error (CDFstatus);
void nc_handle_error (int);
void removeFilepath();
void removeCDFext();
void removeVers();

/*--------------------------------------------------------------------------*/
void usage()
{
   printf ("\nDescription:\n");
   printf ("    This program converts a themis CDF file into a netCDF file.\n");
   printf ("\n");
   printf ("Usage: fgm2nc <CDF file name> <ThemisID> <Resolution>\n");
   printf ("\n");
   printf ("Example: fgm2nc testfile tha h\n");
   printf ("\n");
   exit(1);
}
/*--------------------------------------------------------------------------
 *  Handles a CDF error.
 *--------------------------------------------------------------------------*/
void cdf_handle_error(CDFstatus status)
{

  char  message[CDF_STATUSTEXT_LEN+1];

   CDFerror (status, message);              /* Get the appropriate message */
   fprintf  (stderr, "%s\n", message);
   exit(1);
}
/*--------------------------------------------------------------------------
 *  Handles a netCDF error.
 *--------------------------------------------------------------------------*/
void nc_handle_error(int status)
{
  fprintf(stderr, "%s\n", nc_strerror(status));
  exit(1);
}
/*--------------------------------------------------------------------------
 *  Remove the filepath from a file name. *
 *  Example:
 *      /home/data/mydata.txt => mydata.txt
 *--------------------------------------------------------------------------*/
void removeFilepath (char *fileName)
{
    char *ptr;

    ptr = strrchr(fileName, '/');        // Unix file path separator
    if (ptr != NULL)
    {
        ptr++;
        strcpy(fileName, ptr);
    }
}
/*--------------------------------------------------------------------------
 *  Decode CDF File Name *
 *--------------------------------------------------------------------------*/
void removeVers (char *fileName)
{
    char *ptr;
    char zero = '\0';
    int i;
  
 for (i = 0; i < 9; i++)
  {
     ptr = strchr(fileName, '_');
      if (ptr != NULL)
     {
        ptr++;
        strcpy(fileName, ptr);
      }
    }
     ptr = strchr(fileName, '_');        //
  
     if (ptr != NULL)
    {
        ptr++;
         strncpy(Version, ptr, 2);
    }
 }

 /*--------------------------------------------------------------------------
 *  Remove the CDF extention *
 *--------------------------------------------------------------------------*/
void removeCDFext (char *fileName)
{
    char *ptr;
    char zero = '\0';

    ptr = strchr(fileName, '.');
    if (ptr != NULL)
       strcpy(ptr, &zero);
}
/*--------------------------------------------------------------------------
 *  NetCDF File Definition  *
 *--------------------------------------------------------------------------*/
 void ncdefine(double Time, char *Sampling)
 {
    char *s;
    time_t p;
    int status;
    char *STime;

/*********************** Create netCDF file *****************************/
      STime = Double2DD_Time(Time);
      
      memcpy(&(ncFile[3]),&(Sampling[0]), 1);
      memcpy(&(ncFile[4]),&(STime[2]), 9);
      if ((status = nc_create(ncFile, NC_CLOBBER, &ncID)) != NC_NOERR)
                                                      nc_handle_error(status);
/******************netCDF Dimensions *******************************/
        nc_def_dim (ncID, "Time", NC_UNLIMITED, &TimeDimID);
        nc_def_dim (ncID, "TimeLength", TIMELENGTH, &TimeLengthID);
        nc_def_dim (ncID, "Data",3L, &DataID);

/********************netCDF Variables ******************/
       TimeDimVector[0] = TimeDimID;
       DataDimVector[0] = TimeDimID;
       TimeDimVector[1] = TimeLengthID;
       DataDimVector[1] = DataID;

//ModeID, DensID, VelID, TempID;
       nc_def_var (ncID, "Time", NC_CHAR, 2, TimeDimVector, &TimeID);      
       nc_def_var (ncID, "B", NC_FLOAT, 2, DataDimVector, &FGMID);
       nc_def_var (ncID, "StartTime",NC_CHAR, 1, &TimeLengthID, &StartTimeID);
       nc_def_var (ncID, "StopTime",NC_CHAR, 1, &TimeLengthID , &StopTimeID);

       nc_put_att_text(ncID, NC_GLOBAL, "Themis", 3, ThemisID);
       nc_put_att_text(ncID, NC_GLOBAL, "Source", 12, Source);
       nc_put_att_text(ncID, NC_GLOBAL, "Resolution", 1, Sampling);
   //  nc_put_att_text(ncID, NC_GLOBAL, "Version", 2, Version);
       nc_put_att_text(ncID, FGMID, "Units", 2, "nT");     
       nc_put_att_text(ncID, FGMID, "Frame", 3, "GSE");

       time(&p);
       s = ctime(&p);
       nc_put_att_text(ncID, NC_GLOBAL, "Created", 24, s);
       nc_enddef(ncID);
       nc_put_vara_text(ncID, StartTimeID, &(Start[1]), &(TimeCount[1]), Double2DD_Time(Time));

 }
/*--------------------------------------------------------------------------*/
int main(int argc, char *argv[])
{
    long RecStart = 0, RecCount, RecCountF = 1, RecInt = 1, MaxRec;
    long indices[1] = {0}, counts[1] = {3}, intervals[1] = {1};
    long countsE[1] = {1}, indicesF[2]={0,3};
    double *value;
    size_t numElem;
    long dimN, varN, par0, par1;
    CDFstatus   cstatus;           // CDF status code
    CDFid id;
    int i, j, status;
    char fileName[MAX_FILE_NAME_LEN];
    char Sampling[1];
    dd_tmstr_t *dtm;
    int First = 1;
    float par[3];
    long DayOld;

    char *UT;
/*-------------------------------- Arguments Decoding ----------------------------------------*/
     if (argc <= 3) usage();       // CDF input file name and HEMIS Number not specified
     else
     {
           strcpy(fileName, argv[1]);
           strncpy(ThemisID, argv[2], 3);
           strncpy(Sampling, argv[3], 1);
      }
     
  
/*------------------------------------------ CDF Variables Names Updated according to THEMIS Number -------------*/
	       
        memcpy(&(ThemisTime[2]),&(ThemisID[2]),1);
        memcpy(&(PAR0[2]),&(ThemisID[2]),1);
        memcpy(&(ThemisTime[6]),&(Sampling[0]),1);
        memcpy(&(PAR0[6]),&(Sampling[0]),1);
       
/*********************** Open CDF file *****************************/
     if ((cstatus = CDFopen(fileName, &id))  != CDF_OK)
                                      cdf_handle_error(cstatus);
     printf(" %s %s\n", argv[2],argv[3]);

/*********** treat all vars as zVars with eliminated false dimensionality **********/
    
     if ((cstatus = CDFlib(SELECT_, CDF_zMODE_, zMODEon2, NULL_)) != CDF_OK)
                                                   cdf_handle_error (cstatus);

     // Remove the file path (/home/data/mydata => mydata)
      removeFilepath(fileName);
     // Remove Version Number
      removeVers(fileName);

     // Remove .cdf   extension
     removeCDFext(fileName);

/************************ Get CDF Data  ************************************/

   if ((cstatus = CDFlib(GET_, zVAR_NUMBER_, ThemisTime, &varN, NULL_)) != CDF_OK)
                                                    cdf_handle_error(cstatus) ;
   if ((cstatus = CDFlib( SELECT_, zVAR_, varN,
                                    GET_, zVAR_MAXREC_, &MaxRec, NULL_)) != CDF_OK)
                                                          cdf_handle_error(cstatus) ;

  
   if ((cstatus = CDFlib(GET_, zVAR_NUMBER_, PAR0, &par0, NULL_)) != CDF_OK)
                                                    cdf_handle_error(cstatus) ;
     
   if ((cstatus = CDFlib( SELECT_, zVAR_, par0,
                                 GET_, zVAR_DIMSIZES_, CDFDimSizes, NULL_)) != CDF_OK)
                                                       cdf_handle_error (cstatus) ;


      RecCount = (long)(MaxRec+1);
      printf(" Max Rec %d\n", MaxRec);
      if (MaxRec > 1) {
       value = (double *)malloc(sizeof(double)* RecCount);
       if ((cstatus = CDFlib (SELECT_,
		     zVAR_, varN,
		     zVAR_RECNUMBER_, RecStart ,
		     zVAR_RECCOUNT_, RecCount,
		     zVAR_RECINTERVAL_, RecInt,
		     zVAR_DIMINDICES_, indices,
		     zVAR_DIMCOUNTS_, countsE,
	             zVAR_DIMINTERVALS_, intervals,
                     GET_, zVAR_HYPERDATA_, value,  NULL_) )
                                             != CDF_OK)  cdf_handle_error (cstatus);

        for (i = 0; i < RecCount; i++)
          {
           
              UT = Double2DD_Time(value[i]);
              dtm =  ReadTime(UT);
     
              if (i > 0 && (value[i]-value[i-1])  >  TimeGap)
	        {
                    printf(" !!! Time GAP -> %f min\n", (value[i]-value[i-1])/60.0);
	            nc_put_vara_text(ncID,StopTimeID,&Start[1],&TimeCount[1], Double2DD_Time(dtm->times));
	            if ((status = nc_close(ncID)) != NC_NOERR) nc_handle_error(status);
	      }

              if (First == 1)
                {
                       ncdefine(dtm->times, Sampling);
                       First = 0;
                       DayOld = dtm->day;
                 }
              if (i > 0 && (value[i]-value[i-1])  >  TimeGap)
	        {
	           ncdefine(dtm->times, Sampling);
	           Start[0] = 0L;
	         }
                   nc_put_vara_text(ncID, TimeID, Start, TimeCount, Double2DD_Time(dtm->times));


	RecStart = (long)i;
     
	if ((cstatus = CDFlib (SELECT_, zVAR_, par0,
	                        zVAR_RECNUMBER_, RecStart ,
	                        zVAR_RECCOUNT_, RecCountF,
		                zVAR_RECINTERVAL_, RecInt,
		                zVAR_DIMINDICES_, indicesF,
	                        zVAR_DIMCOUNTS_, counts,
	                        zVAR_DIMINTERVALS_, intervals,
	                        GET_, zVAR_HYPERDATA_, par, NULL_))
                                              != CDF_OK)  cdf_handle_error(cstatus);
        if (!isnan(par[0]))          
           nc_put_vara_float(ncID, FGMID, Start, DataCount, par);
        else nc_put_vara_float(ncID, FGMID, Start, DataCount, FillValue);

          
	 Start[0]++;
        DayOld = dtm->day;
       }
      nc_put_vara_text(ncID,StopTimeID,&Start[1],&TimeCount[1], Double2DD_Time(dtm->times));
      free(value);
 
     if ((status = nc_close(ncID)) != NC_NOERR) nc_handle_error(status);
   }
/********************Close Files******************/
     if ((cstatus = CDFlib(CLOSE_, CDF_, NULL_)) != CDF_OK)
                            cdf_handle_error (cstatus);
     
}