diff --git a/src/CALLEXT/createVI.php b/src/CALLEXT/createVI.php index 10f0668..f66cd02 100755 --- a/src/CALLEXT/createVI.php +++ b/src/CALLEXT/createVI.php @@ -80,8 +80,7 @@ $infoFile = $center->getDatasetInfo($remSetID); if ($infoFile) - { - echo "INFO ".$infoFile.PHP_EOL; + { $baseMgr->setInfo($infoFile); } @@ -89,12 +88,13 @@ if (!$infoFile && $ncFiles) { - echo "INFO ".$ncFiles[0].PHP_EOL; $baseMgr->setInfo($ncFiles[0]); } - $baseMgr->addRemoteData($remSetID, $ncFiles, $startIso, $stopIso); - + $baseMgr->addRemoteData($remSetID, $ncFiles, $startIso, $stopIso); + // put real Global Start from file - IMPORTANT for new AMDA Kernel + $baseMgr->updateRemoteStart(); + // if ($verbose) error_log("Get dataset info for ".$remSetID." from ".$dataBaseID." returns ".$res.PHP_EOL, 3, log); diff --git a/src/DATA/MANAGER/DDBaseMgr.php b/src/DATA/MANAGER/DDBaseMgr.php index 4f1a8d7..dc0438b 100644 --- a/src/DATA/MANAGER/DDBaseMgr.php +++ b/src/DATA/MANAGER/DDBaseMgr.php @@ -8,12 +8,12 @@ class DDBaseMgr { - private $brief, $times, $info, $info_xml, $cache; + public $brief, $times, $info, $info_xml, $cache; private $ViId, $remoteViId; private $DDsysDoc, $DDsys; private $base, $mission, $instrument; private $min_sampling, $max_sampling; - private $location, $ViDir; + public $location, $ViDir; public $globalStart = null, $globalStop = null; function __construct() @@ -212,8 +212,7 @@ class DDBaseMgr protected function lockVi() { - // Stamp -> this directory is being updated - + // Stamp -> this directory is being updated touch($this->ViDir."/LOCK"); // fprintf($STDERR,$ViDir." is LOCKED\n"); @@ -260,6 +259,24 @@ class DDBaseMgr //system("gunzip -c ".$this->ViDir."/$ncFile.gz > $fullAliasName"); } + + public function updateRemoteStart() + { + $startStamp = shell_exec("GetStartTime ".$this->location.$this->times); + $startIso = date("Y-m-d\TH:i:s", $startStamp).substr(fmod($startStamp, 1),1,4)."Z"; + + $xml_dom = new DomDocument("1.0"); + $xml_dom->load($this->location."/".$this->info_xml); + $startNode = $xml_dom->getElementsByTagName("GlobalStart")->item(0); + $startNode->nodeValue = $startIso; + + $xml_dom->save($this->location."/".$this->info_xml); + + $currDir = getcwd(); + chdir($this->location); + system("infoLocal2nc ".$this->info_xml." ".$this->info); + chdir($currDir); + } } ?> \ No newline at end of file diff --git a/src/DATA/TOOLS/GetStartTime.c b/src/DATA/TOOLS/GetStartTime.c new file mode 100644 index 0000000..9cf32ba --- /dev/null +++ b/src/DATA/TOOLS/GetStartTime.c @@ -0,0 +1,58 @@ + +/** @file GetStartTime.c +* @brief Stand-alone executable <br> Returns real Start for given VI in DDBase <br> +* +* @details GetStartTime(string *) <br> +* @arg \c argv[1] Full name of *_times.nc +* +*/ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <math.h> +#include <netcdf.h> +#include <DD.h> + + +int DataID, StartID; +double StartStamp; +char StartT[TIMELENGTH]; +size_t count[2] = {1L,TIMELENGTH}; +size_t start[2] = {0L,0L}; + +/*---------------- NC ERROR --------------------------------------*/ +void nc_handle_error(int status) +{ + fprintf(stderr, "%s\n", nc_strerror(status)); + exit(1); +} + +/* ----------------------- MAIN ------------------------------------*/ +int main(int argc, char *argv[]) +{ + int status, len; + + if (argc < 2){ + fprintf(stderr,"Usage: GetStartTime *_times.nc\n"); + exit(1); + } + + // Open VI_times.nc + if ((status = nc_open(argv[1], NC_NOWRITE, &DataID)) != NC_NOERR) + nc_handle_error(status); + + if ((status = nc_inq_varid(DataID, "StartTime", &StartID)) != NC_NOERR) + nc_handle_error(status); + + // Get The First Start + if((status = nc_get_vara_text(DataID, StartID, start, count, StartT)) != NC_NOERR) + nc_handle_error(status); + + StartStamp = DD_Time2Double(StartT); + + printf("%f\n", StartStamp); + if ((status = nc_close(DataID)) != NC_NOERR) nc_handle_error(status); +} diff --git a/src/DATA/TOOLS/StartStop.c b/src/DATA/TOOLS/StartStop.c new file mode 100644 index 0000000..d58a329 --- /dev/null +++ b/src/DATA/TOOLS/StartStop.c @@ -0,0 +1,104 @@ + +/** @file StartStop.c +* @brief Stand-alone executable <br> Returns real Start-Stop for VI in DDBase <br> +* Is used in DD Server WebServices <br> +* @details StartStop(string *, string *) <br> +* @arg \c argv[1] Full name of DDBase reference file <br> +* @arg \c argv[2] Virtual Instrument ID (DD notation) <br> +* Output: YYYYDDdayHHMMSSMLS-YYYYDDdayHHMMSSMLS +* +* @date 10.10.2007 +* @version $Id: StartStop.c,v 1.3 2011/09/05 11:27:34 budnik Exp $ +*/ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <math.h> +#include <netcdf.h> +#include <DD.h> + + +int DataID, RecID, VarID, StartID, StopID; +size_t RecNum; +char StartT[TIMELENGTH], StopT[TIMELENGTH], Var[128]; +size_t count[2] = {1L,TIMELENGTH}; +size_t start[2] = {0L,0L}; +size_t countVar[2] = {1L,128L}; + +/*---------------- NC ERROR --------------------------------------*/ +void nc_handle_error(int status) +{ + fprintf(stderr, "%s\n", nc_strerror(status)); + exit(1); +} + +/* ----------------------- MAIN ------------------------------------*/ + int main(int argc, char *argv[]) +{ + + int status, len; + + char Project[50],Instrument[50],Mode[50], RInstrName[100]; + + + if (argc < 3) + { + fprintf(stderr,"Usage: StartStop reference_file_name DD_VI_ID\n"); + exit(0); + } + + + if ((status = nc_open(argv[1], NC_NOWRITE, &DataID)) != NC_NOERR) + nc_handle_error(status); + + sscanf(argv[2], "%[^:]%*c%[^:]%*c%[^:]%*c",Project, + Instrument, + Mode); + sprintf(RInstrName,"%s_%s_%s\0",Project,Instrument,Mode); + + if ((status = nc_inq_varid(DataID,RInstrName,&VarID)) != NC_NOERR) + nc_handle_error(status); + + start[0] = 1; + if((status = nc_get_vara_text(DataID, VarID, start, countVar, Var)) != NC_NOERR) + nc_handle_error(status); + + len = strcspn(Var," "); Var[len] = '\0'; + + if ((status = nc_close(DataID)) != NC_NOERR) nc_handle_error(status); + +// Open VI_times.nc + + if ((status = nc_open(Var, NC_NOWRITE, &DataID)) != NC_NOERR) + nc_handle_error(status); + + if ((status = nc_inq_dimid(DataID, "record", &RecID)) != NC_NOERR) + nc_handle_error(status); + +// Get Number of Records + + if ((status = nc_inq_dimlen(DataID, RecID, &RecNum)) != NC_NOERR) + nc_handle_error(status); + + if ((status = nc_inq_varid(DataID, "StartTime", &StartID)) != NC_NOERR) + nc_handle_error(status); + if ((status = nc_inq_varid(DataID, "StopTime", &StopID)) != NC_NOERR) + nc_handle_error(status); + +// Get The First Start and The Last Stop Times + start[0] = 0; + + if((status = nc_get_vara_text(DataID, StartID, start, count, StartT)) != NC_NOERR) + nc_handle_error(status); + + start[0] = RecNum-1; + if((status = nc_get_vara_text(DataID, StopID, start, count, StopT)) != NC_NOERR) + nc_handle_error(status); + + printf("%s-%s\n", StartT, StopT); + if ((status = nc_close(DataID)) != NC_NOERR) nc_handle_error(status); + +} diff --git a/src/DECODERS/cdfnew2nc/CMakeLists.txt b/src/DECODERS/cdfnew2nc/CMakeLists.txt new file mode 100644 index 0000000..777c65c --- /dev/null +++ b/src/DECODERS/cdfnew2nc/CMakeLists.txt @@ -0,0 +1,26 @@ + +PROJECT(cdfnew2nc) + +include_directories( + ${DDCLIENTINCLUDE_DIR} + ${NETCDFINCLUDE_DIR} + ${libcdf_INCLUDE_DIR} +) + +#Configuration de l'exécutable +file( + GLOB_RECURSE + source_files + ./* +) + +ADD_EXECUTABLE (cdfnew2nc ${source_files} ) + +target_link_libraries( + cdfnew2nc + ${DDCLIENTLIBRARY} + ${NETCDFLIBRARY} + ${libcdf_LIBRARIES} +) + +install (TARGETS cdfnew2nc DESTINATION bin) diff --git a/src/DECODERS/cdfnew2nc/cdfnew2nc.c b/src/DECODERS/cdfnew2nc/cdfnew2nc.c new file mode 100644 index 0000000..ee003b1 --- /dev/null +++ b/src/DECODERS/cdfnew2nc/cdfnew2nc.c @@ -0,0 +1,1994 @@ +/********************************************************** + * Usage : amda-cdf-to-netcdf-w-false FileName [varToKeep1 varToKeep2 .....] + * No 'false dims' suppression + *********************************************************/ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include "netcdf.h" +#include "cdf.h" + +#define MAX_FILE_NAME_LEN 120 /* Max. file name length */ +#define MAX_ATTRS 3000 /* Max # of CDF attributes */ +#define UNKNOWN_DT -99 /* Unsupported CDF datatype indicator */ + +#define DEFAULT_MAPPING_FILE "cdf_to_netcdf_mapping.dat" +#define MAX_REC_LENGTH NC_MAX_NAME+CDF_ATTR_NAME_LEN256+2 + /* Max record length of DEFAULT_MAPPING_FILE */ + +#define TRUE 1 +#define FALSE 0 + +/************************************* + Global variables and structures +**************************************/ +CDFid id; /* CDF file ID */ +int ncid; /* netCDF file ID */ + +long nZvars, /* Number of zVariables in a CDF file */ + nAttrs; /* Number of attributes (global & variable) in a CDF file */ + +typedef struct ncdim { /* netCDF dimension structure */ + char name[NC_MAX_NAME+1]; /* Dimension name */ + int size; /* Dimension size */ + int id; /* Dimension id */ +} netcdfDimension; + +netcdfDimension ncDims[NC_MAX_DIMS]; /* max dimensions per netCDF file */ +int totNCdims = 0; /* Total # of netCDF dimensions created */ + +typedef struct cdfvar { /* CDF variable structure */ + char name[CDF_VAR_NAME_LEN256+1]; + long datatype; + long numElements; /* string length for CDF_CHAR, 1 otherwise */ + long dimensionality; /* variable dimensionality */ + long dimSizes[CDF_MAX_DIMS]; /* variable dimension sizes */ + long recVariance; /* record variance */ + long numRecs; /* # of records this variable contains */ +} CDFvar; + +/**************************************************************************** + * Arrays to hold the CDF-to-netCDF mapping information that are loaded + * from the default or user-define mapping file. + ****************************************************************************/ +char netcdfAttrNames[MAX_ATTRS][NC_MAX_NAME]; +char cdfAttrNames[MAX_ATTRS][CDF_ATTR_NAME_LEN256+1]; +char comments[MAX_ATTRS][CDF_ATTR_NAME_LEN256+1]; + +int totAttrsInMappingFile; /* # of attributes in the mapping file */ +char mappingFile[CDF_PATHNAME_LEN]; /* Mapping file name */ + +int DEBUG = FALSE; + + + +/************************** + Function prototypes +**************************/ +int endsWith(char *, char *); +char * strlaststr(char *, char *); +void get_cdf_attribute(long, long, long, int); +void get_cdf_attr_data(char *, long, long, long, int); +char * cdf_str_datatype (long); +char * NC_datatype (nc_type); +nc_type get_netcdf_datatype (long); +void usage(); +CDFid cdf_open(char *); +void read_cdf_file_info(); +void get_zVariables(long *, int); +int create_netcdf_dimensions_attribute (int *); +void create_netcdf_dimensions_variable (CDFvar, long, int *, int *); +int create_netcdf_variable (CDFvar, long, int); +void get_cdf_variable_data (long, CDFvar, long); +void read_cdf_variable_data (long, long, long, long, long [], void *); +void removeFilepath(); +void handle_netcdf_error (int); +void memory_error(char *, char *); +void cdf_status_handler (CDFstatus, char *); +void insufficient_memory(); /* used for debug */ +char * getNextArgument (int, char *[], int); +void parseCmdLine (int, char *[]); +void errorMsg (char *); +void map_CDF_attr_to_netCDF (char *, char *); +void breakdown_DIMENSIONS_entry (char *, char **); + +#define AMDA +#ifdef AMDA + +#include "tools.h" + +char start_time [DD_TIME_STRING_LEN+1]; +char stop_time [DD_TIME_STRING_LEN+1]; + +#endif + +/**************************************************************************** + NOTE: + + CDF has the following features that are not supported by netCDF: + + - CDF_EPOCH datatype (8-byte real number) that is used to store time + values referenced from a particular epoch that is + 01-Jan-0000 00:00:00.000. CDF_EPOCH values are the number of + milliseconds since the epoch described above. + + - CDF_EPOCH16 datatype (16-byte real number) that is used to store time + values referenced from a particular epoch that is + 01-Jan-0000 00:00:00.000.000.000.000. CDF_EPOCH16 values are the + number of milliseconds since the epoch described above. + + - CDF global attribute (not variable attribute) can have multiple + attribute entries and each entry can have a different datatype. +*****************************************************************************/ +int main(int argc, char *argv[]) +{ + FILE *inFile; /* Pointer to the CDF-to-netCDF mapping file */ + char rec[MAX_REC_LENGTH]; /* CDF-to-netCDF mapping record */ + + /************************/ + /* netCDF declaration */ + /************************/ + int status, /* netCDF status code */ + dummy, i; + + char *ptr, fileName[CDF_PATHNAME_LEN]; + + /**********************/ + /* CDF declaration */ + /**********************/ + CDFstatus cstatus; /* CDF status code */ + long attrId; /* CDF attribute ID */ + long varId; + long *varsToGet; + int nVarsToGet; + + if (argc <= 1) + usage(); /* CDF input file name not specified */ + else { + strcpy(fileName, argv[1]); /* Get the input file name */ + strcpy(mappingFile, "UNSPECIFIED"); + parseCmdLine(argc, argv); + if (strcmp(mappingFile, fileName) == 0) + errorMsg("** Error - either input file or mapping file is missing"); + if (strcmp(mappingFile,"UNSPECIFIED") == 0) + strcpy(mappingFile, DEFAULT_MAPPING_FILE); + } + +#ifdef AMDA + + + status = check_version(); +#endif + /***********************************************/ + /* Load the CDF-to-netCDF mapping information */ + /***********************************************/ + if ((inFile = fopen(mappingFile, "r")) == NULL) { + printf ("WARNING : Cannot open file: %s **\n", mappingFile); + totAttrsInMappingFile = 0; + } + else { + totAttrsInMappingFile = 0; + while (fgets(rec, MAX_REC_LENGTH, inFile) != NULL) { + rec[strlen(rec)-1] = '\0'; /* Remove the newline character */ + + /* Process the mapping record if it's not a comment */ + if (rec[0] != '#' && rec[0] != ' ' && strlen(rec) > 0) { + sscanf(rec, "%s %s", + netcdfAttrNames[totAttrsInMappingFile], + cdfAttrNames[totAttrsInMappingFile]); + ptr = (char *) strstr(rec, "//"); + if (ptr != NULL) { + ptr += 3; + strcpy (comments[totAttrsInMappingFile], ptr); + } + if (DEBUG) + printf("%s %s %s\n", + netcdfAttrNames[totAttrsInMappingFile], + cdfAttrNames[totAttrsInMappingFile], + comments[totAttrsInMappingFile]); + totAttrsInMappingFile++; + } + } + } + /*********************************************************** + * Process the CDF information and create a netCDF file + ***********************************************************/ +/* printf ("\nInput file name: %s\n", fileName); */ + id = cdf_open (fileName); + + /* Remove the file path if it exists (/home/mydata.cdf => mydata.cdf). */ + removeFilepath(fileName); + + if (endsWith(fileName,".cdf")) { + /* Strip off the .cdf file extension. */ + ptr = (char *) strlaststr(fileName, ".cdf"); + if (ptr != NULL) *ptr = '\0'; + } + strcat(fileName, ".nc"); + status = nc_create(fileName, NC_CLOBBER, &ncid); + if (status != NC_NOERR) handle_netcdf_error(status); + printf ("Output file name: %s\n", fileName); + + /*********************************************************************** + * Get the number of dimensions, number of variables, number of global + * attributes. + * + * Note that the information retrieved from read_cdf_file_info are stored + * into the global variables defined at the top. + ***********************************************************************/ + read_cdf_file_info (); + if (DEBUG) printf ("nAttrs=%ld, nZvars=%ld\n", nAttrs, nZvars); + + /* Get the CDF global attributes and create netCDF global attributes. */ + if (DEBUG) printf ("Global attributes:\n"); + dummy = -1; + for (attrId = 0; attrId < nAttrs; attrId++) + get_cdf_attribute(attrId, GLOBAL_SCOPE, (long) dummy, dummy); + + /* Write the placeholder attributes. */ + for (i=0; i < totAttrsInMappingFile; i++) { + if (strcmp(cdfAttrNames[i],"*") == 0) { + status = nc_put_att_text (ncid, + NC_GLOBAL, /* vavriable ID */ + netcdfAttrNames[i], /* Attribute name */ + strlen(comments[i]), /* # of attr values */ + comments[i]); + } + } + + + /* Process CDF variables and create netCDF variables */ + if (argc > 2) { + varsToGet = (long *) malloc(sizeof(long)*(argc-2)); + for (i = 2; i < argc; i++ ) { + status = CDFlib ( GET_, zVAR_NUMBER_, argv[i], &varId); + varsToGet[i-2] = varId; + } + nVarsToGet = argc-2; + } + else { + varsToGet = (long *) malloc(sizeof(long)*nZvars); + for (i = 0; i < nZvars; i++) varsToGet[i] = (long)i; + nVarsToGet = nZvars; + } + printf("NVARS %d\n",nVarsToGet); + if (nZvars > 0) get_zVariables(varsToGet, nVarsToGet); + + + /* Close the netCDF and CDF files */ + cstatus = CDFlib (CLOSE_, CDF_, NULL_); + if (cstatus != CDF_OK) cdf_status_handler (cstatus, "CLOSE_, CDF_"); + + status = nc_close(ncid); + if (status != NC_NOERR) handle_netcdf_error(status); +} + + +/*---------------------------------------------------------------------------- + * TRUE if s1 ends with s2. Otherwise, FALSE is returned. + *---------------------------------------------------------------------------*/ +int endsWith (char *s1, char *s2) +{ + int i; + char *ps1, *ps2; + + if (strlen(s2) > strlen(s1)) + return FALSE; + + ps1 = s1 + strlen(s1) - strlen(s2); + ps2 = s2; + + for (i=0; i < strlen(s2); i++) + if (*(ps1++) != *(ps2++)) + return FALSE; + + return TRUE; +} + + +/*--------------------------------------------------------------------------------- + * Find the last occurence of s2 in s1. If s21 is not found, s1 is returned. + *--------------------------------------------------------------------------------*/ +char * strlaststr (char *s1, char *s2) +{ + char *sc2, *psc1, *ps1; + + if (*s2 == '\0') + return((char *)s1); + + ps1 = s1 + strlen(s1); + + while(ps1 != s1) { + --ps1; + for (psc1 = ps1, sc2 = s2; ; ) + if (*(psc1++) != *(sc2++)) + break; + else if (*sc2 == '\0') + return ((char *)ps1); + } + return ((char *)NULL); +} + + +/*-------------------------------------------------------------------------- + * This routine opens a CDF file + *-------------------------------------------------------------------------*/ +CDFid cdf_open (char *fileName) +{ + CDFstatus status; + CDFid id; + char msg[500]; + + status = CDFlib (OPEN_, CDF_, fileName, /* in - file name to be opened */ + &id, /* out - CDF file ID */ + NULL_); + + if (status != CDF_OK) { + strcpy(msg, "OPEN_, CDF_, "); + strcat(msg, fileName); + cdf_status_handler (status, msg); + } + return id; +} + + +/*--------------------------------------------------------------------------- + * This routine retrievs the following information: + * + * nAttr - number of attributes (including global and variable) + * nZvars - number of zVariables + * + * CDF file can have both rVariables (old style) and zVariables (new style) + * simultaneously. zVariable is a superset of rVariable, and it is a lot + * more efficient and offers all the functionality a rVariable offers and + * more. Treat all CDF variables as zVariables. + *--------------------------------------------------------------------------*/ +void read_cdf_file_info () +{ + CDFstatus status; + + status = CDFlib (SELECT_, CDF_zMODE_, zMODEon2, + GET_, CDF_NUMATTRS_, &nAttrs, + CDF_NUMzVARS_, &nZvars, + NULL_); + if (status != CDF_OK) cdf_status_handler (status, "GET_, CDF_FILEINFO_"); +} + + +/*---------------------------------------------------------------------------- + * This routine retrieves the CDF attribute (global or variable) name + * and its data for the given CDF attribute ID. + *---------------------------------------------------------------------------*/ +void get_cdf_attribute(long attrNum, /* in - CDF attribute number/id */ + long scope, /* in - CDF attribute scope */ + long cdfVarId, /* in - CDF variable number/id */ + int netcdfVarId) /* in - netCDF variable ID */ +{ + int ncstatus, i, len; + long status, numEntries, datatype, attrScope, entryNum, + numElements; + nc_type ncDatatype; /* netCDF datatype */ + + char *cPtr, attrName[CDF_ATTR_NAME_LEN256+1], + mappedAttrName[CDF_ATTR_NAME_LEN256+1]; + + status = CDFlib (SELECT_, ATTR_, attrNum, + GET_, ATTR_NAME_, attrName, + ATTR_SCOPE_, &attrScope, + NULL_); + if (status != CDF_OK) cdf_status_handler (status, "SELECT_, ATTR_"); + + /****************************************************************/ + /* If the attribute scope is not the requested attribute scope */ + /* (VARIABLE_SCOPE or GLOBAL_SCOPE), do not process the current */ + /* attribute. */ + /****************************************************************/ + if (attrScope != scope) return; + if (strcmp(attrName, "DIMENSIONS_G") == 0 || + strcmp(attrName, "DIMENSIONS_V") == 0) return; + map_CDF_attr_to_netCDF(attrName, mappedAttrName); + strcpy(attrName, mappedAttrName); + + if (attrScope == GLOBAL_SCOPE) { + status = CDFlib (GET_, ATTR_NUMgENTRIES_, &numEntries, NULL_); + if (status != CDF_OK) + cdf_status_handler (status, "GET_, ATTR_NUMgENTRIES_"); + if (DEBUG) printf ("\t%s", attrName); + + /********************************************************************* + * While the CDF global attribute can have multiple entries of + * of different datatypes, the CDF variable attribute can only have + * one attribute entry. netCDF doesn't allow more than 1 attribute + * entry - handle this case + ********************************************************************/ + for (entryNum=0; entryNum < numEntries; entryNum++) { + if (entryNum > 0) /* Attribute has more than 1 entry */ + sprintf (attrName, "%s_%ld", mappedAttrName, entryNum); + status = CDFlib (SELECT_, gENTRY_, entryNum, + GET_, gENTRY_DATATYPE_, &datatype, + gENTRY_NUMELEMS_, &numElements, + NULL_); + if (status == NO_SUCH_ENTRY) return; + if (status != CDF_OK) cdf_status_handler(status,"GET_ATTR_INFO_"); + get_cdf_attr_data (attrName, gENTRY_DATA_, datatype, numElements, + netcdfVarId); + } + } + else { + /********************************************************************* + * IMPORTANT NOTE: + * For the variable attribute, entry number is the variable ID. + *********************************************************************/ + status = CDFlib (SELECT_, zENTRY_, cdfVarId, + GET_, zENTRY_DATATYPE_, &datatype, + zENTRY_NUMELEMS_, &numElements, + NULL_); + /******************************************************************/ + /* If there's no attribute entry for the current attribute number */ + /* selected, process the next attribute. */ + /******************************************************************/ + if (status == NO_SUCH_ENTRY) return; + + if (status != CDF_OK) cdf_status_handler (status,"GET_ATTR_INFO_"); + if (DEBUG) printf ("\t%s", attrName); + if (attrName[strlen(attrName)-1] == (char) '_') { + char name2[CDF_ATTR_NAME_LEN256+1]; + strcpy(name2, attrName); + name2[strlen(name2)-1] = (char) '\0'; + status = CDFlib (GET_, ATTR_NUMBER_, name2, &attrNum, + NULL_); + if (status == CDF_OK) { + strcpy(attrName, name2); + map_CDF_attr_to_netCDF(attrName, mappedAttrName); + strcpy(attrName, mappedAttrName); + } + } + get_cdf_attr_data (attrName, zENTRY_DATA_, datatype, numElements, + netcdfVarId); + } +} + + +/*-------------------------------------------------------------------------- + * This routine retrieves the CDF attribute data (a.k.a. attribute entries) + * and write its values to the target netCDF file. + *--------------------------------------------------------------------------*/ +void get_cdf_attr_data (char *attrName, /* in - attribute name */ + long entryData, /* in - type of attr entry data */ + long datatype, /* in - attribute datatype */ + long numElements, /* in - # of attribute values */ + int netcdfVarId) /* in - netCDF variable ID */ +{ + char entryDataType[20], msg[100], + epString[EPOCH4_STRING_LEN+1], + ep16String[EPOCH16_4_STRING_LEN+1], + mappedAttrName[CDF_ATTR_NAME_LEN256+1], + tt2000String[TT2000_3_STRING_LEN+1]; + double epoch16[2]; + + nc_type ncDatatype; /* netCDF datatype */ + int nc_status, /* netCDF status code */ + varId; /* netCDF variable ID */ + long status; /* CDF status code */ + + char *cPtr; + signed char *scPtr; + unsigned char *uscPtr; + short *sPtr; + unsigned short *usPtr; + int *iPtr, i; + unsigned int *uiPtr; + long long *jPtr, aLonglong; + float *fPtr; + double *dPtr; + + /************************************************* + * entryData has one of following values: + * + * gENTRY_DATA_ - global attribute entry + * rENTRY_DATA_ - rVariable attribute entry + * zENTRY_DATA_ - zVariable attribute entry + *************************************************/ + if (entryData == gENTRY_DATA_) { + varId = NC_GLOBAL; + strcpy(entryDataType, "gENTRY_DATA_"); + } + else { + varId = netcdfVarId; + strcpy(entryDataType, "zENTRY_DATA_"); + } + strcpy (msg, "get_cdf_attr_data, GET_, "); + strcat (msg, entryDataType); + strcat (msg, cdf_str_datatype(datatype)); + + /* Map the CDF datatype to an appropriate netCDF datatype. */ + ncDatatype = get_netcdf_datatype (datatype); + + /* Remove trailing blank spaces if there are any */ + for (i=strlen(attrName)-1; i >= 0; i--) { + if (attrName[i] != ' ') { + attrName[i+1] = '\0'; + break; + } + } + /* Replace blanks space(s) with underscore(s). */ + for (i=0; i < strlen(attrName); i++) { + if (attrName[i] == ' ') attrName[i] = '_'; + } + + switch (datatype) { + case CDF_CHAR: + case CDF_UCHAR: + cPtr = (char *) malloc(numElements * sizeof(char) + 1); + if (cPtr == NULL) memory_error("get_cdf_attr_data", "NC_CHAR"); + status = CDFlib (GET_, entryData, cPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + *(cPtr+numElements) = '\0'; /* End of string mark */ + if (DEBUG) printf (" = \"%s\"", cPtr); + nc_status = nc_put_att_text(ncid, varId, attrName, numElements, cPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free(cPtr); + break; + + case CDF_BYTE: + case CDF_INT1: + scPtr = (signed char *) malloc (sizeof(signed char) * numElements); + if (scPtr == NULL) memory_error("get_cdf_attr_data", "NC_BYTE"); + status = CDFlib (GET_, entryData, scPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%d", *(scPtr+i)); + } + } + nc_status = nc_put_att_schar(ncid, varId, attrName, ncDatatype, + numElements, scPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (scPtr); + break; + + case CDF_UINT1: + uscPtr = (unsigned char *) malloc (sizeof(unsigned char) * numElements); + if (uscPtr == NULL) memory_error("get_cdf_attr_data", "NC_BYTE"); + sPtr = (short *) malloc (sizeof(short) * numElements); + if (sPtr == NULL) memory_error("get_cdf_attr_data", "NC_SHORT"); + status = CDFlib (GET_, entryData, uscPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%d", *(uscPtr+i)); + } + } + for (i = 0; i < numElements; ++i) { + *(sPtr+i) = (short) *(uscPtr+i); + } + nc_status = nc_put_att_short(ncid, varId, attrName, ncDatatype, + numElements, sPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (uscPtr); + free (sPtr); + break; + + case CDF_INT2: + sPtr = (short *) malloc (sizeof(short) * numElements); + if (sPtr == NULL) memory_error("get_cdf_attr_data", "NC_SHORT"); + status = CDFlib (GET_, entryData, sPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%hd", *(sPtr+i)); + } + } + nc_status = nc_put_att_short(ncid, varId, attrName, ncDatatype, + numElements, sPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (sPtr); + break; + + case CDF_UINT2: + usPtr = (unsigned short *) malloc (sizeof(unsigned short) * numElements); + if (usPtr == NULL) memory_error("get_cdf_attr_data", "NC_SHORT"); + iPtr = (int *) malloc (sizeof(int) * numElements); + if (iPtr == NULL) memory_error("get_cdf_attr_data", "NC_INT"); + status = CDFlib (GET_, entryData, usPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%hu", *(usPtr+i)); + } + } + for (i = 0; i < numElements; ++i) { + *(iPtr+i) = (int) *(usPtr+i); + } + nc_status = nc_put_att_int(ncid, varId, attrName, ncDatatype, + numElements, iPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (usPtr); + free (iPtr); + break; + + case CDF_INT4: + iPtr = (int *) malloc (sizeof(int) * numElements); + if (iPtr == NULL) memory_error("get_cdf_attr_data", "NC_INT"); + status = CDFlib (GET_, entryData, iPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%d", *(iPtr+i)); + } + } + nc_status = nc_put_att_int(ncid, varId, attrName, ncDatatype, + numElements, iPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (iPtr); + break; + + case CDF_UINT4: + uiPtr = (unsigned int *) malloc (sizeof(unsigned int) * numElements); + if (uiPtr == NULL) memory_error("get_cdf_attr_data", "NC_INT"); + dPtr = (double *) malloc (sizeof(double) * numElements); + if (dPtr == NULL) memory_error("get_cdf_attr_data", "NC_DOUBLE"); + status = CDFlib (GET_, entryData, uiPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%ud", *(uiPtr+i)); + } + } + for (i = 0; i < numElements; ++i) { + *(dPtr+i) = (double) *(uiPtr+i); + } + nc_status = nc_put_att_double(ncid, varId, attrName, ncDatatype, + numElements, dPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (uiPtr); + free (dPtr); + break; + + case CDF_INT8: + jPtr = (long long *) malloc (sizeof(long long) * numElements); + if (jPtr == NULL) memory_error("get_cdf_attr_data", "NC_INT64"); + dPtr = (double *) malloc (sizeof(double) * numElements); + if (dPtr == NULL) memory_error("get_cdf_attr_data", "NC_DOUBLE"); + status = CDFlib (GET_, entryData, jPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%lld", *(jPtr+i)); + } + } + for (i = 0; i < numElements; ++i) { + *(dPtr+i) = (double) *(jPtr+i); + } + nc_status = nc_put_att_double(ncid, varId, attrName, ncDatatype, + numElements, dPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (jPtr); + free (dPtr); + break; + + case CDF_FLOAT: + case CDF_REAL4: + fPtr = (float *) malloc (sizeof(float) * numElements); + if (fPtr == NULL) memory_error("get_cdf_attr_data", "NC_FLOAT"); + status = CDFlib (GET_, entryData, fPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%g", *(fPtr+i)); + } + } + nc_status = nc_put_att_float(ncid, varId, attrName, ncDatatype, + numElements, fPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (fPtr); + break; + + case CDF_DOUBLE: + case CDF_REAL8: + dPtr = (double *) malloc (sizeof(double) * numElements); + if (dPtr == NULL) memory_error("get_cdf_attr_data", "NC_DOUBLE"); + status = CDFlib (GET_, entryData, dPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) { + printf (" = "); + for (i=0; i < numElements; i++) { + if (i > 0) printf (", "); + printf ("%g", *(dPtr+i)); + } + } + nc_status = nc_put_att_double(ncid, varId, attrName, + ncDatatype, numElements, dPtr); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + free (dPtr); + break; + + case CDF_EPOCH: /* 8-byte real number */ + dPtr = (double *) malloc (sizeof(double) * numElements); + if (dPtr == NULL) memory_error("get_cdf_attr_data", "CDF_EPOCH"); + status = CDFlib (GET_, entryData, dPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) printf (" = "); + for (i=0; i < numElements; i++) { + encodeEPOCH4 (* (dPtr+i), epString); + nc_status = nc_put_att_text(ncid, varId, attrName, EPOCH4_STRING_LEN, epString); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + if (DEBUG) { + if (i > 0) printf (", "); + printf ("%s", epString); + if (i == (numElements -1)) printf ("\n"); + } + } + free (dPtr); + break; + + case CDF_EPOCH16: /* 16-byte real number */ + dPtr = (double *) malloc (sizeof(double) * numElements * 2); + if (dPtr == NULL) memory_error("get_cdf_attr_data", "CDF_EPOCH16"); + status = CDFlib (GET_, entryData, dPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) printf (" = "); + for (i=0; i < numElements; i++) { + epoch16[0] = *(dPtr+i*2); + epoch16[1] = *(dPtr+i*2+1); + encodeEPOCH16_4 (epoch16, ep16String); + nc_status = nc_put_att_text(ncid, varId, attrName, + strlen(ep16String), ep16String); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + if (DEBUG) { + if (i > 0) printf (", "); + printf ("%s", ep16String); + if (i == (numElements -1)) printf ("\n"); + } + } + free (dPtr); + break; + + case CDF_TIME_TT2000: /* 8-byte integer number */ + jPtr = (long long *) malloc (sizeof(long long) * numElements); + if (jPtr == NULL) memory_error("get_cdf_attr_data", "CDF_TIME_TT2000"); + status = CDFlib (GET_, entryData, jPtr, NULL_); + if (status != CDF_OK) cdf_status_handler (status, msg); + if (DEBUG) printf (" = "); + for (i=0; i < numElements; i++) { + encodeTT2000 (*(jPtr+i), tt2000String); + nc_status = nc_put_att_text(ncid, varId, attrName, + TT2000_3_STRING_LEN, tt2000String); + if (nc_status != NC_NOERR) handle_netcdf_error(nc_status); + if (DEBUG) { + if (i > 0) printf (", "); + printf ("%s", tt2000String); + if (i == (numElements -1)) printf ("\n"); + } + } + free (jPtr); + break; + + default: + printf ("** Error in get_cdf_attribute: bad data type"); + } + if (DEBUG) printf (" ;\n"); +} + + +/*-------------------------------------------------------------------------- + * Get the zVariables in the CDF file. + *--------------------------------------------------------------------------*/ +void get_zVariables(long *vars, int nvars) +{ + CDFstatus status; + int i, ncstatus, createUnlimitedDim, unlimitedDimId, + attrId, netcdfVarId, bypass; + char netcdfDimName[NC_MAX_NAME+1]; /* netCDF dimension name */ + long holdDim, holdDim0; + long varId, ncVarId; + CDFvar var; + + if (DEBUG) printf ("\n"); + + createUnlimitedDim = TRUE; + bypass = FALSE; + + for (i = 0; i < nvars; i++) { + + varId = vars[i]; + ncVarId = (long)i; + status = CDFlib (SELECT_,zVAR_, varId, + GET_, zVAR_NAME_, var.name, + zVAR_DATATYPE_, &var.datatype, + zVAR_NUMELEMS_, &var.numElements, + zVAR_NUMDIMS_, &var.dimensionality, + zVAR_DIMSIZES_, var.dimSizes, + zVAR_NUMRECS_, &var.numRecs, + zVAR_RECVARY_, &var.recVariance, + NULL_); + if (status != CDF_OK) cdf_status_handler (status, "GET_, zVARS_"); + + if (DEBUG) { + printf ("var name = %s, %s/%ld, %ld:[", + var.name, cdf_str_datatype(var.datatype), + var.numElements, var.dimensionality); + for (i=0; i < var.dimensionality; i++) { + if (i > 0) printf (","); + printf ("%ld", var.dimSizes[i]); + } + printf("], numRecs = %ld\n", var.numRecs); + } + + if (varId == 0) + bypass = create_netcdf_dimensions_attribute (&unlimitedDimId); + if (!bypass) + create_netcdf_dimensions_variable (var, ncVarId, &createUnlimitedDim, + &unlimitedDimId); + netcdfVarId = create_netcdf_variable (var, ncVarId, unlimitedDimId); + + /* Leave the define mode before adding data */ + ncstatus = nc_enddef(ncid); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + + get_cdf_variable_data (varId, var, ncVarId); + + /* Enter the define mode before writing netCDF variable attributes */ + /* and creating a variable. */ + ncstatus = nc_redef(ncid); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + + /* Get the variable attributes */ + for (attrId = 0; attrId < nAttrs; attrId++) + get_cdf_attribute(attrId, VARIABLE_SCOPE, varId, netcdfVarId); + } +#ifdef AMDA + + if (set_file_time_coverage() == -1) { + + printf ("ERROR : unable to compute file time coverage\n"); + } + + if (rename_time_variable () == -1) { + + printf ("ERROR : uname to rename time variable\n"); + } + + +#endif +} + + +/*-------------------------------------------------------------------------- + * This routine creates all netCDF dimensions from a global attribute if + * such attribute exists (likely the CDF is created by netcdf-to-cdf + * converter). It returns TRUE if dimensions are creaated, FLASE otherwise. + *--------------------------------------------------------------------------*/ +int create_netcdf_dimensions_attribute (int *unlimitedDimId) +{ + int status, /* netCDF status code */ + i, id, value, len; + long numElems, numEntries; + char netcdfDimName[NC_MAX_NAME+1]; /* netCDF dimension name */ + char valueStr[20+1]; + char *ptr, entry[NC_MAX_NAME + 20 + 1]; + CDFstatus statusC; + + statusC = CDFlib (SELECT_, ATTR_NAME_, "DIMENSIONS_G", + GET_, ATTR_NUMgENTRIES_, &numEntries, + NULL_); + if (statusC != CDF_OK) return FALSE; + /* A CDF file that was created by netCDF-to-cdf */ + for (i = 0; i < (int) numEntries; ++i) { + statusC = CDFlib (SELECT_, ATTR_NAME_, "DIMENSIONS_G", + gENTRY_, (long) i, + GET_, gENTRY_DATA_, entry, + gENTRY_NUMELEMS_, &numElems, + NULL_); + if (statusC != CDF_OK) continue; + entry[numElems] = (char) '\0'; + ptr = strstr(entry, "="); + if (ptr == NULL) continue; + len = (int) (ptr - entry); + strncpy(netcdfDimName, entry, len); + strcpy(valueStr, ptr+1); + netcdfDimName[len] = (char) '\0'; + if (strcmp(valueStr, "UNLIMITED") == 0) { + status = nc_def_dim(ncid, /* in */ + netcdfDimName, /* in */ + NC_UNLIMITED, /* in */ + unlimitedDimId); /* out */ + } else { + if (sscanf(valueStr, "%d", &value) != 1) continue; + status = nc_def_dim(ncid, /* in */ + netcdfDimName, /* in */ + value, /* in */ + &id); /* out */ + } + if (status != NC_NOERR) handle_netcdf_error(status); + } + return TRUE; +} + + +/*-------------------------------------------------------------------------- + * This routine creates a netCDF dimension(s) from a variable. + *--------------------------------------------------------------------------*/ +void create_netcdf_dimensions_variable (CDFvar var, long varNum, + int *createUnlimitedDim, + int *unlimitedDimId) +{ + int status, /* netCDF status code */ + i, j, dimensionCreated, id; + long dimensionality; + char netcdfDimName[NC_MAX_NAME+1]; /* netCDF dimension name */ + CDFstatus statusC; + + dimensionality = var.dimensionality; + + if (var.datatype == CDF_CHAR) { + var.dimSizes[dimensionality] = var.numElements; + dimensionality++; + } + else if (var.datatype == CDF_EPOCH) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + else if (var.datatype == CDF_EPOCH16) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + else if (var.datatype == CDF_TIME_TT2000) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + + if (*createUnlimitedDim) { + if (var.recVariance == VARY) { + status = nc_def_dim(ncid, "Time", NC_UNLIMITED,unlimitedDimId); + if (status != NC_NOERR) handle_netcdf_error(status); + *createUnlimitedDim = FALSE; + } + } + for (i=0; i < dimensionality; i++) { + dimensionCreated = FALSE; + for (j=0; j < totNCdims; j++) { + if (ncDims[j].size == var.dimSizes[i]) { + dimensionCreated = TRUE; + break; + } + } + if (!dimensionCreated && var.dimSizes[i] > 1) { + ncDims[totNCdims].size = var.dimSizes[i]; + sprintf (netcdfDimName, "dim%d", totNCdims); + strcpy(ncDims[totNCdims].name, netcdfDimName); + status = nc_def_dim(ncid, /* in */ + ncDims[totNCdims].name, /* in */ + ncDims[totNCdims].size, /* in */ + &ncDims[totNCdims].id); /* out */ + if (status != NC_NOERR) handle_netcdf_error(status); + totNCdims++; + } + } +} + + +/*-------------------------------------------------------------------------- + * This routine creates a netCDF variable. + *--------------------------------------------------------------------------*/ +int create_netcdf_variable (CDFvar var, /* in - CDF variable */ + long varNum, /* in - CDF variable id */ + int unlimitedDimId) /* in - unlimited dim ID */ +{ + int status, /* netCDF status code */ + i, j, k, id, + varId, /* netCDF variable ID */ + nc_dimensionality, + dimensionality, /* netCDF dimensionality */ + dims[NC_MAX_DIMS]; /* netCDF dimensions */ + nc_type datatype; + char *entry; + char **dimStrings; + int count = 0; + long numElems; + CDFstatus statusC; + + dimensionality = var.dimensionality; + datatype = get_netcdf_datatype (var.datatype); + + /********************************************************************* + * While the string value is treated as 0-d in CDF, it is treated as + * 1-D in netCDF. + *********************************************************************/ + if (var.datatype == CDF_CHAR) { + var.dimSizes[dimensionality] = var.numElements; + dimensionality++; + } + + /********************************************************************* + * In CDF, CDF_EPOCH, CDF_EPOCH16 and CDF_TIME_TT2000 are used to + * store a date and time value into a 8-byte real, 16-byte real or + * 8-byte integer value, respectively. Since netCDF + * doesn't support EPOCH, the CDF EPOCH variable needs to be translated + * as a string value. + *********************************************************************/ + else if (var.datatype == CDF_EPOCH) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + else if (var.datatype == CDF_EPOCH16) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + else if (var.datatype == CDF_TIME_TT2000) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + + /************************************************************************ + * If CDF's record variance is true, then the netCDF's first dimension + * reflects the record number. + ************************************************************************/ + k = 0; + if (var.recVariance == VARY) { + dims[k++] = unlimitedDimId; + dimensionality++; + } + + entry = (char *) malloc ((size_t) (dimensionality+1) * NC_MAX_NAME + + dimensionality + 1 ); + statusC = CDFlib (SELECT_, ATTR_NAME_, "DIMENSIONS_V", + zENTRY_, varNum, + GET_, zENTRY_DATA_, entry, + zENTRY_NUMELEMS_, &numElems, + NULL_); + if (statusC == CDF_OK) { /* A CDF converted from netCDF-to-cdf. */ + entry[numElems] = (char) '\0'; + for (i = 0; i < strlen(entry); ++i) if (entry[i] == (char) ',') ++ count; + ++count; + dimStrings = (char **) malloc (sizeof(char *) * count); + for (i = 0; i < count; ++i) { + dimStrings[i] = (char *) malloc(NC_MAX_NAME + 1); + } + breakdown_DIMENSIONS_entry(entry, dimStrings); + k = 0; + for (j = 0; j < count; ++j) { + status = nc_inq_dimid(ncid, dimStrings[j], &id); + if (status != NC_NOERR) handle_netcdf_error(status); + dims[k++] = id; + } + for (i = 0; i < count; ++i) free (dimStrings[i]); + free (dimStrings); + } else { + for (i=0; i < dimensionality; i++) { + for (j=0; j < totNCdims; j++) { + if (ncDims[j].size == var.dimSizes[i]) { + dims[k++] = ncDims[j].id; + break; + } + } + } + } + free (entry); + /* Remove trailing blank spaces if there are any */ + for (i=strlen(var.name)-1; i >= 0; i--) { + if (var.name[i] != ' ') { + var.name[i+1] = '\0'; + break; + } + } + + /* Replace blank space(s) with underscore(s). */ + for (i=0; i < strlen(var.name); i++) { + if (var.name[i] == ' ') var.name[i] = '_'; + } + +/* Exclude "false" dimension */ + nc_dimensionality = dimensionality; +// for (i=0; i < dimensionality; i++) { +// if ( var.dimSizes[i] == 1 ) { +// nc_dimensionality--; +// j = i; +// break; +// } +// } + + /* Create a netCDF variable. */ + status = nc_def_var(ncid, var.name, datatype, nc_dimensionality, dims, &varId); + if (status != NC_NOERR) handle_netcdf_error(status); + return varId; +} + + +/*-------------------------------------------------------------------------- + * Get the CDF variable data and write the data just read into the + * netCDF variable created in create_netcdf_variable. + *--------------------------------------------------------------------------*/ +void get_cdf_variable_data (long varId, /* in - variable ID/number */ + CDFvar var, /* in - CDF variable structure */ + long ncVarId) /* in - netCDF variable ID/number */ +{ + CDFstatus status; /* CDF status code */ + int ncstatus; /* netCDF status code */ + char epString[EPOCH4_STRING_LEN+1]; + char ep16String[EPOCH16_4_STRING_LEN+1]; + char tt2000String[TT2000_3_STRING_LEN+1]; + double epoch16[2]; + + size_t start[NC_MAX_DIMS], /* index for where to read first */ + count[NC_MAX_DIMS]; /* # of values to read */ + + int i, j, k, divide, + dimensionality, + numValues; /* # of values on each record */ +char * ptr; + char *cPtr; + signed char *scPtr; + unsigned char *ucPtr; + short *sPtr; + unsigned short *usPtr; + int *iPtr; + unsigned int *uiPtr; + long long *jPtr, aLonglong; + float *fPtr; + double *dPtr; + long recNo, + totRecs, /* total # of records to read */ + numRecsLeftToRead, + numRecs; /* # of records to read and write at a time */ + + j = 0; + start[0] = 0; + numValues = 1; /* # of values on each CDF record */ + + if (var.recVariance == VARY) { /* Treat it as a netCDF record variable */ + start[j] = 0; /* start record # */ + count[j++] = var.numRecs; /* # of records to write */ + } + + dimensionality = var.dimensionality; + + if (var.datatype == CDF_CHAR) { + var.dimSizes[dimensionality] = var.numElements; + dimensionality++; + } + + /********************************************************************* + * In CDF, CDF_EPOCH and CDF_EPOCH16 are used to store a date and time + * value into a 8-byte and 16-byte real value, respectively. Since netCDF + * doesn't support EPOCH, the CDF EPOCH variable needs to be translated + * as a string value. Added newer 8-byte integer CDF_TIME_TT2000 data. + *********************************************************************/ + else if (var.datatype == CDF_EPOCH) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + else if (var.datatype == CDF_EPOCH16) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + else if (var.datatype == CDF_TIME_TT2000) { + var.dimSizes[dimensionality] = DD_TIME_STRING_LEN; + dimensionality++; + } + + for (i=0; i < dimensionality; i++) { + start[j] = 0; + if (var.dimSizes[i] > 1) count[j++] = var.dimSizes[i]; + numValues *= var.dimSizes[i]; + } + + if (var.datatype == CDF_EPOCH) + numValues /= DD_TIME_STRING_LEN; + else if (var.datatype == CDF_EPOCH16) + numValues /= DD_TIME_STRING_LEN; + else if (var.datatype == CDF_TIME_TT2000) + numValues /= DD_TIME_STRING_LEN; + + totRecs = var.numRecs; /* total # of records for this var */ + numRecsLeftToRead = var.numRecs; + + while (numRecsLeftToRead > 0) { + recNo = start[0]; /* record # to start reading */ + divide = 1; + numRecs = numRecsLeftToRead; /* # of records to read at a time */ + + switch (var.datatype) { + case CDF_CHAR: + case CDF_UCHAR: + cPtr = NULL; + while (cPtr == NULL) { + cPtr = (char *) malloc (sizeof(char) * numValues * numRecs); + if (cPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + cPtr); /* data pointer */ + if (DEBUG) { + printf (" retrieved CDF data = \n"); + for (k=0; k < numRecs; k++) { + printf("\""); + for (i=0; i < numValues; i++) + printf ("%c", *(cPtr+(k*numValues+i))); + printf("\"\n"); + } + } + + start[0] = 0; + start[1] = 0; + if (var.recVariance == VARY) { + count[0] = numRecs; + } + + if (DEBUG) { + for (i=0; i < dimensionality; i++) + printf (" start[%d] = %ld, count[%d] = %ld\n", + i, start[i], i, count[i]); + } + ncstatus = nc_put_vara_text(ncid, ncVarId, start, count, cPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + if (DEBUG && ncstatus != NC_NOERR) { + if (ncstatus != NC_NOERR) + printf (" Error putting data...\n"); + else + printf (" Done putting data...\n"); + } + free (cPtr); + break; + + case CDF_BYTE: + case CDF_INT1: + scPtr = NULL; + while (scPtr == NULL) { + scPtr = + (signed char *) malloc (sizeof(signed char)*numValues*numRecs); + if (scPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + scPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + ncstatus = nc_put_vara_schar(ncid, ncVarId, start, count, scPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (scPtr); + break; + + case CDF_UINT1: + ucPtr = NULL; + sPtr = NULL; + while (ucPtr == NULL || sPtr == NULL) { + ucPtr = + (unsigned char *) malloc (sizeof(unsigned char)*numValues*numRecs); + sPtr = + (short *) malloc (sizeof(short)*numValues*numRecs); + if (ucPtr == NULL || sPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + ucPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + for (j = 0; j < numValues*numRecs; ++j) { + *(sPtr+j) = (short) *(ucPtr+j); + } + ncstatus = nc_put_vara_short(ncid, ncVarId, start, count, sPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (ucPtr); + free (sPtr); + break; + + case CDF_INT2: + sPtr = NULL; + while (sPtr == NULL) { + sPtr = (short *) malloc (sizeof(short) * numValues * numRecs); + if (sPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + sPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + ncstatus = nc_put_vara_short(ncid, ncVarId, start, count, sPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (sPtr); + break; + + case CDF_UINT2: + usPtr = NULL; + iPtr = NULL; + while (usPtr == NULL || iPtr == NULL) { + usPtr = (unsigned short *) malloc (sizeof(unsigned short) * numValues * numRecs); + iPtr = (int *) malloc (sizeof(int) * numValues * numRecs); + if (usPtr == NULL || iPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + usPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + for (j = 0; j < numValues*numRecs; ++j) { + *(iPtr+j) = (int) *(usPtr+j); + } + ncstatus = nc_put_vara_int(ncid, ncVarId, start, count, iPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (usPtr); + free (iPtr); + break; + + case CDF_INT4: + iPtr = NULL; + while (iPtr == NULL) { + iPtr = (int *) malloc (sizeof(int) * numValues * numRecs); + if (iPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + iPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + ncstatus = nc_put_vara_int(ncid, ncVarId, start, count, iPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (iPtr); + break; + + case CDF_UINT4: + uiPtr = NULL; + dPtr = NULL; + while (uiPtr == NULL || dPtr == NULL) { + uiPtr = (unsigned int *) malloc (sizeof(unsigned int) * numValues * numRecs); + dPtr = (double *) malloc (sizeof(double) * numValues * numRecs); + if (iPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + uiPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + for (j = 0; j < numValues*numRecs; ++j) { + *(dPtr+j) = (double) *(uiPtr+j); + } + ncstatus = nc_put_vara_double(ncid, ncVarId, start, count, dPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (uiPtr); + free (dPtr); + break; + + case CDF_INT8: + jPtr = NULL; + dPtr = NULL; + while (jPtr == NULL || dPtr == NULL) { + jPtr = (long long *) malloc (sizeof(long long) * numValues * numRecs); + dPtr = (double *) malloc (sizeof(double) * numValues * numRecs); + if (jPtr == NULL || dPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + jPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + for (j = 0; j < numValues*numRecs; ++j) { + *(dPtr+j) = (double) *(jPtr+j); + } + ncstatus = nc_put_vara_double(ncid, ncVarId, start, count, dPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (jPtr); + free (dPtr); + break; + + case CDF_FLOAT: + case CDF_REAL4: + fPtr = NULL; + while (fPtr == NULL) { + fPtr = (float *) malloc (sizeof(float) * numValues * numRecs); + if (fPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + fPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + ncstatus = nc_put_vara_float(ncid, ncVarId, start, count, fPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (fPtr); + break; + + case CDF_DOUBLE: + case CDF_REAL8: + dPtr = NULL; + while (dPtr == NULL) { + dPtr = (double *) malloc (sizeof(double) * numValues * numRecs); + if (dPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + dPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + + ncstatus = nc_put_vara_double(ncid, ncVarId, start, count, dPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (dPtr); + break; + + case CDF_EPOCH: + dPtr = NULL; + while (dPtr == NULL) { + dPtr = (double *) malloc (sizeof(double)*numValues*numRecs); + if (dPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + dPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + + cPtr = (char *) malloc (sizeof(char) * numValues * numRecs * + DD_TIME_STRING_LEN + 1); + if (cPtr == NULL) + memory_error("get_cdf_variable_data", "CDF_EPOCH"); + + ptr = cPtr; + + /* Get all the EPOCH values into a single string. */ + for (i=0; i < numRecs * numValues; i++) { + encodeEPOCH4 (*(dPtr+i), epString); + strcpy (ptr, isotime_to_dd_time (epString)); + ptr += DD_TIME_STRING_LEN; + } + ncstatus = nc_put_vara_text(ncid, ncVarId, start, count, cPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (cPtr); + free (dPtr); + break; + + case CDF_EPOCH16: + dPtr = NULL; + while (dPtr == NULL) { + dPtr = (double *) malloc (sizeof(double) * numValues*numRecs*2); + if (dPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + dPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + + cPtr = (char *) malloc (sizeof(char) * numValues * numRecs * + DD_TIME_STRING_LEN + 1); + if (cPtr == NULL) + memory_error("get_cdf_variable_data", "CDF_EPOCH16"); + + ptr = cPtr; + + /* Get all the EPOCH16 values into a single string. */ + for (i=0; i < numRecs * numValues; i++) { + epoch16[0] = *(dPtr+i*2); + epoch16[1] = *(dPtr+i*2+1); + encodeEPOCH16_4 (epoch16, ep16String); + strcpy (ptr, isotime_to_dd_time (ep16String)); + ptr += DD_TIME_STRING_LEN; + } + printf(" %d %d\n", count[0], count[1]); + ncstatus = nc_put_vara_text(ncid, ncVarId, start, count, cPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (cPtr); + free (dPtr); + break; + + case CDF_TIME_TT2000: + jPtr = NULL; + while (jPtr == NULL) { + jPtr = (long long *) malloc (sizeof(long long)*numValues*numRecs); + if (jPtr == NULL) { + if (DEBUG) insufficient_memory(); + divide *= 2; + numRecs = totRecs / divide; + } + } + read_cdf_variable_data (varId, + recNo, /* starting record # */ + numRecs, /* # of records to read */ + var.dimensionality, + var.dimSizes, /* dimesion sizes */ + jPtr); /* data pointer */ + if (var.recVariance == VARY) + count[0] = numRecs; + + cPtr = (char *) malloc (sizeof(char) * numValues * numRecs * + DD_TIME_STRING_LEN + 1); + if (cPtr == NULL) + memory_error("get_cdf_variable_data", "CDF_EPOCH"); + + ptr = cPtr; + + /* Get all the TT2000 values into a single string. */ + for (i=0; i < numRecs * numValues; i++) { + // encodeTT2000 (*(jPtr+i), tt2000String); + CDF_TT2000_to_UTC_string(*(jPtr+i), tt2000String, 3); + strcpy (ptr, isotime_to_dd_time (tt2000String)); + ptr += DD_TIME_STRING_LEN; + } + ncstatus = nc_put_vara_text(ncid, ncVarId, start, count, cPtr); + if (ncstatus != NC_NOERR) handle_netcdf_error(ncstatus); + free (cPtr); + free (jPtr); + break; + + default: + printf ("** Error in getVarData: bad type"); + } + + numRecsLeftToRead = totRecs - numRecs; + if (numRecsLeftToRead > 0) { + totRecs = numRecsLeftToRead; + start[0] = numRecs; + } + } /* end of the 'while' loop */ + +} + + +/*-------------------------------------------------------------------------- + * This routine returns the string representation of the given CDF + * datatype. + *--------------------------------------------------------------------------*/ +char * cdf_str_datatype (long type) +{ + switch (type) { + case CDF_BYTE: + return "CDF_BYTE"; + + case CDF_INT1: + return "CDF_INT1"; + + case CDF_CHAR: + return "CDF_CHAR"; + + case CDF_INT2: + return "CDF_INT2"; + + case CDF_UCHAR: + return "CDF_UCHAR"; + + case CDF_UINT1: + return "CDF_UINT1"; + + case CDF_INT4: + return "CDF_INT4"; + + case CDF_INT8: + return "CDF_INT8"; + + case CDF_UINT2: + return "CDF_UINT2"; + + case CDF_FLOAT: + return "CDF_FLOAT"; + + case CDF_REAL4: + return "CDF_REAL4"; + + case CDF_DOUBLE: + return "CDF_DOUBLE"; + + case CDF_REAL8: + return "CDF_REAL8"; + + case CDF_UINT4: + return "CDF_UINT4"; + + case CDF_EPOCH: + return "CDF_EPOCH"; + + case CDF_EPOCH16: + return "CDF_EPOCH16"; + + case CDF_TIME_TT2000: + return "CDF_TIME_TT2000"; + + default: + return "BAD_CDF_TYPE"; + + } +} + + +/*-------------------------------------------------------------------------- + * This routine returns the string representation of the given netCDF + * datatype. + *--------------------------------------------------------------------------*/ +char * NC_datatype (nc_type type) +{ + switch (type) { + case NC_BYTE: + return "byte"; + case NC_CHAR: + return "char"; + case NC_SHORT: + return "short"; + case NC_INT: + return "int"; + case NC_FLOAT: + return "float"; + case NC_DOUBLE: + return "double"; + default: + return "UNKNOWN"; + } +} + + +/*-------------------------------------------------------------------------- + * This routine returns the netCDF datatype for the given CDF datatype. + * All unsigned types are bumped up, either to double the size, or to + * a double. CDF's epoch types are converted to string. + *--------------------------------------------------------------------------*/ +nc_type get_netcdf_datatype (long type) +{ + nc_type netcdf_type; + + switch (type) { + case CDF_BYTE: + case CDF_INT1: + netcdf_type = NC_BYTE; + break; + + case CDF_CHAR: + case CDF_UCHAR: + case CDF_EPOCH: + case CDF_EPOCH16: + case CDF_TIME_TT2000: + netcdf_type = NC_CHAR; + break; + + case CDF_UINT1: + netcdf_type = NC_SHORT; + break; + + case CDF_INT2: + netcdf_type = NC_SHORT; + break; + + case CDF_UINT2: + netcdf_type = NC_INT; + break; + + case CDF_INT4: + netcdf_type = NC_INT; + break; + + case CDF_UINT4: + netcdf_type = NC_DOUBLE; + break; + + case CDF_INT8: + netcdf_type = NC_DOUBLE; + break; + + case CDF_FLOAT: + case CDF_REAL4: + netcdf_type = NC_FLOAT; + break; + + case CDF_DOUBLE: + case CDF_REAL8: + netcdf_type = NC_DOUBLE; + break; + + default: { + printf ("** ERROR: Unknown CDF datatype\n"); + exit (1); + } + } + return netcdf_type; +} + + +/*--------------------------------------------------------------------------- + * Read the CDF variable data for the given CDF variable number. + *---------------------------------------------------------------------------*/ +void read_cdf_variable_data (long varNum, /* CDF variable number */ + long recNo, /* record # for start reading */ + long recCount, /* # of records to read */ + long dim, /* CDF dimensionality */ + long dimSizes[], /* CDF dimesion sizes */ + void *data) /* data pointer */ +{ + CDFstatus status; + int i; + long recInterval, /* No. of recors to skip */ + dimIndices[CDF_MAX_DIMS], /* Beginning location of the array */ + /* to be dumped */ + dimIntervals[CDF_MAX_DIMS]; /* No. of elements to skip */ + + recInterval = 1L; /* # of records to skip between writes */ + + for (i=0; i < dim; i++) { + dimIndices[i] = 0; /* Dump data from the beginning of array */ + dimIntervals[i] = 1; /* Dump all the elements in the array */ + } + + status = CDFlib (SELECT_,zVAR_, varNum, + zVAR_RECNUMBER_, recNo, + zVAR_RECCOUNT_, recCount, + zVAR_RECINTERVAL_, recInterval, + zVAR_DIMINDICES_, dimIndices, + zVAR_DIMCOUNTS_, dimSizes, + zVAR_DIMINTERVALS_, dimIntervals, + GET_, zVAR_HYPERDATA_, data, + NULL_); + if (status != CDF_OK) cdf_status_handler (status, "GET_, zVAR_HYPERDATA_"); +} + + + +/*-------------------------------------------------------------------------- + * Remove the filepath from a file name. + * + * Example: + * /home/data/mydata.txt => mydata.txt + *--------------------------------------------------------------------------*/ +void removeFilepath (char *fileName) { + char *ptr; + + ptr = (char *) strrchr(fileName, '/'); /* Unix file path separator */ + if (ptr != NULL) { + ptr++; + strcpy(fileName, ptr); + } + else { + ptr = (char *) strrchr(fileName, '\\'); /* Windows file separator */ + if (ptr != NULL) { + ptr++; + strcpy(fileName, ptr); + } + } +} + + +/*-------------------------------------------------------------------------- + * Handles a CDF error. + *--------------------------------------------------------------------------*/ +void cdf_status_handler (CDFstatus status, char *source) +{ + char message[CDF_STATUSTEXT_LEN+1]; + + CDFerror (status, message); /* Get the appropriate message */ + + if (status < CDF_WARN) { + printf ("An error has occurred, halting...\n"); + printf ("%s\n", message); + printf ("** Error source: %s\n", source); + exit (status); + } + else if (status < CDF_OK) { + printf ("Warning, function may not have compeleted as expected...\n"); + printf ("%s\n", message); + } + else if (status > CDF_OK) { + printf ("Function compeleted successfully, but be advised that...\n"); + printf ("%s\n", message); + } +} + + +/*-------------------------------------------------------------------------- + * Handles a netCDF error. + *--------------------------------------------------------------------------*/ +void handle_netcdf_error(int status) { + fprintf(stderr, "%s\n", nc_strerror(status)); +} + + +/*-------------------------------------------------------------------------- + * Handles a memory allocation error. + *--------------------------------------------------------------------------*/ +void memory_error(char *source, char *datatype) { + printf ("** Memory allocation error occurred in %s. data type = %s", + source, datatype); + exit (1); +} + +void insufficient_memory () { + printf("Insufficient memory to load all the records at once"); +} + + +/*--------------------------------------------------------------------------*/ +void usage() +{ + printf ("\nDescription:\n"); + printf (" This program converts a CDF file into a netCDF file."); + printf ("\n"); + printf ("Usage: cdf-to-netCDF -[Options] <CDF file name>\n"); + printf ("\n"); + printf ("Options:\n"); + printf (" -map <mapfile> Use the user-supplied mapping file.\n"); + printf (" -debug Show debug information.\n"); + printf ("\n"); + printf ("Examples of usage: \n"); + printf ("1) cdf-to-netCDF test.cdf\n"); + printf (" will convert the test.cdf file into the test.nc file.\n\n"); + printf ("2) cdf-to-netCDF -map mymap.dat test.cdf\n"); + printf (" will convert the test.cdf file into the test.nc file using\n"); + printf (" the user-supplied mapping file called 'mymap.dat' instead\n"); + printf (" of using the default cdf-to-netCDF mapping file.\n"); + printf ("\n"); + exit(1); +} + +void parseCmdLine (int argc, char *argv[]) +{ + int i; + char *nextArg; + + for (i=0; i < argc; i++) { + if (strcmp(argv[i],"-map") == 0) { + nextArg = getNextArgument(argc, argv, i); + if (strcmp(nextArg, "No next argument") == 0 || + *(nextArg+0) == '-') + errorMsg("** Error - mapping file is not defined"); + else + strcpy(mappingFile, nextArg); + } + else if (strcmp(argv[i],"-debug") == 0) + DEBUG = TRUE; + } +} + + +char * getNextArgument (int argc, char *argv[], int currentIndex) +{ + char *nextArg, msg[30]; + int nextIndex; + + nextIndex = currentIndex+1; + if (nextIndex == argc) { + strcpy (msg, "No next argument"); + nextArg = msg; + } + else + nextArg = argv[nextIndex]; + + return nextArg; +} + +void errorMsg (char *msg) +{ + printf ("%s\n", msg); + exit (1); +} + + +void map_CDF_attr_to_netCDF (char *searchAttr, /* in - CDF attr name */ + char *mappedAttrName) /* out - netCDF attr name */ +{ + int i; + + strcpy(mappedAttrName, searchAttr); + + for (i=0; i < totAttrsInMappingFile; i++) { + if (strcmp(cdfAttrNames[i], searchAttr) == 0) { + strcpy(mappedAttrName, netcdfAttrNames[i]); + break; + } + } +} + +void breakdown_DIMENSIONS_entry (char *entry, /* in - a DIMENSIONS entry */ + char **dimStrings) /* out - dimesion names */ +{ + char *ptr, *ptr1; + int i = 0, j; + + ptr = entry; + ptr1 = strstr(ptr, ","); + i = 0; + while (ptr1 != NULL) { + j = ptr1 - ptr; + strncpy (dimStrings[i], ptr, (size_t)j); + dimStrings[i][j] = (char) '\0'; + ptr = ptr1 + 1; + ptr1 = strstr(ptr, ","); + ++i; + } + if (ptr != NULL) strcpy (dimStrings[i], ptr); +} + diff --git a/src/DECODERS/cdfnew2nc/tools.c b/src/DECODERS/cdfnew2nc/tools.c new file mode 100644 index 0000000..e210587 --- /dev/null +++ b/src/DECODERS/cdfnew2nc/tools.c @@ -0,0 +1,391 @@ +/******************************************************************************* + * + * tools.c - 2014/01/29 + * + * Some specific functions requiered for AMDA converter + * + */ +#include <stdio.h> +#include <string.h> + +#include "tools.h" +#include "netcdf.h" +#include "cdf.h" + +#ifndef TRUE +#define TRUE 1 +#define FALSE (! TRUE) +#endif + +#define VERSION_MIN "3.4.0" + +#define START_TIME "StartTime" +#define STOP_TIME "StopTime" +#define TIME_VAR "Time" + +extern CDFid id; /* CDF file identifier */ + +extern int ncid; /* netCDF file identifier */ + +extern long nZvars; /* Number of CDF zVariables */ + +/******************************************************************************* + * + * Check version of CDFlib greated or equal to 3.5 (needed for TT2000) + */ +int check_version (void) +{ + long version, release, increment; + char subincrement; + int status; + char str_version [30]; + + status = CDFgetLibraryVersion (& version, & release, & increment, & subincrement); + + if (status < CDF_OK) { + + printf ("ERROR : unable to get CDFlib version\n"); + goto EXIT; + } + + sprintf (str_version, "%d.%d.%d-%c", version, release, increment, subincrement); + + printf ("CDFlib version : %s\n", str_version); + + if (strcmp (str_version, VERSION_MIN) < 0) { + + printf ("ERROR : version %s < %s", str_version, VERSION_MIN); + } + +EXIT: return status; +} + + + +/******************************************************************************* + * + * Check if the given year is a leap one + */ +int leap_year (int year) +{ + if ((year % 400) == 0) return TRUE; + if ((year % 100) == 0) return FALSE; + if ((year % 4) == 0) return TRUE; + return FALSE; +} + + +/******************************************************************************* + * + * Convert an ISO 8601 date time to a DD Time string + */ +char * isotime_to_dd_time (char * input) +{ + static char output [DD_TIME_STRING_LEN + 1]; + int i, count, ddd; + int yy, mm, dd, h, m, s, ms; + int duration[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + count = sscanf (input, "%d-%d-%dT%d:%d:%d.%3d", & yy, & mm, & dd, & h, & m, & s, &ms); + + if (count != 7) { + printf ("Unexpected time format: %s\n", input); + strcpy (output, "ERROR "); + goto EXIT; + } + + if (leap_year (yy)) duration [2] = 29; + + ddd = dd - 1; /* Jan-01 : 0 => ddd in [0, 366[ */ + + for (i = 1; i < mm; i++) ddd += duration [i]; + + sprintf (output, "%04.4d%03.3d%02.2d%02.2d%02.2d%03.3d", + yy, ddd, h, m, s, ms); + +EXIT: return output; +} + + +/******************************************************************************* + * + * Parse variables metadata to define time variable ID : + * + * ID of a variable that appears in DEPEND_0 attribute of other variables + */ +char * get_time_variable() +{ + long timeVarId = -1; + long varId; + CDFstatus status; + long attrNum = CDFgetAttrNum (id, "DEPEND_0"); + char * timeVarName = NULL; + + if (attrNum < CDF_OK) { + printf ("ERROR : no DEPEND_0 attribute\n"); + attrNum = CDFgetAttrNum (id, "Depend_0"); + if (attrNum < CDF_OK) { + printf ("ERROR : no Depend_0 attribute\n"); + goto EXIT; + } + } + + for (varId = 0; varId < nZvars; varId++) { + + char name [CDF_VAR_NAME_LEN256+1]; + long dataType; + long numElems; + char buffer [CDF_VAR_NAME_LEN256+1]; + + status = CDFgetzVarName (id, varId, name); + + if (status != CDF_OK) + cdf_status_handler (status, "Get var name"); + + status = CDFinquireAttrzEntry (id, attrNum, varId, & dataType, & numElems); + + if (status == NO_SUCH_ENTRY) continue; + + if (status != CDF_OK) + cdf_status_handler (status, "Get DEPEND_0"); + else { + if (dataType == CDF_CHAR) { + + status = CDFgetAttrzEntry (id, attrNum, varId, buffer); + buffer [numElems] = 0; + + if (timeVarName == NULL) { + timeVarName = strdup (buffer); + } + else if (strcmp (timeVarName, buffer) != 0) { + + printf ("WARNING : Search time variable conflict between %s and %s\n %s is taken as Time\n", + timeVarName, + buffer, + timeVarName); + // EB: select the first time variable + // timeVarName = NULL; + // goto EXIT; + } + } + } + } + + if (timeVarName != NULL) + printf ("Identified time variable : %s\n", timeVarName); + +EXIT: return timeVarName; +} + + +/******************************************************************************* + * + * Compute time coverage (DD_TIME strings) of a currently opened CDF file + */ +int get_file_coverage (char * start_coverage, char * stop_coverage) +{ + int error = -1; + long varId = -1; + CDFstatus status; + char varName [CDF_VAR_NAME_LEN256+1]; + long dataType, numElems, numDims, recVary, numRecs; + long dimSizes [CDF_MAX_DIMS]; + long dimVarys [CDF_MAX_DIMS]; + long indices [CDF_MAX_DIMS]; + double d_buffer [2]; + long long l_buffer [2]; + char * timeVar = NULL; + char str1 [EPOCH16_4_STRING_LEN+1]; + char str2 [EPOCH16_4_STRING_LEN+1]; + + strcpy (start_coverage, ""); + strcpy (stop_coverage, ""); + + timeVar = get_time_variable (); + + if (timeVar == NULL) { + printf ("Error : no time variable identified\n"); + goto EXIT; + } + + varId = CDFvarNum (id, timeVar); + + if (varId == -1) { + + printf ("Error : no time variable identified\n"); + goto EXIT; + } + + status = CDFinquirezVar (id, varId, + varName, + & dataType, + & numElems, + & numDims, + dimSizes, + & recVary, + dimVarys); + + if (status != CDF_OK) cdf_status_handler (status, "CDF inquire zVar"); + + if (recVary != VARY) { + printf ("ERROR : variable %s not record varying\n", varName); + goto EXIT; + } + + if (numDims > 1) { + printf ("Error : variable %s numDims > 1\n", varName); + goto EXIT; + } + + status = CDFgetzVarNumRecsWritten (id, varId, & numRecs); + + if (status != CDF_OK) cdf_status_handler (status, "CDF get zVar num recs"); + + indices [0] = 0; + indices [1] = 0; + indices [3] = 0; + + switch (dataType) { + + case CDF_EPOCH: + + status = CDFgetzVarData (id, varId, 0L, indices, d_buffer); + + encodeEPOCH4 (d_buffer [0], str1); + + status = CDFgetzVarData (id, varId, numRecs -1, indices, d_buffer); + + encodeEPOCH4 (d_buffer [0], str2); + + break; + + case CDF_EPOCH16: + + status = CDFgetzVarData (id, varId, 0L, indices, d_buffer); + + encodeEPOCH16_4 (d_buffer, str1); + + status = CDFgetzVarData (id, varId, numRecs -1, indices, d_buffer); + + encodeEPOCH16_4 (d_buffer, str2); + + break; + + case CDF_TIME_TT2000: + + status = CDFgetzVarData (id, varId, 0L, indices, l_buffer); + + encodeTT2000 (l_buffer [0], str1, 3); + + status = CDFgetzVarData (id, varId, numRecs -1, indices, l_buffer); + + encodeTT2000 (l_buffer [0], str2, 3); + + break; + default: + printf ("Error : variable %d is not a Time variable\n"); + goto EXIT; + } + + strcpy (start_coverage, isotime_to_dd_time (str1)); + strcpy (stop_coverage, isotime_to_dd_time (str2)); + error = 0; + +EXIT: return error; +} + + +#define NDIM 2 + +/******************************************************************************* + * + * Set file time coverage metadata + */ +int set_file_time_coverage () +{ + int error = 0; + char start_time [DD_TIME_STRING_LEN + 1]; + char stop_time [DD_TIME_STRING_LEN + 1]; + int time_dim; + int start_id, stop_id; + int nc_status = NC_NOERR; + size_t start [NDIM]; + size_t count [NDIM]; + + error = get_file_coverage (start_time, stop_time); + + if (error != 0) goto EXIT; + + printf ("CDF time coverage : %s - %s\n", start_time, stop_time); + + nc_status = nc_def_dim (ncid, "TimeLength", DD_TIME_STRING_LEN, & time_dim); + + if (nc_status != NC_NOERR) goto EXIT; + + nc_status = nc_def_var (ncid, START_TIME, NC_CHAR, 1, & time_dim, & start_id); + + if (nc_status != NC_NOERR) goto EXIT; + + nc_status = nc_def_var (ncid, STOP_TIME, NC_CHAR, 1, & time_dim, & stop_id); + + if (nc_status != NC_NOERR) goto EXIT; + + start [0] = 0; + count [0] = DD_TIME_STRING_LEN; + + nc_enddef (ncid); + + nc_status = nc_put_vara_text (ncid, start_id, start, count, start_time); + + if (nc_status != NC_NOERR) goto EXIT; + + nc_status = nc_put_vara_text (ncid, stop_id, start, count, stop_time); + + if (nc_status != NC_NOERR) goto EXIT; + +EXIT: printf ("NC status = %d\n", nc_status); + return error; +} + + +/******************************************************************************* + * + * Rename time_variable to "Time" (necessary for AMDA DD server usage) + */ +int rename_time_variable () +{ + int error = -1; + char * timeVar = NULL; + int varId; + int nc_status; + + timeVar = get_time_variable (); + + if (timeVar == NULL) { + + printf ("ERROR : no time variable identified\n"); + goto EXIT; + } + + nc_status = nc_redef (ncid); + + if (nc_status != NC_NOERR) goto EXIT; + + nc_status = nc_inq_varid (ncid, timeVar, & varId); + + if (nc_status != NC_NOERR) goto EXIT; + + nc_status = nc_rename_var (ncid, varId, TIME_VAR); + + if (nc_status != NC_NOERR) goto EXIT; + + nc_status = nc_enddef (ncid); + + if (nc_status != NC_NOERR) goto EXIT; + + error = 0; + +EXIT: return error; + +} + diff --git a/src/DECODERS/cdfnew2nc/tools.h b/src/DECODERS/cdfnew2nc/tools.h new file mode 100644 index 0000000..aecc5cd --- /dev/null +++ b/src/DECODERS/cdfnew2nc/tools.h @@ -0,0 +1,10 @@ +#ifndef TOOLS_H +#define TOOLS_H + +#define DD_TIME_STRING_LEN 17 + +int set_file_time_coverage (); + +char * isotime_to_dd_time (char * str_isotime); + +#endif -- libgit2 0.21.2