#include #include #include #include #include #include #include "cdf.h" #define MAX_FILE_NAME_LEN 156 /* Max. file name length */ #define MAX_UNITS 500 /* Max # of CDF attributes */ #define UNKNOWN_DT -99 /* Unsupported CDF datatype indicator */ #define DEFAULT_MAPPING_FILE "cdf_to_pds_mapping.dat" #define MAX_REC_LENGTH 256 /* Max record length of DEFAULT_MAPPING_FILE */ #define LONGEST_PDS_KEYWORD "SPACECRAFT_CLOCK_START_COUNT" #define MAX_LABEL_LINE_LENGTH 78 /* 80 - - = 78 */ #define INDENT 6 #define MAX_UNITS_LEN 64 #define MAX_FORMAT_LEN 15 #define MAX_VALIDMIN_LEN EPOCH16_STRING_LEN #define MAX_VALIDMAX_LEN EPOCH16_STRING_LEN #define MAX_VAR_DESCR_LEN 128 #define MAX_VAR_NOTES_LEN 512 #define MAX_VAR_DATATYPE_LEN 15 /***********************************************/ /* PDS catalog file (DATASET.CAT) placeholders */ /***********************************************/ #define PDS_CATALOG_FILE "DATASET.CAT" #define DATA_SET_RELEASE_DATE "2007-03-01" #define ARCHIVE_STATUS "IN PEER REVIEW" #define DETAILED_CATALOG_FLAG "N" #define DATA_SET_TERSE_DESC " " #define CITATION_DESC " " #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 cdfvar { /* CDF variable structure */ char name[CDF_VAR_NAME_LEN+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 written */ long maxRec; /* last record # for this variable */ } CDFvar; /**************************************************************************** * Arrays to hold the CDF-to-PDS mapping information that are loaded * from the default or user-define mapping file. ****************************************************************************/ char pdsUnits[MAX_UNITS][MAX_UNITS_LEN]; char cdfUnits[MAX_UNITS][MAX_UNITS_LEN+1]; int totUnitsInMappingFile; /* # of attributes in the mapping file */ char mappingFile[MAX_FILE_NAME_LEN]; /* Mapping file name */ char dataset_ID[MAX_FILE_NAME_LEN]; /* DATA_SET_ID */ char *pdsKeywords[] = { "PDS_VERSION_ID", "RECORD_TYPE", "MISSION_NAME", "INSTRUMENT_HOST_ID", "INSTRUMENT_HOST_NAME", "INSTRUMENT_ID", "INSTRUMENT_NAME", "DATA_SET_ID", "PRODUCT_ID", "PRODUCT_CREATION_TIME", "SPACECRAFT_CLOCK_START_TIME", "SPACECRAFT_CLOCK_STOP_TIME", "SPACECRAFT_CLOCK_START_COUNT", "SPACECRAFT_CLOCK_STOP_COUNT", "START_TIME", "STOP_TIME", "TARGET_NAME", "^TIFF_DOCUMENT", "OBJECT", "PDS_OBJECT", "TEXT", "PDS_RECORD_TYPE", "PDS_MISSION_NAME", "PDS_INSTRUMENT_HOST_ID", "PDS_INSTRUMENT_HOST_NAME", "PDS_INSTRUMENT_ID", "PDS_INSTRUMENT_NAME", "PDS_DATA_SET_ID", "PDS_PRODUCT_ID", "PDS_PRODUCT_CREATION_TIME", "PDS_SPACECRAFT_CLOCK_START_TIME", "PDS_SPACECRAFT_CLOCK_STOP_TIME", "PDS_SPACECRAFT_CLOCK_START_COUNT", "PDS_SPACECRAFT_CLOCK_STOP_COUNT", "PDS_START_TIME", "PDS_STOP_TIME", "PDS_TARGET_NAME", "PDS_TIFF_DOCUMENT", "PI_name", "Acknowledgement", "Logical_source_description", NULL }; int totPDSKeywords; struct ccig_object { /* unique for the CCIG data */ char name[64]; char docName[256]; char publicationDate[20]; char docTopicType[64]; char interchangeFormat[20]; char docFormat[20]; char description[2000]; }; struct pds_header_struct { char verID[6]; char recType[20]; /* RECORD_TYPE */ char recLength[12]; /* RECORD_BYTE - record length */ char maxRec[12]; /* FILE_RECORDS - # of records */ char rows[12]; /* FILE_RECORDS - # of records */ char tableName[256]; /* PDS ASCII table - data file name */ char missionName[64]; char instrumentHostID[50]; char instrumentHostName[128]; char instrumentID[50]; char instrumentName[128]; char datasetID[128]; char datasetName[128]; char productID[128]; char productIDcomments[64]; char productCreationTime[20]; char scClockStartTime[20]; char scClockStopTime[20]; char startTime[20]; char stopTime[20]; char targetName[64]; char tiffDocument[256]; char PI_name[70]; char acknowledgement[512]; struct ccig_object obj; }; struct pds_header_struct pdsHeader; char **units; /* Array of UNITS variable attribute values */ char **formats; /* Array of FORMAT variable attribute values */ char **fillval; /* Array of FILLVAL variable attribute values */ char **validmin; /* Array of VALIDMIN variable attribute values */ char **validmax; /* Array of VALIDMAX variable attribute values */ char **var_notes; /* Array of VAR_NOTES variable attribute values */ int *formatWidth; int *formatDecimal; long zVarsMaxRec; /* Maximum record number for all zVariables */ /* PDS label for ASCII table columns */ char ** varNames; /* col names */ char ** varDescriptions; /* col descriptions */ char ** varDatatypes; /* col datatypes: TIME, ASCII_INTEGER, ASCII_REAL */ char pdsDataFileName[MAX_FILE_NAME_LEN]; char outputFilename[MAX_FILE_NAME_LEN]; int CCIGdata = FALSE; int determineFormat = FALSE; int instrumentHostNameDefined = FALSE; int maxWidth = 0; int maxDecimal = 0; FILE *labelFile, /* Pointer to the PDS label file */ *dataFile, /* Pointer to the PDS data file */ *catFile; /* Pointer to the PDS catalog file */ int DEBUG = FALSE; int DEBUG1 = FALSE; /* Debug the wrapLongString routine */ /************************** Function prototypes **************************/ int endsWith(char *, char *); char * strlaststr(char *, char *); void get_cdf_attribute(long, long, long, char *); void get_cdf_attr_data(char *, long, long, long, long, char *); int validPDSKeyword (char *attrName); void get_pds_header (char *attrName, void *attrData, long entryNum); char * cdf_str_datatype (long); char * get_pds_ascii_table_datatype (long type); void usage(); CDFid cdf_open(char *); void read_cdf_file_info(); void get_zVariables(); void get_ccig_scan_comments(); void write_pds_data_file_header(); void get_attr_str_value (long varId, char *attrName, char *attrValue); void write_pds_label (); void write_pds_catalog (); void write_pds_keyword (FILE *file, char *keyword, char *value, int longest, char *flag); void write_pds_data (char *varData, long varId, char *flag); void wrapLongString (FILE *file, char *str, int indent, int maxLineLength); void get_cdf_variable_data (long varId, CDFvar var, long recNo); void read_cdf_variable_data (long, long, long, long, long [], void *); void removeFilepath(); void removeFileExtension (char *fileName, char *ext); void removeInavlidPDSfilenameChars (char *fileName); 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_units_to_PDS (char *, char *); void makeUppercase (char *str); void write_blank_line (FILE *file, int nLines); void remove_trailing_blanks (char *str); void get_default_format (CDFvar var, char *format); void fixRealNumber (char *num); int scientificNotation (char *num); void parseFormat (char *format, char *width, char *decimal, int *foundDecimal); /**************************************************************************** NOTE: - 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. *****************************************************************************/ 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 */ char *ptr, attrValue[512], fileName[MAX_FILE_NAME_LEN]; char fileExtension[12]; char pdsLabelFileName[MAX_FILE_NAME_LEN], tmpLabelFileName[MAX_FILE_NAME_LEN], pdsCatalogFileName[MAX_FILE_NAME_LEN], unit[MAX_UNITS_LEN]; CDFstatus status; /* CDF status code */ int i, j, k, leng; long attrId, dummy; /* CDF attribute ID */ if (argc <= 1) usage(); /* CDF input file name not specified */ else { strcpy(fileName, argv[argc-1]); /* Get the input file name */ strcpy(mappingFile, "UNSPECIFIED"); strcpy(outputFilename, "UNSPECIFIED"); strcpy(dataset_ID, "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); } totPDSKeywords = 0; for (i=0; pdsKeywords[i] != NULL ; i++) totPDSKeywords++; /***********************************************/ /* Load the CDF-to-PDS mapping information */ /***********************************************/ totUnitsInMappingFile = 0; if ((inFile = fopen(mappingFile, "r")) != NULL) { if (DEBUG) printf("Units mapping (CDF-to-PDS)\n--------------------------\n"); while (fgets(rec, MAX_REC_LENGTH, inFile) != NULL) { leng = strlen(rec); /* Remove the newline character */ rec[leng-1] = '\0'; leng = strlen(rec); /* Process the mapping record if it's not a comment */ if (rec[0] != '#' && leng > 0) { i = 0; j = 0; while (rec[i] != '"') i++; i++; while (rec[i] != '"') unit[j++] = rec[i++]; unit[j] = '\0'; strcpy (cdfUnits[totUnitsInMappingFile], unit); i++; j = 0; while (rec[i] != '"') i++; i++; while (rec[i] != '"') unit[j++] = rec[i++]; unit[j] = '\0'; strcpy (pdsUnits[totUnitsInMappingFile], unit); if (DEBUG) printf("\"%s\" => \"%s\"\n", cdfUnits[totUnitsInMappingFile], pdsUnits[totUnitsInMappingFile]); totUnitsInMappingFile++; } } } printf ("\n Input file: %s\n", fileName); id = cdf_open (fileName); removeFilepath(fileName); /* /home/mydata.cdf => mydata.cdf */ removeFileExtension (fileName, ".cdf"); removeInavlidPDSfilenameChars (fileName); strcpy (outputFilename, fileName); makeUppercase (outputFilename); strcpy (pdsHeader.productID, outputFilename); ptr = strlaststr (outputFilename, "_CCIG"); if (ptr != NULL) CCIGdata = TRUE; else CCIGdata = FALSE; /*********************************************************************** * 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=%d, nZvars=%d\n", nAttrs, nZvars); /* Get the CDF global attributes */ if (DEBUG) printf ("Global attributes:\n"); for (attrId = 0; attrId < nAttrs; attrId++) get_cdf_attribute(attrId, GLOBAL_SCOPE, (long) dummy, attrValue); /* Define the value of PDS INSTRUMENT_HOST_NAME if not defined. */ if (!instrumentHostNameDefined) sprintf (pdsHeader.instrumentHostName, "%s%s", pdsHeader.missionName, " LUNAR SURFACE EXPERIMENTS PACKAGE"); if (CCIGdata) { strcpy (outputFilename, pdsHeader.tiffDocument); ptr = strlaststr (outputFilename, ".TIF"); if (ptr != NULL) *ptr = '\0'; strcpy (pdsHeader.productID, outputFilename); } makeUppercase (pdsHeader.productID); dummy = -1; strcpy (pdsLabelFileName, outputFilename); strcat (pdsLabelFileName, ".LBL"); strcpy (tmpLabelFileName, pdsLabelFileName); strcat (tmpLabelFileName, "_tmp"); strcpy (pdsDataFileName, outputFilename); strcat (pdsDataFileName, ".TAB"); strcpy (pdsHeader.tableName, pdsDataFileName); if ((labelFile = fopen(pdsLabelFileName, "w")) == NULL) { printf ("** Cannot create file: %s **\n", tmpLabelFileName); exit (1); } printf ("\n Output label file: %s\n", pdsLabelFileName); catFile = fopen(PDS_CATALOG_FILE, "w"); if (CCIGdata) { /* If the data source is CCIG (Cold Cathode Ion Gage), extract the comments recorded (if any) during the scanning that is captured in the variable named "Comments" or "COMMENTS" */ get_ccig_scan_comments (); write_pds_label (); } else { if ((dataFile = fopen(pdsDataFileName, "w")) == NULL) { printf ("** Cannot create file: %s **\n", pdsDataFileName); exit (1); } printf (" Output table file: %s\n", pdsDataFileName); write_pds_data_file_header (); write_pds_catalog (); if (nZvars > 0) get_zVariables(); write_pds_label (); } if (inFile != NULL) fclose (inFile); fclose (labelFile); fclose (catFile); if (!CCIGdata) fclose (dataFile); status = CDFlib (CLOSE_, CDF_, NULL_); if (status != CDF_OK) cdf_status_handler (status, "CLOSE_, CDF_"); } /*---------------------------------------------------------------------------- * 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 s2 is not found, NULL is returned. *----------------------------------------------------------------------------*/ char * strlaststr (char *s1, char *s2) { char *sc2, *psc1, *ps1; if (*s2 == '\0') return ((char *)NULL); // 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[80]; 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 */ char *attrValue) /* out - string representation */ /* of the attribute value */ { int i, len; long status, numEntries, datatype, attrScope, entryNum, numElements; char attrName[CDF_ATTR_NAME_LEN+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 (attrScope == GLOBAL_SCOPE) { if (!validPDSKeyword(attrName)) return; status = CDFlib (GET_, ATTR_NUMgENTRIES_, &numEntries, NULL_); if (status != CDF_OK) cdf_status_handler (status, "GET_, ATTR_NUMgENTRIES_"); if (DEBUG) printf ("\t%s", attrName); /* Solar Wind Spectrometer (SWS) - The TEXT global attribute has more than 4 entries, but only the first 4 entries are significant. */ if (!CCIGdata) { if (numEntries > 4) numEntries = 4; } /********************************************************************* * 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++) { 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, entryNum, attrValue); } } else { /********************************************************************* * IMPORTANT NOTE: * For the variable attribute, entry number is the variable ID. * numElements - represents the number of attribute values *********************************************************************/ 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) { strcpy (attrValue, "N/A"); return; } if (status != CDF_OK) cdf_status_handler (status,"GET_ATTR_INFO_"); if (DEBUG) printf ("\t%s", attrName); entryNum = 0; /* dummy for variable attributes */ get_cdf_attr_data (attrName, zENTRY_DATA_, datatype, numElements, entryNum, attrValue); } } int validPDSKeyword (char *attrName) { int i, validKeyword; validKeyword = FALSE; for (i=0; i < totPDSKeywords; i++) { if (strcmp(pdsKeywords[i], attrName) == 0) { validKeyword = TRUE; break; } } return validKeyword; } /*-------------------------------------------------------------------------- * 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 */ long entryNum, /* in - global attr entry number */ char *attrValue) /* out - string representation */ /* of the attribute value */ { char entryDataType[20], msg[100], tmp[128], tmp1[128], epString[EPOCH_STRING_LEN+1], ep16String[EPOCH16_STRING_LEN+1]; double epoch16[2]; long year, month, day, hour, minute, second, msec, usec, nsec, psec; long status; /* CDF status code */ char *cPtr; signed char *scPtr; short *sPtr; int *iPtr, i, j, k; 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_) strcpy(entryDataType, "gENTRY_DATA_"); else strcpy(entryDataType, "zENTRY_DATA_"); strcpy (msg, "get_cdf_attr_data, GET_, "); strcat (msg, entryDataType); strcat (msg, cdf_str_datatype(datatype)); if (entryNum == 0) { /* 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: cPtr = (char *) malloc(numElements * sizeof(char) + 1); if (cPtr == NULL) memory_error("get_cdf_attr_data", "CDF_CHAR"); status = CDFlib (GET_, entryData, cPtr, NULL_); if (status != CDF_OK) cdf_status_handler (status, msg); *(cPtr+numElements) = '\0'; /* End of string mark */ if (entryData == gENTRY_DATA_) { get_pds_header (attrName, cPtr, entryNum); } else { /* zENTRY_DATA_ */ strcpy (attrValue, cPtr); } if (DEBUG) printf (" %s = \"%s\"", attrName, cPtr); 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", "CDF_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)); } } if (entryData == zENTRY_DATA_) { for (i=0; i < numElements; i++) { if (i > 0) strcat (attrValue, ", "); sprintf (tmp, "%d", *(scPtr+i)); strcat (attrValue, tmp); } } free (scPtr); break; case CDF_INT2: case CDF_UCHAR: case CDF_UINT1: sPtr = (short *) malloc (sizeof(short) * numElements); if (sPtr == NULL) memory_error("get_cdf_attr_data", "CDF_INT2"); 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 ("%d", *(sPtr+i)); } } if (entryData == zENTRY_DATA_) { for (i=0; i < numElements; i++) { if (i > 0) strcat (attrValue, ", "); sprintf (tmp, "%d", *(sPtr+i)); strcat (attrValue, tmp); } } free (sPtr); break; case CDF_INT4: case CDF_UINT2: case CDF_UINT4: iPtr = (int *) malloc (sizeof(int) * numElements); if (iPtr == NULL) memory_error("get_cdf_attr_data", "CDF_INT4"); 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)); } } if (entryData == zENTRY_DATA_) { for (i=0; i < numElements; i++) { if (i > 0) strcat (attrValue, ", "); sprintf (tmp, "%d", *(iPtr+i)); strcat (attrValue, tmp); } } free (iPtr); break; case CDF_FLOAT: case CDF_REAL4: fPtr = (float *) malloc (sizeof(float) * numElements); if (fPtr == NULL) memory_error("get_cdf_attr_data", "CDF_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)); } } if (entryData == zENTRY_DATA_) { for (i=0; i < numElements; i++) { if (i > 0) strcat (attrValue, ", "); sprintf (tmp, "%G", *(fPtr+i)); fixRealNumber (tmp); strcpy (attrValue, tmp); } } free (fPtr); break; case CDF_DOUBLE: case CDF_REAL8: dPtr = (double *) malloc (sizeof(double) * numElements); if (dPtr == NULL) memory_error("get_cdf_attr_data", "CDF_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)); } } if (entryData == zENTRY_DATA_) { for (i=0; i < numElements; i++) { if (i > 0) strcat (attrValue, ", "); sprintf (tmp, "%G", *(dPtr+i)); fixRealNumber (tmp); strcat (attrValue, tmp); } } 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++) { encodeEPOCH (*(dPtr+i), epString); if (DEBUG) { if (i > 0) printf (", "); printf (epString); } if (i > 0) strcat (attrValue, ", "); /* Convert the CDF EPOCH format to the PDS TIME format. CDF EPOCH - dd-mmm-yyyy hh:mm:ss:mmm PDS TIME - yyyy-mm-ddThh:mm.ss */ EPOCHbreakdown (*(dPtr+i), &year, &month, &day, &hour, &minute, &second, &msec); sprintf (attrValue, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second); } 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 (epoch16, ep16String); if (DEBUG) { if (i > 0) printf (", "); printf (ep16String); } if (i > 0) strcat (attrValue, ", "); /* Convert the CDF EPOCH format to the PDS TIME format. CDF EPOCH - dd-mmm-yyyy hh:mm:ss:mmm:uuu:nnn.ppp PDS TIME - yyyy-mm-ddThh:mm:ss */ EPOCH16breakdown (epoch16, &year, &month, &day, &hour, &minute, &second, &msec, &usec, &nsec, &psec); sprintf (attrValue, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second); } free (dPtr); break; default: printf ("** Error in get_cdf_attribute: bad data type"); } if (DEBUG) printf (" ;\n"); } void get_pds_header (char *attrName, void *attrData, long entryNum) { char *ptr, tmp[50], tmp1[50]; if (strcmp(attrName, "PDS_VERSION_ID") == 0) { strcpy (pdsHeader.verID, (char *) attrData); if (strcmp(pdsHeader.verID, "PDS1") == 0) strcpy (pdsHeader.verID, "PDS3"); } else if (strcmp(attrName, "RECORD_TYPE") == 0 || strcmp(attrName, "PDS_RECORD_TYPE") == 0) strcpy (pdsHeader.recType, (char *) attrData); else if (strcmp(attrName, "MISSION_NAME") == 0 || strcmp(attrName, "PDS_MISSION_NAME") == 0) strcpy (pdsHeader.missionName, (char *) attrData); else if (strcmp(attrName, "INSTRUMENT_HOST_ID") == 0 || strcmp(attrName, "PDS_INSTRUMENT_HOST_ID") == 0) { strcpy (pdsHeader.instrumentHostID, (char *) attrData); if (strcmp(pdsHeader.instrumentHostID, "A12LS") == 0) strcpy (pdsHeader.instrumentHostID, "A12A"); else if (strcmp(pdsHeader.instrumentHostID, "A14LS") == 0) strcpy (pdsHeader.instrumentHostID, "A14A"); else if (strcmp(pdsHeader.instrumentHostID, "A15LS") == 0) strcpy (pdsHeader.instrumentHostID, "A15A"); } else if (strcmp(attrName, "INSTRUMENT_HOST_NAME") == 0 || strcmp(attrName, "PDS_INSTRUMENT_HOST_NAME") == 0) { strcpy (pdsHeader.instrumentHostName, (char *) attrData); instrumentHostNameDefined = TRUE; } else if (strcmp(attrName, "INSTRUMENT_ID") == 0 || strcmp(attrName, "PDS_INSTRUMENT_ID") == 0) { strcpy (pdsHeader.instrumentID, (char *) attrData); if (strcmp(pdsHeader.instrumentID, "CCIGE") == 0) strcpy (pdsHeader.instrumentID, "CCIG"); } else if (strcmp(attrName, "INSTRUMENT_NAME") == 0 || strcmp(attrName, "PDS_INSTRUMENT_NAME") == 0) { strcpy (pdsHeader.instrumentName, (char *) attrData); remove_trailing_blanks (pdsHeader.instrumentName); makeUppercase (pdsHeader.instrumentName); } else if (strcmp(attrName, "DATA_SET_ID") == 0 || strcmp(attrName, "PDS_DATA_SET_ID") == 0) { if (strcmp(dataset_ID,"UNSPECIFIED") == 0) { strncpy (tmp, (char *) attrData, 10); tmp[10] = '\0'; if (strcmp(tmp, "A12LS-SWS-") == 0) strcpy (tmp, "A12A-L-SWS-2-"); else if (strcmp(tmp, "A15LS-SWS-") == 0) strcpy (tmp, "A15A-L-SWS-2-"); strcpy (pdsHeader.datasetID, tmp); strcat (pdsHeader.datasetID, attrData+10); if (strcmp(pdsHeader.datasetID, "A15LS-L-CCIGE-3-ATMOS-DENSITY-PLOTS-V1.0") == 0) strcpy (pdsHeader.datasetID, "A15A-L-CCIG-3-ATMOS-DENSITY-PLOTS-V1.0"); if (strcmp(pdsHeader.datasetID, "A14LS-L-CCIGE-3-ATMOS-DENSITY-PLOTS-V1.0") == 0) strcpy (pdsHeader.datasetID, "A14A-L-CCIG-3-ATMOS-DENSITY-PLOTS-V1.0"); if (strcmp(pdsHeader.datasetID, "A15A-L-SWS-4-SOLAR-WIND-28S-RES-V1.0") == 0) strcpy (pdsHeader.datasetID, "A15A-L-SWS-3-SOLAR-WIND-28S-RES-V1.0"); } else /* If provided from the command line, use this */ strcpy(pdsHeader.datasetID, dataset_ID); } else if (strcmp(attrName, "Logical_source_description") == 0) strcpy (pdsHeader.datasetName, (char *) attrData); else if (strcmp(attrName, "PRODUCT_ID") == 0 || strcmp(attrName, "PDS_PRODUCT_ID") == 0) { /** strcpy (pdsHeader.productID, (char *) attrData); **/ ptr = strstr(pdsHeader.productID, "/*"); /* Microfiche ID */ if (ptr == NULL) strcpy (pdsHeader.productIDcomments, "NONE"); else { strcpy (pdsHeader.productIDcomments, ptr); *ptr = '\0'; } // remove_trailing_blanks (pdsHeader.productID); } else if (strcmp(attrName, "PRODUCT_CREATION_TIME") == 0 || strcmp(attrName, "PDS_PRODUCT_CREATION_TIME") == 0) strcpy (pdsHeader.productCreationTime, (char *) attrData); else if (strcmp(attrName, "SPACECRAFT_CLOCK_START_TIME") == 0 || strcmp(attrName, "SPACECRAFT_CLOCK_START_COUNT") == 0 || strcmp(attrName, "PDS_SPACECRAFT_CLOCK_START_TIME") == 0 || strcmp(attrName, "PDS_SPACECRAFT_CLOCK_START_COUNT") == 0) strcpy (pdsHeader.scClockStartTime, (char *) attrData); else if (strcmp(attrName, "SPACECRAFT_CLOCK_STOP_TIME") == 0 || strcmp(attrName, "SPACECRAFT_CLOCK_STOP_COUNT") == 0 || strcmp(attrName, "PDS_SPACECRAFT_CLOCK_STOP_TIME") == 0 || strcmp(attrName, "PDS_SPACECRAFT_CLOCK_STOP_COUNT") == 0) strcpy (pdsHeader.scClockStopTime, (char *) attrData); else if (strcmp(attrName, "START_TIME") == 0 || strcmp(attrName, "PDS_START_TIME") == 0) { strcpy (pdsHeader.startTime, (char *) attrData); if (strlen(pdsHeader.startTime) == 10) /* hh:mm missing */ strcat (pdsHeader.startTime, "T00:00:00"); } else if (strcmp(attrName, "STOP_TIME") == 0 || strcmp(attrName, "PDS_STOP_TIME") == 0) { strcpy (pdsHeader.stopTime, (char *) attrData); if (strlen(pdsHeader.stopTime) == 10) /* hh:mm missing */ strcat (pdsHeader.stopTime, "T00:00:00"); } else if (strcmp(attrName, "TARGET_NAME") == 0 || strcmp(attrName, "PDS_TARGET_NAME") == 0) strcpy (pdsHeader.targetName, (char *) attrData); else if (strcmp(attrName, "^TIFF_DOCUMENT") == 0 || strcmp(attrName, "PDS_TIFF_DOCUMENT") == 0) strcpy (pdsHeader.tiffDocument, (char *) attrData); else if (strcmp(attrName, "TEXT") == 0) { if (entryNum == 0) strcpy (pdsHeader.obj.description, (char *) attrData); else { strcat (pdsHeader.obj.description, " "); strcat (pdsHeader.obj.description, (char *) attrData); } } else if (strcmp(attrName, "PI_name") == 0) strcpy (pdsHeader.PI_name, (char *) attrData); else if (strcmp(attrName, "Acknowledgement") == 0) strcpy (pdsHeader.acknowledgement, (char *) attrData); else if (strcmp(attrName, "OBJECT") == 0 || strcmp(attrName, "PDS_OBJECT") == 0) { if (entryNum == 0) strcpy (pdsHeader.obj.name, (char *) attrData); else if (entryNum == 1) strcpy (pdsHeader.obj.docName, (char *) attrData); else if (entryNum == 2) strcpy (pdsHeader.obj.publicationDate, (char *) attrData); else if (entryNum == 3) strcpy (pdsHeader.obj.docTopicType, (char *) attrData); else if (entryNum == 4) strcpy (pdsHeader.obj.interchangeFormat, (char *) attrData); else if (entryNum == 5) strcpy (pdsHeader.obj.docFormat, (char *) attrData); else strcpy (pdsHeader.obj.docFormat, "UNKNOWN OBJECT DATA"); } } /*-------------------------------------------------------------------------- * Get the zVariables in the CDF file. *--------------------------------------------------------------------------*/ void get_zVariables() { CDFstatus status; int i, j, k; long varId, attrId, recNo; char attrValue[512]; CDFvar var; if (DEBUG) printf ("\n"); /* zVarsMaxRec: this global variable is set in write_pds_data_file_header. */ for (recNo=0; recNo <= zVarsMaxRec; recNo++) { for (varId=0; varId < nZvars; varId++) { 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_MAXREC_, &var.maxRec, zVAR_RECVARY_, &var.recVariance, NULL_); if (status != CDF_OK) cdf_status_handler (status, "GET_, zVARS_"); if (DEBUG) { printf ("\nvar name = %s, %s/%d, %d:[", var.name, cdf_str_datatype(var.datatype), var.numElements, var.dimensionality); for (i=0; i < var.dimensionality; i++) { if (i > 0) printf (","); printf ("%d", var.dimSizes[i]); } printf("], numRecs = %d, maxRec = %d\n", var.numRecs, var.maxRec); } var.numRecs = 1; /* read 1 record a time */ get_cdf_variable_data (varId, var, recNo); /* Get the variable attributes */ /*********** if (recNo == 0) { for (attrId = 0; attrId < nAttrs; attrId++) get_cdf_attribute(attrId, VARIABLE_SCOPE, varId, attrValue); } ************/ } /* Add the line delimeter - CR (carriage return) and LF (line feed) CR = 0x0D, LF = 0x0A */ if (!CCIGdata) fprintf (dataFile, "\r\n"); } } /*-------------------------------------------------------------------------- * Get the comments recorded during the scanning process. *--------------------------------------------------------------------------*/ void get_ccig_scan_comments () { CDFstatus status; int i, j; long varId, recNo; char *ptr; CDFvar var; status = CDFlib (GET_, zVAR_NUMBER_, "COMMENTS", &varId, NULL_); if (status == NO_SUCH_VAR) { status = CDFlib (GET_, zVAR_NUMBER_, "Comments", &varId, NULL_); } if (status == NO_SUCH_VAR) return; if (status != CDF_OK) cdf_status_handler (status, "GET_, zVAR_NUMRECS_"); 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_MAXREC_, &var.maxRec, zVAR_RECVARY_, &var.recVariance, NULL_); if (status != CDF_OK) cdf_status_handler (status, "GET_, zVAR_, COMMENTS"); if (DEBUG) { printf ("\nvar name = %s, %s/%d, %d:[", var.name, cdf_str_datatype(var.datatype), var.numElements, var.dimensionality); for (i=0; i < var.dimensionality; i++) { if (i > 0) printf (","); printf ("%d", var.dimSizes[i]); } printf("], numRecs = %d\n", var.numRecs); } ptr = (char *) strlaststr(pdsHeader.obj.description, "Any comment recorded during the scanning"); if (ptr != NULL) *ptr = '\0'; remove_trailing_blanks (pdsHeader.obj.description); recNo = 0; /* get data strating from record number 0. */ get_cdf_variable_data (varId, var, recNo); } /*-------------------------------------------------------------------------- * Get the appropriate PDS label for the SWS data. It also writes * the PDS data file. *--------------------------------------------------------------------------*/ void write_pds_data_file_header () { CDFstatus status; int i, j, k, totalRecLength, nBlanks, foundDecimal; int colLength, leng; long varId; char format[MAX_FORMAT_LEN], originalFormat[MAX_FORMAT_LEN], col[5]; char *ptr, width[15], decimal[15], pdsUnit[MAX_UNITS_LEN+1]; char catdesc[MAX_VAR_DESCR_LEN+1], direction; CDFvar var; /***********************************/ /* Initialize the global variables */ /***********************************/ formats = (char **) malloc (sizeof(char *) * nZvars); formatWidth = (int *) malloc (sizeof(int *) * nZvars); formatDecimal = (int *) malloc (sizeof(int *) * nZvars); fillval = (char **) malloc (sizeof(char *) * nZvars); validmin = (char **) malloc (sizeof(char *) * nZvars); validmax = (char **) malloc (sizeof(char *) * nZvars); varNames = (char **) malloc (sizeof(char *) * nZvars); varDescriptions = (char **) malloc (sizeof(char *) * nZvars); var_notes = (char **) malloc (sizeof(char *) * nZvars); varDatatypes = (char **) malloc (sizeof(char *) * nZvars); units = (char **) malloc (sizeof(char *) * nZvars); for (i=0; i < nZvars; i++) { *(formats+i) = malloc (sizeof(char) * MAX_FORMAT_LEN + 1); *(fillval+i) = malloc (sizeof(char) * MAX_FORMAT_LEN + 1); *(validmin+i) = malloc (sizeof(char) * MAX_VALIDMIN_LEN + 1); *(validmax+i) = malloc (sizeof(char) * MAX_VALIDMAX_LEN + 1); *(varNames+i) = malloc (sizeof(char) * CDF_VAR_NAME_LEN256 + 1); *(varDescriptions+i) = malloc (sizeof(char) * MAX_VAR_DESCR_LEN + 1); *(var_notes+i) = malloc (sizeof(char) * MAX_VAR_NOTES_LEN + 1); *(varDatatypes+i) = malloc (sizeof(char) * MAX_VAR_DATATYPE_LEN + 1); *(units+i) = malloc (sizeof(char) * MAX_UNITS_LEN + 1); } strcpy (catdesc, "Solar Ecliptic coordinates"); /***************************************************/ /* Get the max record number of all the variables. */ /***************************************************/ status = CDFlib (GET_, zVARs_MAXREC_, &zVarsMaxRec, NULL_); /* Add the column header records - 1st 2 lines in the data file. */ /* Also add 1 since record number starts at 0 in CDF. */ sprintf (pdsHeader.maxRec, "%d", zVarsMaxRec+3); /* FILE_RECORDS */ sprintf (pdsHeader.rows, "%d", zVarsMaxRec+1); /* ROWS */ /**************************************************************************/ /* Determine the format (F6.1, I4, etc.) of the data of each variable. */ /* This is needed since the value of the FORMAT attribute is not reliable */ /* and used in writing a PDS ASCII table. If the value of the FORMAT */ /* attribute is incorrect, it can result in loss in precision. Read each */ /* data value and determine the format that's appropriate. */ /**************************************************************************/ determineFormat = TRUE; for (varId=0; varId < nZvars; varId++) { maxWidth = 0; /* Global variable */ maxDecimal = 0; /* Global variable */ 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_MAXREC_, &var.maxRec, zVAR_RECVARY_, &var.recVariance, NULL_); if (status != CDF_OK) cdf_status_handler (status, "GET_, zVAR_NAME_"); get_cdf_variable_data (varId, var, 0L); if (DEBUG) printf ("formatWidth[%d] = %d, formatDecimal[%d] = %d\n", varId, formatWidth[varId], varId, formatDecimal[varId]); } determineFormat = FALSE; /************************************************/ /* Get the PDS label and data file header info. */ /************************************************/ for (varId=0; varId < nZvars; varId++) { 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_MAXREC_, &var.maxRec, zVAR_RECVARY_, &var.recVariance, NULL_); if (status != CDF_OK) cdf_status_handler (status, "GET_, zVAR_NAME_"); if (DEBUG) printf ("--- varId = %d, name = %s", varId, var.name); makeUppercase (var.name); /* Caputre the variable/column related metadata or attributes. */ strcpy (*(varNames+varId), var.name); strcpy (*(varDatatypes+varId),get_pds_ascii_table_datatype(var.datatype)); get_attr_str_value(varId, "CATDESC", *(varDescriptions+varId)); ptr = strlaststr (*(varDescriptions+varId), "East, SE Coords"); if (ptr != NULL) strcpy (*(varDescriptions+varId), "Proton Flow Angle toward East in Solar Ecliptic Coordinates"); ptr = strlaststr (*(varDescriptions+varId), "North, SE Coords"); if (ptr != NULL) strcpy (*(varDescriptions+varId), "Proton Flow Angle toward North in Solar Ecliptic Coordinates"); ptr = strlaststr (*(varDescriptions+varId), "Angle of flow"); if (ptr != NULL) { strcpy (catdesc, *(varDescriptions+varId)); direction = catdesc[14]; strcpy (catdesc, "Angle of flow toward ecliptic east n, in Solar Ecliptic Coordinates"); catdesc[35] = direction; strcpy (*(varDescriptions+varId), catdesc); } ptr = strlaststr (*(varDescriptions+varId), "Angle toward ecliptic north"); if (ptr != NULL) { strcpy (catdesc, *(varDescriptions+varId)); direction = catdesc[28]; strcpy (catdesc, "Angle of flow toward ecliptic north n, in Solar Ecliptic Coordinates"); catdesc[36] = direction; strcpy (*(varDescriptions+varId), catdesc); } ptr = strlaststr (*(varDescriptions+varId), "Var_Notes"); if (ptr != NULL) { *(ptr+0) = 'N'; *(ptr+1) = 'O'; *(ptr+2) = 'T'; *(ptr+3) = 'E'; *(ptr+4) = '.'; *(ptr+5) = '\0'; } get_attr_str_value(varId, "FILLVAL", *(fillval+varId)); get_attr_str_value(varId, "VALIDMIN", *(validmin+varId)); get_attr_str_value(varId, "VALIDMAX", *(validmax+varId)); get_attr_str_value(varId, "UNITS", *(units+varId)); map_CDF_units_to_PDS(*(units+varId), pdsUnit); strcpy (*(units+varId), pdsUnit); get_attr_str_value(varId, "VAR_NOTES", *(var_notes+varId)); get_attr_str_value(varId, "FORMAT", format); if (strcmp(format, "N/A") == 0) get_default_format (var, format); else makeUppercase (format); strcpy(originalFormat, format); /* Use the format determined by reading the actual data (instead of relying on the value of the FORMAT attribute). */ if (format[0] == 'E' || format[0] == 'F') sprintf (format, "F%d.%d", formatWidth[varId], formatDecimal[varId]); else if (format[0] == 'I') sprintf (format, "I%d", formatWidth[varId]); else if (format[0] == 'A') sprintf (format, "A%d", formatWidth[varId]); strcpy (*(formats+varId), format); if (DEBUG) printf (", format = %s\n", format); } /********************************************/ /* Print the PDS data file header - line #1 */ /********************************************/ totalRecLength = 0; for (i=0; i < nZvars; i++) { sprintf (col, "%d", i+1); colLength = strlen(col); /* Column header length */ fprintf (dataFile, "%s", col); if (colLength > formatWidth[i]) { formatWidth[i] = colLength; nBlanks = colLength - formatWidth[i]; strcpy (format, *(formats+i)); if (format[0] == 'E' || format[0] == 'F') sprintf (format, "F%d.%d", formatWidth[i], formatDecimal[i]); else if (format[0] == 'I') sprintf (format, "I%d", formatWidth[i]); else if (format[0] == 'A') sprintf (format, "A%d", formatWidth[i]); strcpy (*(formats+i), format); } else nBlanks = formatWidth[i] - colLength; totalRecLength += formatWidth[i]; /* Add the field delimiter - ", ". The last loop interation wiil */ /* 2 for PDS ASCII table line delimter - */ totalRecLength += 2; for (j=0; j < nBlanks; j++) fprintf (dataFile, " "); /* Put 2 spaces between fields */ if (i != (nZvars -1)) fprintf (dataFile, " "); } sprintf (pdsHeader.recLength, "%d", totalRecLength); /* RECORD_BYTES */ strcpy (pdsHeader.recType, "FIXED_LENGTH"); /* RECORD_TYPE */ fprintf (dataFile, "\r\n"); /********************************************/ /* Print the PDS data file header - line #2 */ /********************************************/ for (i=0; i < nZvars; i++) { for (j=0; j < formatWidth[i]; j++) fprintf (dataFile, "="); /* Put 2 spaces between fields */ if (i != (nZvars -1)) fprintf (dataFile, " "); } fprintf (dataFile, "\r\n"); } /*-------------------------------------------------------------------------- * Returns the variable attribute value/entry for the given variable ID * and variable attribute name. *--------------------------------------------------------------------------*/ void get_attr_str_value (long varId, char *attrName, char *attrValue) { CDFstatus status; long numElements, attrNum, attrScope; char msg[512]; status = CDFlib (GET_, ATTR_NUMBER_, attrName, /* in */ &attrNum, /* out */ NULL_); if (status == NO_SUCH_ATTR) { strcpy (attrValue, "N/A"); return; } if (status != CDF_OK) { sprintf (msg, "GET_, ATTR_NUMBER_ : %s", attrName); cdf_status_handler (status, msg); } else get_cdf_attribute (attrNum, /* in */ VARIABLE_SCOPE, /* in */ varId, /* in */ attrValue); /* out */ } /*-------------------------------------------------------------------------- * Write PDS label. *--------------------------------------------------------------------------*/ void write_pds_label () { time_t tval; struct tm *now; char *ptr; int i, longest, startByte, headerBytes; char longestKeyword[50], tableName[512], nCols[12], tmp[CDF_VAR_NAME_LEN256]; /* Get the current date and time for the PRODUCT_CREATION_TIME keyword */ tval = time(NULL); now = localtime(&tval); sprintf (pdsHeader.productCreationTime, "%04d-%02d-%02dT%02d:%02d:%02d", now->tm_year+1900, now->tm_mon+1, now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); strcpy (longestKeyword, LONGEST_PDS_KEYWORD); longest = strlen(longestKeyword); write_pds_keyword (labelFile, "PDS_VERSION_ID", pdsHeader.verID, longest, " "); write_pds_keyword (labelFile, "RECORD_TYPE", pdsHeader.recType, longest, "\""); /* There's a data file (e.g. SWS) */ if (!CCIGdata) { write_pds_keyword (labelFile, "RECORD_BYTES", pdsHeader.recLength, longest, " "); write_pds_keyword (labelFile, "FILE_RECORDS", pdsHeader.maxRec, longest, " "); write_pds_keyword (labelFile, "^HEADER", pdsDataFileName, longest, "\""); strcpy (tableName, "(\""); strcat (tableName, pdsDataFileName); strcat (tableName, "\",3)"); write_pds_keyword (labelFile, "^TABLE", tableName, longest, " "); } write_blank_line (labelFile, 1); write_pds_keyword (labelFile, "MISSION_NAME", pdsHeader.missionName, longest, "\""); if (!CCIGdata) write_pds_keyword (labelFile, "INSTRUMENT_HOST_ID", pdsHeader.instrumentHostID, longest, "\""); write_pds_keyword (labelFile, "INSTRUMENT_HOST_NAME", pdsHeader.instrumentHostName, longest, "\""); if (!CCIGdata) write_pds_keyword (labelFile, "INSTRUMENT_ID", pdsHeader.instrumentID, longest, "\""); write_pds_keyword (labelFile, "INSTRUMENT_NAME", pdsHeader.instrumentName, longest, "\""); write_blank_line (labelFile, 1); write_pds_keyword (labelFile, "DATA_SET_ID", pdsHeader.datasetID, longest, "\""); write_pds_keyword (labelFile, "PRODUCT_ID", pdsHeader.productID, longest, "\""); write_pds_keyword (labelFile, "PRODUCT_CREATION_TIME", pdsHeader.productCreationTime, longest, " "); write_blank_line (labelFile, 1); if (CCIGdata) { write_pds_keyword (labelFile, "START_TIME", pdsHeader.startTime, longest, " "); write_pds_keyword (labelFile, "STOP_TIME", pdsHeader.stopTime, longest, " "); } if (strcmp(pdsHeader.scClockStartTime, "N/A") == 0) write_pds_keyword (labelFile, "SPACECRAFT_CLOCK_START_COUNT", pdsHeader.scClockStartTime, longest, "\""); else write_pds_keyword (labelFile, "SPACECRAFT_CLOCK_START_COUNT", pdsHeader.scClockStartTime, longest, " "); if (strcmp(pdsHeader.scClockStopTime, "N/A") == 0) write_pds_keyword (labelFile, "SPACECRAFT_CLOCK_STOP_COUNT", pdsHeader.scClockStopTime, longest, "\""); else write_pds_keyword (labelFile, "SPACECRAFT_CLOCK_STOP_COUNT", pdsHeader.scClockStopTime, longest, " "); if (!CCIGdata) { write_pds_keyword (labelFile, "START_TIME", pdsHeader.startTime, longest, " "); write_pds_keyword (labelFile, "STOP_TIME", pdsHeader.stopTime, longest, " "); } write_pds_keyword (labelFile, "TARGET_NAME", pdsHeader.targetName, longest, "\""); write_blank_line (labelFile, 1); /* No PDS data file (e.g TIFF image for the CCIG data */ if (CCIGdata) { if (strcmp(pdsHeader.obj.name, "TIFF_DOCUMENT") == 0) { write_pds_keyword (labelFile, "^TIFF_DOCUMENT", pdsHeader.tiffDocument, longest, "\""); write_blank_line (labelFile, 1); write_pds_keyword (labelFile, "OBJECT", pdsHeader.obj.name, longest, " "); write_pds_keyword (labelFile, " DOCUMENT_NAME", pdsHeader.obj.docName, longest, "\""); write_pds_keyword (labelFile, " PUBLICATION_DATE", pdsHeader.obj.publicationDate, longest, " "); write_pds_keyword (labelFile, " DOCUMENT_TOPIC_TYPE", pdsHeader.obj.docTopicType, longest, "\""); write_pds_keyword (labelFile, " INTERCHANGE_FORMAT", pdsHeader.obj.interchangeFormat, longest, " "); write_pds_keyword (labelFile, " DOCUMENT_FORMAT", pdsHeader.obj.docFormat, longest, "\""); write_pds_keyword (labelFile, " DESCRIPTION", pdsHeader.obj.description, longest, "\""); write_pds_keyword (labelFile, "END_OBJECT", pdsHeader.obj.name, longest, " "); } } else { write_pds_keyword (labelFile, "OBJECT", "HEADER", longest, " "); headerBytes = atoi(pdsHeader.recLength) * 2; /* 2 col header recs */ sprintf (tmp, "%d", headerBytes); write_pds_keyword (labelFile, " BYTES", tmp, longest, " "); write_pds_keyword (labelFile, " RECORDS", "2", longest, " "); write_pds_keyword (labelFile, " HEADER_TYPE", "COLUMN_LABEL", longest, " "); write_pds_keyword (labelFile, " INTERCHANGE_FORMAT", "ASCII", longest, " "); write_pds_keyword (labelFile, " DESCRIPTION", "Column header records", longest, "\""); write_pds_keyword (labelFile, "END_OBJECT", "HEADER", longest, " "); write_blank_line (labelFile, 1); write_pds_keyword (labelFile, "OBJECT", "TABLE", longest, " "); write_pds_keyword (labelFile, " INTERCHANGE_FORMAT", "ASCII", longest, " "); write_pds_keyword (labelFile, " ROWS", pdsHeader.rows, longest, " "); sprintf (nCols, "%d", nZvars); write_pds_keyword (labelFile, " COLUMNS", nCols, longest, " "); write_pds_keyword (labelFile, " ROW_BYTES", pdsHeader.recLength, longest, " "); write_pds_keyword (labelFile, " INDEX_TYPE", "SINGLE", longest, " "); if (strlen(pdsHeader.obj.description) > 0) write_pds_keyword (labelFile, " DESCRIPTION", pdsHeader.obj.description, longest, "\""); else write_pds_keyword (labelFile, " DESCRIPTION", "ASCII table - comma separted", longest, "\""); startByte = 1; for (i=0; i < nZvars; i++) { write_blank_line (labelFile, 1); sprintf (tmp, "%d", i+1); write_pds_keyword (labelFile, " OBJECT", "COLUMN", longest, " "); write_pds_keyword (labelFile, " COLUMN_NUMBER", tmp, longest, " "); write_pds_keyword (labelFile, " NAME", varNames[i], longest, "\""); if (strcmp(varDescriptions[i], "N/A") != 0) write_pds_keyword (labelFile, " DESCRIPTION", varDescriptions[i], longest, "\""); write_pds_keyword (labelFile, " DATA_TYPE", varDatatypes[i], longest, "\""); if (strcmp(formats[i], "N/A") != 0) write_pds_keyword (labelFile, " FORMAT", formats[i], longest, "\""); if (strcmp(units[i], "N/A") != 0 && strcmp(units[i], " ") != 0) write_pds_keyword (labelFile, " UNIT", units[i], longest, "\""); if (strcmp(var_notes[i], "N/A") != 0) write_pds_keyword (labelFile, " NOTE", var_notes[i], longest, "\""); if (strcmp(fillval[i], "N/A") != 0) write_pds_keyword (labelFile, " MISSING_CONSTANT", fillval[i], longest, " "); /************* Do not write the VALID_MIN and VALID_MAX attributes as their values are not reliable and cause problems with the PDS tabel checker program. if (strcmp(validmin[i], "N/A") != 0) write_pds_keyword (labelFile, " VALID_MINIMUM",validmin[i],longest," "); if (strcmp(validmax[i], "N/A") != 0) write_pds_keyword (labelFile, " VALID_MAXIMUM",validmax[i],longest," "); ****************/ sprintf (tmp, "%d", startByte); write_pds_keyword (labelFile, " START_BYTE", tmp, longest, " "); sprintf (tmp, "%d", formatWidth[i]); write_pds_keyword (labelFile, " BYTES", tmp, longest, " "); startByte += formatWidth[i] + 2; /* 2 spaces between columns */ write_pds_keyword (labelFile, " END_OBJECT", "COLUMN", longest, " "); } write_blank_line (labelFile, 1); write_pds_keyword (labelFile, "END_OBJECT", "TABLE", longest, " "); } write_blank_line (labelFile, 1); write_pds_keyword (labelFile, "END", "", longest, " "); /* fprintf (labelFile, "END"); */ } /*-------------------------------------------------------------------------- * Write PDS catalog. *--------------------------------------------------------------------------*/ void write_pds_catalog () { int i, longest; char longestKeyword[50], tableName[512], nCols[12], tmp[CDF_VAR_NAME_LEN256]; strcpy (longestKeyword, " DATA_SET_COLLECTION_MEMBER_FLG"); longest = strlen(longestKeyword); write_pds_keyword (catFile, "PDS_VERSION_ID", pdsHeader.verID, longest, " "); strcpy (tmp, pdsHeader.productCreationTime); strcat (tmp, " D. Han Created"); write_pds_keyword (catFile, "LABEL_REVISION_NOTE", tmp, longest, "\""); write_blank_line (catFile, 1); write_pds_keyword (catFile, "OBJECT", "DATA_SET", longest, " "); write_pds_keyword (catFile, " DATA_SET_ID", pdsHeader.datasetID, longest,"\""); write_blank_line (catFile, 1); write_pds_keyword (catFile, " OBJECT", "DATA_SET_INFORMATION", longest," "); write_pds_keyword (catFile, " DATA_SET_NAME", pdsHeader.datasetName, longest, "\""); write_pds_keyword (catFile, " DATA_SET_COLLECTION_MEMBER_FLG", "N", longest, "\""); write_pds_keyword (catFile, " DATA_OBJECT_TYPE", "TABLE", longest, "\""); write_pds_keyword (catFile, " START_TIME", pdsHeader.startTime, longest, "\""); write_pds_keyword (catFile, " STOP_TIME", pdsHeader.stopTime, longest, "\""); write_pds_keyword (catFile, " DATA_SET_RELEASE_DATE", DATA_SET_RELEASE_DATE, longest, " "); write_pds_keyword (catFile, " ARCHIVE_STATUS", ARCHIVE_STATUS, longest, "\""); write_pds_keyword (catFile, " PRODUCER_FULL_NAME", "DAVID WILLIAMS", longest, "\""); write_pds_keyword (catFile, " DETAILED_CATALOG_FLAG", DETAILED_CATALOG_FLAG, longest, "\""); write_pds_keyword (catFile, " DATA_SET_TERSE_DESC", DATA_SET_TERSE_DESC, longest, "\""); write_pds_keyword (catFile, " ABSTRACT_DESC", pdsHeader.obj.description, longest, "\""); write_pds_keyword (catFile, " CITATION_DESC", CITATION_DESC, longest, "\""); write_pds_keyword (catFile, " END_OBJECT", "DATA_SET_INFORMATION", longest," "); write_blank_line (catFile, 1); write_pds_keyword (catFile, " OBJECT", "DATA_SET_TARGET", longest, " "); write_pds_keyword (catFile, " TARGET_NAME", pdsHeader.targetName, longest, "\""); write_pds_keyword (catFile, " END_OBJECT", "DATA_SET_TARGET", longest, " "); write_blank_line (catFile, 1); write_pds_keyword (catFile, " OBJECT", "DATA_SET_HOST", longest, " "); write_pds_keyword (catFile, " INSTRUMENT_HOST_ID", pdsHeader.instrumentHostID, longest, "\""); write_pds_keyword (catFile, " INSTRUMENT_ID", pdsHeader.instrumentID,longest, "\""); write_pds_keyword (catFile, " END_OBJECT", "DATA_SET_HOST", longest, " "); write_blank_line (catFile, 1); write_pds_keyword (catFile, " OBJECT", "DATA_SET_MISSION", longest, " "); write_pds_keyword (catFile, " MISSION_NAME", pdsHeader.missionName, longest, "\""); write_pds_keyword (catFile, " END_OBJECT", "DATA_SET_MISSION",longest, " "); write_blank_line (catFile, 1); write_pds_keyword (catFile, " OBJECT", "DATA_SET_REFERENCE_INFORMATION", longest, " "); write_pds_keyword (catFile, " REFERENCE_KEY_ID", " ", longest, "\""); write_pds_keyword (catFile, " END_OBJECT", "DATA_SET_REFERENCE_INFORMATION", longest, " "); write_blank_line (catFile, 1); write_pds_keyword (catFile, "END_OBJECT", "DATA_SET", longest, " "); write_blank_line (catFile, 1); fprintf (catFile, "END"); } void write_pds_keyword (FILE *file, char *keyword, char *value, int longest, char *flag) { int i, diff, string, remainingSpaces, nCharsWritten; if (strcmp(flag,"\"") == 0) string = TRUE; else string = FALSE; if (strlen(value) == 0) { fprintf (file, "%s\r\n", keyword); return; } diff = longest - strlen(keyword); fprintf (file, "%s", keyword); for (i=0; i < diff; i++) fprintf (file, " "); fprintf (file, " = "); remainingSpaces = MAX_LABEL_LINE_LENGTH - longest - 3; /* " = " */ if (string) remainingSpaces -= 2; /* account for open " and close " */ if (remainingSpaces >= strlen(value)) { /* Fits on one line */ if (string) fprintf (file, "\"%s\"", value); else fprintf (file, "%s", value); if (strcmp(keyword, "PRODUCT_ID") == 0) { if (strcmp(pdsHeader.productIDcomments,"NONE") != 0) fprintf (file, " %s", pdsHeader.productIDcomments); } write_blank_line (file, 1); } else wrapLongString (file, value, longest, MAX_LABEL_LINE_LENGTH); } void write_pds_data (char *varData, long varId, char *flag) { int i, diff, string, remainingSpaces, nCharsWritten; char *tmp; if (strcmp(flag,"\"") == 0) string = TRUE; else string = FALSE; tmp = (char *) malloc (sizeof(char) * formatWidth[varId] + 1); diff = formatWidth[varId] - strlen(varData); /* Right-justify a number. */ if (diff > 0) { for (i=0; i < diff; i++) tmp[i] = ' '; for (i=0; i < strlen(varData); i++) tmp[diff++] = varData[i]; tmp[formatWidth[varId]] = '\0'; strcpy(varData, tmp); } fprintf (dataFile, "%s", varData); /* Do not write 2 spaces for the last variable. Variable ID starts at 0. */ if (varId < (nZvars-1)) fprintf (dataFile, " "); free (tmp); } void wrapLongString (FILE *file, char *str, int indent, int maxLineLength) { int i, j, k, m, n, leng, nCharsProcessed, printToIndex; int linesProcessed; char *line, *tmp; line = (char *) malloc (sizeof(char) * maxLineLength + 1); tmp = (char *) malloc (sizeof(char) * maxLineLength + 1); j = 0; /* index for the 'line' string array */ k = 0; /* index for the 'tmp' string array */ linesProcessed = 0; leng = strlen(str); nCharsProcessed = indent + 4; /* account for ' = "' */ if (DEBUG1) { printf ("\nIn, wrapLongString, str = %s, strlen(str) = %d\n", str, leng); printf ("indent = %d, nChasProcessed = %d\n", indent, nCharsProcessed); } for (i=0; i < maxLineLength; i++) line[i] = ' '; fprintf (file, "\""); for (i=0; i < leng; i++) { if (nCharsProcessed < maxLineLength) { line[j] = str[i]; nCharsProcessed++; if (DEBUG1) printf ("line[%d] = %c, str[%d] = %c, nCharsProcessed = %d\n", j, line[j], i, str[i], nCharsProcessed); j++; } else { linesProcessed++; for (n=0; n < maxLineLength; n++) tmp[n] = ' '; /* Pick up the unprocessed portion of an word into 'tmp'. */ k = 0; /* index for 'tmp' */ m = j - 1; /* last position in 'line' */ /*********************************************************************** The last character read is not a blank that means the read ended in the midlle of a word. Save the unprocessed portion of the word. ***********************************************************************/ if (str[i] != ' ') { while (line[m] != ' ') tmp[k++] = line[m--]; printToIndex = m - 1; /* Do not print the blank spaces at the end */ while (line[printToIndex] == ' ') printToIndex--; } else printToIndex = j - 1; if (linesProcessed > 1) { for (n=0; n < INDENT; n++) fprintf (file, " "); } /* Write the current 'line' */ if (DEBUG1) printf ("## writing to file = \""); for (n=0; n <= printToIndex; n++) { fprintf (file, "%c", line[n]); if (DEBUG1) printf ("%c", line[n]); } if (DEBUG1) printf ("\"\n"); fprintf (file, "\r\n"); j = 0; /* Reset the index for the 'line' array */ nCharsProcessed = INDENT; /* Pick up the unprocess characters on the current line. */ if (DEBUG1) printf ("--- unprocess chars = \"", k); if (k > 0) { for (n=k; n >= 0; n--) /* Skip the leading blank spaces */ if (tmp[n] == ' ') k--; for (; k >= 0; k--) { if (DEBUG1) printf ("%c", tmp[k]); nCharsProcessed++; line[j++] = tmp[k]; } } if (DEBUG1) printf("\"\n"); if (str[i] != ' ') { line[j++] = str[i]; nCharsProcessed++; } if (DEBUG1) { printf ("@@@ beginning of new line, j = %d\n", j); for (n=0; n < j; n++) printf ("line[%d] = %c\n", n, line[n]); printf ("@@@@\n"); } } } /************************/ /* Write the last line. */ /************************/ if (linesProcessed >= 1) { for (n=0; n < INDENT; n++) fprintf (file, " "); } if (j > 0) { if (DEBUG1) printf ("!!! yahoo - flushing the last buffer, j = %d\n", j); for (i=0; i < j; i++) { fprintf (file, "%c", line[i]); if (DEBUG1) printf ("## writing to file, line[%d] = %c\n", i, line[i]); } } fprintf (file, "\"\r\n"); free (line); free (tmp); } /*-------------------------------------------------------------------------- * 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 recNo) /* in - rec # to read data from */ { CDFstatus status; /* CDF status code */ char *str, epString[EPOCH_STRING_LEN+1]; char ep16String[EPOCH16_STRING_LEN+1], varData[CDF_VAR_NAME_LEN256+1], formatValue[15], width[15], decimal[15]; long year, month, day, hour, minute, second, msec, usec, nsec, psec; double epoch16[2]; int i, j, k, divide, foundDecimal, dimensionality, numValues; /* # of values on each record */ char *cPtr; signed char *scPtr; short *sPtr; int *iPtr; float *fPtr; double *dPtr; long totRecs, /* total # of records to read */ numRecsLeftToRead, numRecs; /* # of records to read and write at a time */ j = 0; numValues = 1; /* # of values on each CDF record */ dimensionality = (int) 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. *********************************************************************/ else if (var.datatype == CDF_EPOCH) { var.dimSizes[dimensionality] = EPOCH_STRING_LEN; dimensionality++; } else if (var.datatype == CDF_EPOCH16) { var.dimSizes[dimensionality] = EPOCH16_STRING_LEN; dimensionality++; } for (i=0; i < dimensionality; i++) { numValues *= var.dimSizes[i]; } if (var.datatype == CDF_EPOCH) numValues /= EPOCH_STRING_LEN; else if (var.datatype == CDF_EPOCH16) numValues /= EPOCH16_STRING_LEN; totRecs = var.numRecs; /* total # of records for this var */ numRecsLeftToRead = var.numRecs; while (numRecsLeftToRead > 0) { divide = 1; numRecs = numRecsLeftToRead; /* # of records to read at a time */ switch (var.datatype) { case CDF_CHAR: cPtr = NULL; while (cPtr == NULL) { cPtr = (char *) malloc (sizeof(char) * numValues * numRecs + 1); 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"); } } /* Look for the end of the string. Note that the CDF library doesn't put the null character at the end of the string. */ for (i=numValues-1; ; i--) if (cPtr[i] != ' ') break; cPtr[i+1] = '\0'; if (DEBUG) printf ("Loc of the end of the string = %d\n", i); if (strcmp(var.name,"COMMENTS") == 0 || strcmp(var.name,"Comments") == 0) { strcat (pdsHeader.obj.description, " During the scanning process, the following comment was recorded: "); strcat (pdsHeader.obj.description, (char *) cPtr); } /* Write data to the PDS data file. */ str = (char *) malloc (sizeof(char) * numValues + 1); if (!CCIGdata) { for (k=0; k < numRecs; k++) { for (i=0; i < numValues; i++) { if (!determineFormat) { fprintf (dataFile, "%c", *(cPtr+(k*numValues+i))); } str[i] = *(cPtr+(k*numValues+i)); } str[numValues] = '\0'; if (determineFormat) { if (strlen(str) > maxWidth) maxWidth = strlen(str); } } formatWidth[varId] = maxWidth; formatDecimal[varId] = 0; } 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 */ /* Write data to the PDS data file. */ if (!CCIGdata) { sprintf (formatValue, "%%%dd", formatWidth[varId]); for (k=0; k < numRecs; k++) { for (i=0; i < numValues; i++) { if (determineFormat) { sprintf (varData, "%d", *(scPtr+(k*numValues+i))); if (strlen(varData) > maxWidth) maxWidth = strlen(varData); } else { sprintf (varData, formatValue, *(scPtr+(k*numValues+i))); write_pds_data (varData, varId, " "); } } } if (determineFormat) formatWidth[varId] = maxWidth; } free (scPtr); break; case CDF_INT2: case CDF_UCHAR: case CDF_UINT1: 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 (!CCIGdata) { sprintf (formatValue, "%%%dd", formatWidth[varId]); for (k=0; k < numRecs; k++) { for (i=0; i < numValues; i++) { if (determineFormat) { sprintf (varData, "%d", *(sPtr+(k*numValues+i))); if (strlen(varData) > maxWidth) maxWidth = strlen(varData); } else { sprintf (varData, formatValue, *(sPtr+(k*numValues+i))); write_pds_data (varData, varId, " "); } } } if (determineFormat) formatWidth[varId] = maxWidth; } free (sPtr); break; case CDF_INT4: case CDF_UINT2: case CDF_UINT4: 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 (!CCIGdata) { sprintf (formatValue, "%%%dd", formatWidth[varId]); for (k=0; k < numRecs; k++) { for (i=0; i < numValues; i++) { if (determineFormat) { sprintf (varData, "%d", *(iPtr+(k*numValues+i))); if (strlen(varData) > maxWidth) maxWidth = strlen(varData); } else { sprintf (varData, formatValue, *(iPtr+(k*numValues+i))); write_pds_data (varData, varId, " "); } } } if (determineFormat) formatWidth[varId] = maxWidth; } free (iPtr); 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 (!CCIGdata) { sprintf (formatValue, "%%%d.%df", formatWidth[varId], formatDecimal[varId]); for (k=0; k < numRecs; k++) { for (i=0; i < numValues; i++) { sprintf (varData, "%G", *(fPtr+(k*numValues+i))); if (scientificNotation(varData)) fixRealNumber (varData); if (determineFormat) { if (scientificNotation(varData)) maxWidth = strlen(varData); else parseFormat (varData, width, decimal, &foundDecimal); if (strlen(width) > maxWidth) maxWidth = strlen(width); if (strlen(decimal) > maxDecimal) maxDecimal = strlen(decimal); } else { if (!scientificNotation(varData)) sprintf (varData, formatValue, *(fPtr+(k*numValues+i))); write_pds_data (varData, varId, " "); } } } if (determineFormat) { formatWidth[varId] = maxWidth + maxDecimal + 1; formatDecimal[varId] = maxDecimal; } } 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 (!CCIGdata) { sprintf (formatValue, "%%%d.%df", formatWidth[varId], formatDecimal[varId]); for (k=0; k < numRecs; k++) { for (i=0; i < numValues; i++) { sprintf (varData, "%G", *(dPtr+(k*numValues+i))); if (scientificNotation(varData)) fixRealNumber (varData); if (determineFormat) { if (scientificNotation(varData)) maxWidth = strlen(varData); else parseFormat (varData, width, decimal, &foundDecimal); if (strlen(width) > maxWidth) maxWidth = strlen(width); if (strlen(decimal) > maxDecimal) maxDecimal = strlen(decimal); } else { if (!scientificNotation(varData)) sprintf (varData, formatValue, *(dPtr+(k*numValues+i))); write_pds_data (varData, varId, " "); } } } if (determineFormat) { formatWidth[varId] = maxWidth + maxDecimal + 1; formatDecimal[varId] = maxDecimal; } } 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 */ cPtr = (char *) malloc (sizeof(char) * numValues * numRecs * EPOCH_STRING_LEN + 1); if (cPtr == NULL) memory_error("get_cdf_variable_data", "CDF_EPOCH"); *cPtr = '\0'; /* Initialize (VERY IMPORTANT) */ /* Get all the EPOCH values into a single string. */ for (i=0; i < numRecs * numValues; i++) { encodeEPOCH (*(dPtr+i), epString); strcat(cPtr, epString); /* Convert the CDF EPOCH format to the PDS TIME format. CDF EPOCH - dd-mmm-yyyy hh:mm:ss:mmm PDS TIME - yyyy-mm-ddThh:mm:ss */ EPOCHbreakdown (*(dPtr+i), &year, &month, &day, &hour, &minute, &second, &msec); sprintf (varData, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second); if (!CCIGdata && !determineFormat) { fprintf (dataFile, "%s ", varData); if (recNo == 0) strcpy (pdsHeader.startTime, varData); else if (recNo == zVarsMaxRec) strcpy (pdsHeader.stopTime, varData); } } formatWidth[varId] = strlen(varData); formatDecimal[varId] = 0; 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 */ cPtr = (char *) malloc (sizeof(char) * numValues * numRecs * EPOCH16_STRING_LEN + 1); if (cPtr == NULL) memory_error("get_cdf_variable_data", "CDF_EPOCH16"); *cPtr = '\0'; /* Initialize (VERY IMPORTANT) */ /* 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 (epoch16, ep16String); strcat(cPtr, ep16String); /* Convert the CDF EPOCH16 format to the PDS TIME format. CDF EPOCH16 - dd-mmm-yyyy hh:mm:ss:mmm.uuu.nnn.ppp PDS TIME - yyyy-mm-ddThh:mm:ss */ EPOCH16breakdown (epoch16, &year, &month, &day, &hour, &minute, &second, &msec, &usec, &nsec, &psec); sprintf (varData, "%04d-%02d-%02dT%02d:%02d:%02d", year, month, day, hour, minute, second); if (!CCIGdata && !determineFormat) fprintf (dataFile, "%s ", varData); } formatWidth[varId] = strlen(varData); formatDecimal[varId] = 0; free (cPtr); free (dPtr); break; default: printf ("** Error in getVarData: bad type"); } numRecsLeftToRead = totRecs - numRecs; if (numRecsLeftToRead > 0) { totRecs = numRecsLeftToRead; } } /* 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_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"; } } /*-------------------------------------------------------------------------- * This routine returns the PDS ASCII table datatype for the given CDF * datatype. *--------------------------------------------------------------------------*/ char * get_pds_ascii_table_datatype (long type) { switch (type) { case CDF_CHAR: case CDF_UCHAR: return "CHARACTER"; case CDF_BYTE: case CDF_INT1: case CDF_INT2: case CDF_UINT1: case CDF_INT4: case CDF_UINT2: case CDF_UINT4: return "ASCII_INTEGER"; case CDF_FLOAT: case CDF_REAL4: case CDF_DOUBLE: case CDF_REAL8: return "ASCII_REAL"; case CDF_EPOCH: case CDF_EPOCH16: return "TIME"; } } /*--------------------------------------------------------------------------- * 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 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 PDS file."); printf ("\n"); printf ("Usage: cdf-to-PDS -[Options] \n"); printf ("\n"); printf ("Options:\n"); printf (" -map Use the user-supplied mapping file.\n"); printf (" -output Name of the output file.\n"); printf (" -debug Show debug information.\n"); printf ("\n"); printf ("Examples of usage: \n"); printf ("1) cdf-to-pds test.cdf\n"); printf (" will convert the test.cdf (CCIG) into the test.LBL.\n\n"); printf (" will convert the test.cdf (SWS) into the test.LBL and test.TAB.\n\n"); printf ("2) cdf-to-pds -map mymap.dat test.cdf\n"); printf (" will convert the test.cdf into the test.LBL using the\n"); printf (" user-supplied units mapping file called 'mymap.dat' instead\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],"-dataset_id") == 0) { nextArg = getNextArgument(argc, argv, i); if (strcmp(nextArg, "No next argument") == 0 || *(nextArg+0) == '-') errorMsg("** Error - data set ID is not defined"); else strcpy(dataset_ID, nextArg); } else if (strcmp(argv[i],"-output") == 0) { nextArg = getNextArgument(argc, argv, i); if (strcmp(nextArg, "No next argument") == 0 || *(nextArg+0) == '-') errorMsg("** Error - output file is not defined"); else strcpy(outputFilename, nextArg); } else if (strcmp(argv[i],"-debug") == 0) DEBUG = TRUE; else if (strcmp(argv[i],"-debug1") == 0) DEBUG1 = 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_units_to_PDS (char *cdfUnit, /* in - CDF unit */ char *pdsUnit) /* out - PDS unit */ { int i; strcpy (pdsUnit, cdfUnit); for (i=0; i < totUnitsInMappingFile; i++) { if (strcmp(cdfUnits[i], cdfUnit) == 0) { strcpy(pdsUnit, pdsUnits[i]); break; } } } void makeUppercase (char *str) { int i, strLeng; strLeng = strlen(str); for (i=0; i < strLeng; i++) str[i] = toupper(str[i]); } void write_blank_line (FILE *file, int nLines) { int i; for (i=0; i < nLines; i++) fprintf (file, "\r\n"); } void remove_trailing_blanks (char *str) { int i; i = strlen(str) - 1; while (str[i] == ' ') i--; str[i+1] = '\0'; } void removeFileExtension (char *fileName, char *ext) { char *ptr; ptr = (char *) strlaststr(fileName, ext); if (ptr != NULL) *ptr = '\0'; } void removeInavlidPDSfilenameChars (char *fileName) { int i, j, k, leng; char *tmp, invalid_PDS_Filename_Chars[1]; leng = strlen(fileName); invalid_PDS_Filename_Chars[0] = '#'; tmp = (char *) malloc(sizeof(char) * leng); strcpy(tmp, fileName); for (i=0; i < 1; i++) { k = 0; for (j=0; j < leng; j++) { if (tmp[j] != invalid_PDS_Filename_Chars[i]) fileName[k++] = tmp[j]; } fileName[k] = '\0'; if (i > 0) strcpy(tmp, fileName); } free (tmp); } void get_default_format (CDFvar var, /* in */ char *format) /* out */ { switch (var.datatype) { case CDF_CHAR: sprintf (format, "A%d", var.numElements); break; case CDF_BYTE: case CDF_INT1: strcpy (format, "I4"); case CDF_INT2: case CDF_UINT1: case CDF_UCHAR: strcpy (format, "I6"); break; case CDF_INT4: case CDF_UINT2: case CDF_UINT4: strcpy (format, "I11"); break; case CDF_FLOAT: case CDF_REAL4: strcpy (format, "F10.3"); break; case CDF_DOUBLE: case CDF_REAL8: strcpy (format, "F14.4"); break; case CDF_EPOCH: case CDF_EPOCH16: strcpy (format, "A19"); break; } } void fixRealNumber (char *num) { int j, k, decimalFound, scienticNotationFound; char tmp[200]; decimalFound = FALSE; scienticNotationFound = FALSE; for (j=0; j < strlen(num); j++) { if (num[j] == '.') decimalFound = TRUE; else if (num[j] == 'E') scienticNotationFound = TRUE; } /* Change -1E+31 to -1.0+E31 */ k = 0; if (scienticNotationFound && !decimalFound) { for (j=0; j < strlen(num); j++) { if (num[j] != 'E') tmp[k++] = num[j]; else { tmp[k++] = '.'; tmp[k++] = '0'; tmp[k++] = num[j]; } } tmp[k] = '\0'; strcpy (num, tmp); } else if (!decimalFound) /* regular real number without .0 (e.g. 8)*/ strcat (num, ".0"); } int scientificNotation (char *num) { int i, scienticNotationFound; scienticNotationFound = FALSE; for (i=0; i < strlen(num); i++) { if (num[i] == 'E') { scienticNotationFound = TRUE; break; } } return scienticNotationFound; } void parseFormat (char *format, char *width, char *decimal, int *foundDecimal) { int i, j, k; /* If the value of the FORMAT attributes starts with E (e.g. E10.3), then change the value of E to F since decimal points in real numbers in PDS must be lined up. */ if (format[0] == 'E') format[0] = 'F'; j = 0; /* index for 'width' */ k = 0; /* index for 'decimal' */ *foundDecimal = FALSE; for (i=0; i < strlen(format); i++) { if (format[i] == 'I' || format[i] == 'F' || format[i] == 'A') continue; else if (format[i] == '.') *foundDecimal = TRUE; else if (*foundDecimal) decimal[k++] = format[i]; else width[j++] = format[i]; } width[j] = '\0'; if (k == 0) /* No decimal found in 'format' */ decimal[k++] = '0'; decimal[k] = '\0'; }