/***************************************************************** * Filename: read_sw_info.c * * Usage: * % read_sw_info * where: * : the name of the SeaWinds input file * * Read the attribute information contained in the SeaWinds Level 1A, 1B, * 2A, 2B, and 3 data files in HDF format. * * NOTE: * The HDF library, version 4, must be installed for this program to work. * The National Center for Supercomputing Applications (NCSA) at * http://hdf.ncsa.uiuc.edu freely distributes HDF. * * Author: Richard Chen, PO.DAAC, JPL * Date: 30 May 2002 ******************************************************************/ #include #include /* strtok(); change to strtok_r() if parallelizing */ #include /* isspace() */ #include /* int32, DFACC_RDONLY, SDstart(); includes */ char *getType(int32 dt); int32 checkHDF(int32 retVal, char *funcName, char *param) { if (retVal == FAIL) { fprintf(stderr, "ERROR: %s(", funcName); if (param) fprintf(stderr, "%s", param); fprintf(stderr, ") failed\n"); HEprint(stderr, 0); /* doesn't seem to do anything */ exit(-1); } return(retVal); } /* checkHDF() */ /* The user's guide's "metadata" are HDF's "global attributes". * The user's guide's "data attributes" are HDF's "local attributes". * HDF functions like SDreadattr() can read either global or local attributes. * * Metadata always have storage type char (string); their conceptual type, * determined by their first line, may be int, char, or float. * Data attributes have the same storage type as conceptual type. */ int main(int argc,char *argv[]) { int32 vd_id, sd_id; int32 n_datasets, n_file_attrs; int32 ref_array[128]; /* no way there are more Vdatas than this */ int i, j, k; if (argc < 2) { /* exit if not all parameters are specified */ fprintf(stderr, "usage: %s \n", argv[0]); exit(-1); } /* Print Vdata info; L3 data has none */ checkHDF(vd_id = Hopen(argv[1], DFACC_RDONLY, 0), "Hopen", argv[1]); checkHDF(Vstart(vd_id), "Vstart", argv[1]); if ((j = VSlone(vd_id, ref_array, sizeof ref_array / sizeof(int32))) > 0) { printf("\n%s: Number of VDatasets: %d\n", argv[1], j); printf("Index:VDataset NumRecords Count*DataType\n"); printf("--------------------------------------------------------\n"); } for (i = 0; i < j; i++) { int32 vdata_id; int32 nRecs, interlace, size, data_type; char fieldList[VSNAMELENMAX], name[VSNAMELENMAX]; checkHDF(vdata_id = VSattach(vd_id, ref_array[i],"r"), "VSattach",NULL); checkHDF(VSinquire(vdata_id, &nRecs, &interlace, fieldList, &size, name), "VSinquire", NULL); /* assume name == fieldList */ checkHDF(data_type = VFfieldtype(vdata_id, /* not 1 */ 0), "VFfieldtype", name); /*==DFNT_UINT8 */ printf("%d:%-14s %-10d %d * %s\n", i, name, nRecs, size, getType(data_type)); #if 0 /* This is commented out because it adds no information. */ checkHDF(nattrs = VSnattrs(vdata_id), "VSnattrs", name); #endif checkHDF(VSdetach(vdata_id), "VSdetach", name); } Vend(vd_id); Hclose(vd_id); /* Print SDS info. */ sd_id = checkHDF(SDstart(argv[1], DFACC_RDONLY), "SDstart", argv[1]); /* Determine the contents of the input file. */ checkHDF(SDfileinfo(sd_id, &n_datasets, &n_file_attrs), "SDfileinfo", NULL); printf("\n%s: Number of Datasets: %d\n", argv[1], n_datasets); printf("Index:Dataset Dimensions Scale+Offset DataType\n"); printf("----------------------------------------------------------------------------\n"); /* print info on every object, especially their local attributes */ for (i = 0; i < n_datasets; i++) { int32 sds_id, dim_sizes[MAX_VAR_DIMS], rank, data_type, nattrs; char name[MAX_NC_NAME]; float64 cal,cal_error,off,off_err; int32 dtype; char buf[256]; /* help with formatting the output */ memset(dim_sizes, 0, sizeof dim_sizes); /* Initialize dim_sizes */ sds_id = checkHDF(SDselect(sd_id, i), "SDselect", NULL); checkHDF(SDgetinfo(sds_id, name, &rank, dim_sizes, &data_type, &nattrs), "SDgetinfo", name); /* Get predefined local calibration (scale and offset) attributes */ checkHDF(SDgetcal(sds_id, &cal, &cal_error, &off, &off_err, &dtype), "SDgetcal", name); strcpy(buf, "["); for (j = 0; j < rank; j++) { sprintf(buf, "%s%d", buf, dim_sizes[j]); strcat(buf, ((j + 1 < rank) ? "," : "]")); } printf("%2d:%-22s%-13s %-.4f+", i, name, buf, cal); if (off == 0) strcpy(buf, "0 "); else sprintf(buf, "%-.4f", off); printf("%4s %-s\n", buf, getType(data_type)); #if 0 /* This is commented out because it adds little information. */ /* User-defined local attributes including scale_factor, add_offset */ for (j = 0; j < nattrs; j++) { char aname[MAX_NC_NAME]; int32 adata_type, count; SDattrinfo(sds_id, j, aname, &adata_type, &count); printf(" attribute==%s type==%s count==%d\n", aname, getType(adata_type), count); } #endif } /* global attributes are strings. '\n' separates lines. * Line 1 == "int", "char", or "float" * Line 2 == [,] The array size, possibly two dimensional * Line 3+ == The array values. If 2D, 2nd dimension spins faster */ printf("\n%s: Number of Global Attributes: %d\n", argv[1], n_file_attrs); printf("Index:Attribute Value\n"); printf("-----------------------------------------------------------------------------\n"); for (i = 0; i < n_file_attrs; i++) { int32 adata_type, count; char attr_name[MAX_NC_NAME]; char *attr_data; /* metadata are always stored as strings */ char *line1, *tok, *dim1; int dim2; char value[4096] = ""; /* make the string output look better */ checkHDF(SDattrinfo(sd_id, i, attr_name, &adata_type, &count), "SDattrinfo", NULL); if (adata_type != DFNT_CHAR8) fprintf(stderr, /* always strings */ "ERROR: Metadata %s has type %d\n", attr_name, adata_type); if (!(attr_data = (char *) malloc(count * DFKNTsize(adata_type)))) fprintf(stderr, "ERROR: malloc(%d)\n", DFKNTsize(adata_type)); checkHDF(SDreadattr(sd_id, i, attr_data), "SDreadattr", attr_name); line1 = strtok(attr_data, "\n"); /* don't print Line 1 */ dim1 = strtok(NULL, "\n"); dim2 = (tok = strchr(dim1, ',')) ? atoi(tok+1) : 0; for (j = 0; j < atoi(dim1); j++) { if (j) { printf("%30c ", ' '); if (value[0]) strcat(value, " "); } else printf("%2d:%-27s ", i, attr_name); strcat(value, strtok(NULL, "\n")); for (k = 1; k < dim2; k++) sprintf(value, "%s, %s", value, strtok(NULL, "\n")); if ((strcmp(line1, "char") != 0) || (strlen(value) <= 49)) { printf("%s\n", value); value[0] = '\0'; } else { /* metadata value is a long string */ for (k = 49; k > 0; k--) if (isspace(value[k])) { value[k] = '\0'; printf("%s\n", value); strcpy(value, &value[k+1]); break; } if (k == 0) { /* metadata value is a long string w/o spaces */ printf("%.49s\n", value); strcpy(value, &value[49]); } } } if (value[0]) { if (j) printf("%30c ", ' '); printf("%s\n", value); } free(attr_data); } return(SDend(sd_id)); } /* main() */ /* ================================================================== */ /* GET_TYPE: a function which returns a buffer containing the data type in ascii given the definition value (see HDF documentation for conversions). 8/1996 A.V. Tran 7/1998 Adapted by K.L. Perry */ char *getType(int32 dt) { switch(dt) { case DFNT_CHAR : return(" 8-bit character"); case DFNT_UCHAR : return(" 8-bit unsigned character"); case DFNT_INT8 : return(" 8-bit signed integer"); case DFNT_UINT8 : return(" 8-bit unsigned integer"); case DFNT_INT16 : return("16-bit signed integer"); case DFNT_UINT16 : return("16-bit unsigned integer"); case DFNT_INT32 : return("32-bit signed integer"); case DFNT_UINT32 : return("32-bit unsigned integer"); case DFNT_INT64 : return("64-bit signed integer"); case DFNT_UINT64 : return("64-bit unsigned integer"); case DFNT_FLOAT32: return("32-bit floating point"); case DFNT_FLOAT64: return("64-bit floating point"); default : return("unknown number type"); } }