themis_fgm2nc.c 11.4 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[] = "high_000000000.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[5]),&(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;

	nc_def_var (ncID, "Time", NC_CHAR, 2, TimeDimVector, &TimeID);      
	nc_def_var (ncID, "gse", 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);    
}