#include "hdf5.h" #include "string.h" #include "stdlib.h" /* For detecting and reporting failures */ #define CHECK(ret, val, where) do { \ if ((ret) == (val)) { \ fprintf(stderr, "*** UNEXPECTED RETURN from %s is %ld at line %4d " \ "in %s\n", where, (long)(ret), (int)__LINE__, __FILE__); \ H5Eprint2(H5E_DEFAULT, stdout); \ } \ } while(0) /* Name of the dimension scales */ #define NRAY "/ScienceData/nray" #define NBIN "/ScienceData/nbin" #define CMPLX_PART "/ScienceData/cmplx_part" /* Size of the dimension scales */ #define NRAY_SIZE 9791 /* number of elements in NRAY */ #define NBIN_SIZE 218 /* number of elements in NBIN */ #define CMPLX_PART_SIZE 2 /* number of elements in CMPLX_PART */ #define CP_LEN 4 /* length of each value in CMPLX_PART */ /* Local attributes */ #define N_GLOBAL_ATTRS 18 #define N_FIELDS 3 #define STANDARD_NAME "standard_name" #define LONG_NAME "long_name" #define CALENDAR "calendar" #define CONTENT_TYPE "coverage_content_type" #define VALID_MIN "valid_min" #define VALID_MAX "valid_max" #define FILL_VALUE "_FillValue" #define COORDINATES "coordinates" #define FLAGS "flag_values" #define FLAGS_MEANING "flag_meanings" #define UNIT "units" #define SCALE_FACTOR "scale_factor" #define ADD_OFFSET "add_offset" /* Alias for dataset names */ #define GEOPHYSICAL_DATA "/Geophysical_Data" #define LATITUDE "/Latitude_of_Observation_Point" #define LONGITUDE "/Longitude_of_Observation_Point" #define PIXEL_DATA_QUALITY "/Pixel_Data_Quality" #define POSITION_IN_ORBIT "/Position_in_Orbit" #define SCAN_TIME "/Scan_Time" #define FILENAME "ecare.h5" #define ATTR_NAME_LEN 80 #define DS_RANK 1 typedef struct { char *obj_name; char *new_attr_name; char *attr_value; } attr_t; /* Array of global attributes */ /* The first field is the old name, just for information */ const attr_t added_attrs[N_GLOBAL_ATTRS] = { {"", "Conventions", "CF-1.7, ACDD-1.3"}, {"", "title", "EarthCARE Cloud Profiling Radar Level 1B"}, {"/HeaderData/VariableProductHeader/MainProductHeader/processingCentre", "institution", ""}, {"/HeaderData/VariableProductHeader/MainProductHeader/originalProductName", "project", ""}, {"/HeaderData/FixedProductHeader/Mission", "program", ""}, {"/HeaderData/FixedProductHeader/Source/Creator", "creator_name", ""}, {"", "creator_type", "institution"}, {"", "standard_name_vocabulary", "CF Standard Name Table (v49, 12 February 2018)"}, {"/HeaderData/FixedProductHeader/File_Name", "id", ""}, {"", "naming_authority", "jp.jaxa.saoc"}, {"/HeaderData/VariableProductHeader/MainProductHeader/productLevel", "processing_level", ""}, {"", "platform", "EarthCARE"}, {"", "instrument", "CPR"}, {"/HeaderData/FixedProductHeader/Notes", "comment", ""}, {"/HeaderData/FixedProductHeader/Source/Creation_Date", "date_created", ""}, {"/HeaderData/VariableProductHeader/MainProductHeader/sensingStartTime", "time_coverage_start", ""}, {"/HeaderData/VariableProductHeader/MainProductHeader/sensingStopTime", "time_coverage_end", ""}, {"", "featureType", "trajectoryProfile"} }; /* Attribute Rank & Dimensions */ #define ATTR_RANK 1 #define ATTR_DIM 1 /* temporary names */ #define FAIL -1 #define SUCCEED 0 /************************************************************************** * Function: add_dstype_attr * Description: Adds a new attribute attr_name to the object obj_id using * the dataset's datatype dtype for the attribute. ****************************************************************************/ void add_dstype_attr(hid_t obj_id, hid_t dtype, char* attr_name, const void *attr_value) { hid_t space = -1; hid_t attr = -1; hsize_t dims[] = {ATTR_DIM}; int ii; herr_t ret = FAIL; /* Create dataspace for attribute */ space = H5Screate(H5S_SCALAR); CHECK(space, FAIL, "H5Screate"); attr = H5Acreate2(obj_id, attr_name, dtype, space, H5P_DEFAULT, H5P_DEFAULT); CHECK(attr, FAIL, "H5Acreate2"); /* Write data to the attribute */ ret = H5Awrite(attr, dtype, attr_value); CHECK(ret, FAIL, "H5Awrite"); /* Close attribute and dataspace */ ret = H5Aclose(attr); CHECK(ret, FAIL, "H5Aclose"); ret = H5Sclose(space); CHECK(ret, FAIL, "H5Sclose"); } /* end of add_dstype_attr() */ /************************************************************************** * Function: add_nonscalar_attr * Description: Adds a non-scalar attribute attr_name to the object obj_id * using the datatype dtype for the attribute. ****************************************************************************/ void add_nonscalar_attr(hid_t obj_id, hid_t dtype, hsize_t dimsize, char* attr_name, const void *attr_value) { hid_t space = -1; hid_t attr = -1; hsize_t dims[] = {dimsize}; int ii; herr_t ret = FAIL; /* Create dataspace for attribute */ space = H5Screate_simple(1, dims, NULL); CHECK(space, FAIL, "H5Screate"); attr = H5Acreate2(obj_id, attr_name, dtype, space, H5P_DEFAULT, H5P_DEFAULT); CHECK(attr, FAIL, "H5Acreate2"); /* Write data to the attribute */ ret = H5Awrite(attr, dtype, attr_value); CHECK(ret, FAIL, "H5Awrite"); /* Close attribute and dataspace */ ret = H5Aclose(attr); CHECK(ret, FAIL, "H5Aclose"); ret = H5Sclose(space); CHECK(ret, FAIL, "H5Sclose"); } /* end of add_nonscalar_attr() */ /************************************************************************** * Function: add_string_attr * Description: Adds a new attribute attr_name to the object obj_id using * the variable length string as datatype for the attribute. ****************************************************************************/ void add_string_attr(hid_t obj_id, const char* attr_name, const void *attr_value) { hid_t vlstr_type = -1; hid_t space = -1; hid_t attr = -1; hsize_t dims[] = {ATTR_DIM}; int ii; herr_t ret = FAIL; CHECK(attr_name, NULL, "add_string_attr: invalid attribute name"); CHECK(attr_value, NULL, "add_string_attr: invalid attribute value buffer"); /* Make the datatype variable-length string for the new attribute */ vlstr_type = H5Tcopy(H5T_C_S1); CHECK(vlstr_type, FAIL, "H5Tcopy"); ret = H5Tset_size(vlstr_type, H5T_VARIABLE); CHECK(ret, FAIL, "H5Tset_size"); /* Create dataspace for attribute */ space = H5Screate(H5S_SCALAR); CHECK(space, FAIL, "H5Screate"); attr = H5Acreate2(obj_id, attr_name, vlstr_type, space, H5P_DEFAULT, H5P_DEFAULT); CHECK(attr, FAIL, "H5Acreate2"); /* Write data to the attribute */ ret = H5Awrite(attr, vlstr_type, &attr_value); CHECK(ret, FAIL, "H5Awrite"); /* Close all items */ ret = H5Sclose(space); CHECK(ret, FAIL, "H5Sclose"); ret = H5Tclose(vlstr_type); CHECK(ret, FAIL, "H5Tclose"); ret = H5Aclose(attr); CHECK(ret, FAIL, "H5Aclose"); } /* end of add_string_attr() */ /************************************************************************** * Function: add_dimscale * Description: Adds a new dimension scale dms_name to the file. ****************************************************************************/ void add_dimscale(hid_t file, const char *dms_name, hid_t ds_type, hsize_t dim_size, const void* buf) { hid_t dataset = FAIL; hid_t space = FAIL; hsize_t space_dim[] = {dim_size}; herr_t ret = SUCCEED; /* Create a simple dataspace */ space = H5Screate_simple(DS_RANK, space_dim, NULL); CHECK(space, FAIL, "H5Screate"); dataset = H5Dcreate2(file, dms_name, ds_type, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dcreate2"); /* Write data to the dataset. */ ret = H5Dwrite(dataset, ds_type, H5S_ALL , H5S_ALL, H5P_DEFAULT, buf); CHECK(ret, FAIL, "H5Dwrite"); /* Close everything */ ret = H5Sclose(space); CHECK(ret, FAIL, "H5Sclose"); ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); } /* end of add_dimscale() */ /**************************************************************************** * Function: attach_dimscale * Description: Attach a dimension scale dms_name to the dataset at index idx. *****************************************************************************/ void attach_dimscale(hid_t file, const char *dms_name, hid_t dataset, unsigned int idx) { hid_t dim_scale = FAIL; herr_t ret = SUCCEED; /* Open the dimension scale */ dim_scale = H5Dopen2(file, dms_name, H5P_DEFAULT); CHECK(dim_scale, FAIL, "H5Dopen2"); /* Attach the dimension scale to the idx'th dimension of the dataset */ ret = H5DSattach_scale(dataset, dim_scale, idx); CHECK(ret, FAIL, "H5DSattach_scale"); ret = H5Dclose(dim_scale); CHECK(ret, FAIL, "H5Dclose"); } /* end of attach_dimscale */ /**************************************************************************** * Function: copy_attr_from_ds * Description: Reads the values from the dataset ds_name and stores them * in a new attribute new_attr_name. *****************************************************************************/ void copy_attr_from_ds(hid_t file, const char* ds_name, const char* new_attr_name) { hid_t dataset = FAIL, dtype = FAIL, dspace = FAIL; hid_t attr = FAIL; hssize_t num_elems = 0; void *ds_buf = NULL; size_t type_size = 0; hid_t p_type = FAIL; herr_t ret = SUCCEED; /* Validate arguments */ CHECK(ds_name, NULL, "copy_attr_from_ds: invalid dataset name"); CHECK(new_attr_name, NULL, "copy_attr_from_ds: invalid attribute name"); /* * Open the dataset to read its info and values */ /* Open dataset */ dataset = H5Dopen2(file, ds_name, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); /* Get dataset's datatype and its size */ dtype = H5Dget_type(dataset); CHECK(dtype, FAIL, "H5Dget_type"); type_size = H5Tget_size(dtype); CHECK(type_size, FAIL, "H5Tget_size"); /* Get dataset's dataspace */ dspace = H5Dget_space(dataset); CHECK(dspace, FAIL, "H5Dget_space"); /* Get the size for buffer */ num_elems = H5Sget_simple_extent_npoints(dspace); CHECK(num_elems, FAIL, "H5Sget_simple_extent_npoints"); /* Allocate buffer for dataset values */ ds_buf = malloc(num_elems * type_size + 1); CHECK(ds_buf, NULL, "H5Aopen"); /* Read in the values */ ret = H5Dread(dataset, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, ds_buf); CHECK(ret, FAIL, "H5Dread"); /* * Create new attribute and write data from the dataset. */ attr = H5Acreate2(file, temp, dtype, dspace, H5P_DEFAULT, H5P_DEFAULT); CHECK(attr, FAIL, "H5Acreate2"); /* Write data to the attribute */ ret = H5Awrite(attr, dtype, ds_buf); CHECK(ret, FAIL, "H5Awrite"); /* Close everything and free buffer */ ret = H5Sclose(dspace); CHECK(ret, FAIL, "H5Sclose"); ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); ret = H5Aclose(attr); CHECK(ret, FAIL, "H5Aclose"); ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); free(ds_buf); } /* copy_attr_from_ds */ /**************************************************************************** * Function: copy_attribute * Description: Copy all the attributes from one dataset to another. *****************************************************************************/ void copy_attribute(hid_t old_dset, hid_t new_dset) { hid_t attr = FAIL, dtype = FAIL, dspace = FAIL, old_attr = FAIL; char attr_name[ATTR_NAME_LEN]; H5O_info_t oinfo; void *buf = NULL; int ii; size_t tsize = 0; hid_t space = FAIL; hid_t p_type = FAIL; herr_t ret = SUCCEED; /* Get object info for the number of attributes */ ret = H5Oget_info(old_dset, &oinfo); CHECK(ret, FAIL, "H5Oget_info"); /* For each attribute, get its info and values then add a same one to the new dataset */ for (ii = 0; ii < oinfo.num_attrs; ii++) { old_attr = H5Aopen_by_idx(old_dset, ".", H5_INDEX_CRT_ORDER, H5_ITER_INC, (hsize_t)ii, H5P_DEFAULT, H5P_DEFAULT); CHECK(old_attr, FAIL, "H5Aopen_by_idx"); ret = H5Aget_name(old_attr, ATTR_NAME_LEN, attr_name); CHECK(ret, FAIL, "H5Aget_name"); dtype = H5Aget_type(old_attr); CHECK(dtype, FAIL, "H5Aget_type"); /* Process depending on the type */ if (H5Tget_class(dtype) == H5T_STRING) { /* UNIT */ tsize = H5Tget_size(dtype); CHECK(ret, FAIL, "H5Aget_name"); buf = (char *)malloc(sizeof(char) * tsize); if (buf == NULL) exit(1); ret = H5Aread(old_attr, dtype, buf); CHECK(ret, FAIL, "H5Aread"); /* Add the unit attribute to the new dataset */ add_string_attr(new_dset, attr_name, buf); } else /* SCALE FACTOR */ { float buf = 0.0; ret = H5Aread(old_attr, dtype, &buf); CHECK(ret, FAIL, "H5Aread"); /* Add scale factor to the new dataset */ add_dstype_attr(new_dset, dtype, attr_name, (const void*)&buf); } /* not H5T_STRING */ ret = H5Aclose(old_attr); CHECK(ret, FAIL, "H5Aclose"); } } /* copy_attribute */ /**************************************************************************** * Function: replace_dataset * Description: Replace the dataset old_name with a new dataset new_name. *****************************************************************************/ void replace_dataset(hid_t file, const char *old_name, const char *new_name, int rank, hsize_t *dims, void* buf) { hid_t dataset = FAIL; hid_t dtype = FAIL; hid_t space = FAIL; hid_t new_dataset = FAIL; int ii, jj; void *data = NULL; herr_t ret = SUCCEED; /* Open dataset old dataset and get its datatype */ dataset = H5Dopen2(file, old_name, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); dtype = H5Dget_type(dataset); CHECK(dtype, FAIL, "H5Dget_type"); /* Create dataspace for new dataset */ space = H5Screate_simple(rank, dims, NULL); CHECK(space, FAIL, "H5Screate"); ret = H5Dread(dataset, dtype, space, H5S_ALL, H5P_DEFAULT, buf); CHECK(ret, FAIL, "H5Dread"); /* Create new dataset */ new_dataset = H5Dcreate2(file, new_name, dtype, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); CHECK(new_dataset, FAIL, "H5Dcreate2"); /* Copy current attributes from old dataset to new dataset */ copy_attribute(dataset, new_dataset); ret = H5Dwrite(new_dataset, dtype, space, H5S_ALL, H5P_DEFAULT, buf); CHECK(ret, FAIL, "H5Dwrite"); ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); ret = H5Dclose(new_dataset); CHECK(ret, FAIL, "H5Dclose"); /* Delete old dataset */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret = H5Ldelete(file, old_name, H5P_DEFAULT); CHECK(ret, FAIL, "H5Ldelete"); } /* Main program */ int main() { hid_t file = FAIL; hid_t group = FAIL; hid_t dataset = FAIL, dtype = FAIL; hid_t new_dataset = FAIL; hid_t cptype = FAIL; uint8_t nbin_buf[NBIN_SIZE]; uint16_t nray_buf[NRAY_SIZE]; char cp_buf[2][5] = {"real", "imag"}; herr_t ret = SUCCEED; int ii, jj; /* Open the netCDF file to convert */ file = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT); CHECK(file, FAIL, "H5Fopen"); /* Add attributes to various groups using new data or taking data from existing datasets */ for (ii = 0; ii < N_GLOBAL_ATTRS; ii++) { /* If there is no existing dataset to be used for this attribute, create the new attribute using the hard-coded attribute values */ if (added_attrs[ii].obj_name[0] == '\0') { fprintf(stderr, "adding string attribute: %s\n", added_attrs[ii].new_attr_name); add_string_attr(file, added_attrs[ii].new_attr_name, (const void*)added_attrs[ii].attr_value); } /* Otherwise, copy values from the dataset to the new attribute */ else { fprintf(stderr, "from ds_name = %s\n", added_attrs[ii].obj_name); fprintf(stderr, " --> attribute name = %s\n", added_attrs[ii].new_attr_name); copy_attr_from_ds(file, added_attrs[ii].obj_name, added_attrs[ii].new_attr_name); } } #if 0 /* * Dimension scales to be attached to some datasets */ /* Add dimension scale NRAY */ for (ii = 0; ii < NRAY_SIZE; ii++) nray_buf[ii] = ii; add_dimscale(file, NRAY, H5T_NATIVE_UINT16, H5S_UNLIMITED, (void*) nray_buf); /* Add dimension scale NBIN */ for (ii = 0; ii < NBIN_SIZE; ii++) nbin_buf[ii] = ii; add_dimscale(file, NBIN, H5T_NATIVE_UINT8, NBIN_SIZE, (void*) nbin_buf); /* Add dimension scale CMPLX_PART */ cptype = H5Tcopy(H5T_C_S1); ret = H5Tset_size(cptype, CP_LEN); add_dimscale(file, CMPLX_PART, cptype, CMPLX_PART_SIZE, (void*) cp_buf); /* * Add missing attributes and attach dimension scales to datasets */ /* Dataset /Scan Time */ { float valid_min = 0; float rdata[SCAN_SIZE]; float newdata[SCAN_SIZE]; hsize_t dims[1] = {SCAN_SIZE}; replace_dataset(file, "/Scan Time", SCAN_TIME, 1, dims, rdata); /* Open dataset SCAN_TIME */ dataset = H5Dopen2(file, SCAN_TIME, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); dtype = H5Dget_type(dataset); CHECK(dtype, FAIL, "H5Dget_type"); /* Add missing attributes */ add_string_attr(dataset, STANDARD_NAME, "time"); add_string_attr(dataset, CALENDAR, "gregorian"); add_string_attr(dataset, CONTENT_TYPE, "coordinate"); add_string_attr(dataset, UNIT, "seconds since 1993-01-01 00:00:00"); add_dstype_attr(dataset, dtype, VALID_MIN, (const void*)&valid_min); /* Attach the dimension scale SCAN to the first dimension */ attach_dimscale(file, SCAN, dataset, 0); /* Close the dataset and datatype */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); } /* Dataset /Latitude of Observation Point */ { float valid_min = -90, valid_max = 90, fill_value = -9999; float rdata[SCAN_SIZE][PIXEL_SIZE]; float newdata[SCAN_SIZE][PIXEL_SIZE]; hsize_t dims[2] = {SCAN_SIZE, PIXEL_SIZE}; replace_dataset(file, "/Latitude of Observation Point", LATITUDE, 2, dims, rdata); /* Open dataset /Latitude of Observation Point */ dataset = H5Dopen2(file, LATITUDE, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); dtype = H5Dget_type(dataset); CHECK(dtype, FAIL, "H5Dget_type"); /* Add missing attributes */ add_string_attr(dataset, STANDARD_NAME, "latitude"); add_string_attr(dataset, CONTENT_TYPE, "coordinate"); add_string_attr(dataset, UNIT, "degrees_north"); add_dstype_attr(dataset, dtype, VALID_MIN, (const void*)&valid_min); add_dstype_attr(dataset, dtype, VALID_MAX, (const void*)&valid_max); add_dstype_attr(dataset, dtype, FILL_VALUE, (const void*)&fill_value); /* Attach the dimension scale SCAN to the first dimension */ attach_dimscale(file, SCAN, dataset, 0); /* Attach the dimension scale PIXEL to the second dimension */ attach_dimscale(file, PIXEL, dataset, 1); /* Close the dataset and datatype */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); } /* Dataset /Longitude of Observation Point */ { float valid_min = -180, valid_max = 180, fill_value = -9999; float rdata[SCAN_SIZE][PIXEL_SIZE]; float newdata[SCAN_SIZE][PIXEL_SIZE]; hsize_t dims[2] = {SCAN_SIZE, PIXEL_SIZE}; replace_dataset(file, "/Longitude of Observation Point", LONGITUDE, 2, dims, rdata); /* Open dataset /Longitude of Observation Point */ dataset = H5Dopen2(file, LONGITUDE, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); dtype = H5Dget_type(dataset); CHECK(dtype, FAIL, "H5Dget_type"); /* Add missing attributes */ add_string_attr(dataset, STANDARD_NAME, "longitude"); add_string_attr(dataset, CONTENT_TYPE, "coordinate"); add_string_attr(dataset, UNIT, "degrees_east"); add_dstype_attr(dataset, dtype, VALID_MIN, (const void*)&valid_min); add_dstype_attr(dataset, dtype, VALID_MAX, (const void*)&valid_max); add_dstype_attr(dataset, dtype, FILL_VALUE, (const void*)&fill_value); /* Attach the dimension scale SCAN to the first dimension */ attach_dimscale(file, SCAN, dataset, 0); /* Attach the dimension scale PIXEL to the second dimension */ attach_dimscale(file, PIXEL, dataset, 1); /* Close the dataset and datatype */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); } /* Dataset /Position in Orbit */ { float valid_min = 0; float rdata[SCAN_SIZE]; float newdata[SCAN_SIZE]; hsize_t dims[1] = {SCAN_SIZE}; replace_dataset(file, "/Position in Orbit", POSITION_IN_ORBIT, 1, dims, rdata); /* Open dataset /Position in Orbit */ dataset = H5Dopen2(file, POSITION_IN_ORBIT, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); dtype = H5Dget_type(dataset); CHECK(dtype, FAIL, "H5Dget_type"); /* Add missing attributes */ add_string_attr(dataset, COORDINATES, "Scan_Time"); add_string_attr(dataset, CONTENT_TYPE, "auxiliaryInformation"); add_dstype_attr(dataset, dtype, VALID_MIN, (const void*)&valid_min); /* Attach the dimension scale SCAN to the first dimension */ attach_dimscale(file, SCAN, dataset, 0); /* Close the dataset and datatype */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); } /* Dataset GEOPHYSICAL_DATA */ { hid_t space = FAIL; hsize_t dims[2] = {SCAN_SIZE, PIXEL_SIZE}; short valid_min = 0, valid_max = 1000; short rdata[SCAN_SIZE][PIXEL_SIZE]; short newdata[SCAN_SIZE][PIXEL_SIZE]; double scale_factor = 0.1; double add_offset = 0.0; short fill_value = -32768; replace_dataset(file, "/Geophysical Data", GEOPHYSICAL_DATA, 2, dims, rdata); /* Open dataset GEOPHYSICAL_DATA */ dataset = H5Dopen2(file, GEOPHYSICAL_DATA, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); dtype = H5Dget_type(dataset); CHECK(dtype, FAIL, "H5Dget_type"); add_string_attr(dataset, LONG_NAME, "Sea Ice Concentration"); /* Add missing attributes */ add_string_attr(dataset, STANDARD_NAME, "sea_ice_area_fraction"); add_dstype_attr(dataset, dtype, VALID_MIN, (const void*)&valid_min); add_dstype_attr(dataset, dtype, VALID_MAX, (const void*)&valid_max); add_dstype_attr(dataset, dtype, FILL_VALUE, (const void*)&fill_value); add_dstype_attr(dataset, H5T_IEEE_F64LE, ADD_OFFSET, (const void*)&add_offset); add_dstype_attr(dataset, H5T_IEEE_F64LE, SCALE_FACTOR, (const void*)&scale_factor); add_string_attr(dataset, COORDINATES, "Scan_Time Longitude_of_Observation_Point Latitude_of_Observation_Point"); /* Attach the dimension scale SCAN to the first dimension */ attach_dimscale(file, SCAN, dataset, 0); /* Attach the dimension scale PIXEL to the second dimension */ attach_dimscale(file, PIXEL, dataset, 1); /* Close the dataset and datatype */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); } /* Dataset /Pixel Data Quality */ { int valid_min = -128, valid_max = 64; char flag_values[9] = {0, 1, 2, 4, 16, 32, 64, -128, -112}; uint8_t rdata[SCAN_SIZE][PIXEL_SIZE]; uint8_t newdata[SCAN_SIZE][PIXEL_SIZE]; hsize_t dims[2] = {SCAN_SIZE, PIXEL_SIZE}; hid_t space = FAIL; float scale_factor = 1; hid_t new_dataset = FAIL; replace_dataset(file, "/Pixel Data Quality", PIXEL_DATA_QUALITY, 2, dims, rdata); dataset = H5Dopen2(file, PIXEL_DATA_QUALITY, H5P_DEFAULT); CHECK(dataset, FAIL, "H5Dopen2"); dtype = H5Dget_type(dataset); CHECK(dtype, FAIL, "H5Dget_type"); /* ret = H5Ldelete(file, "/Pixel Data Quality", H5P_DEFAULT); */ /* Add missing attributes */ add_string_attr(dataset, CONTENT_TYPE, "qualityInformation"); add_dstype_attr(dataset, dtype, VALID_MIN, (const void*)&valid_min); add_dstype_attr(dataset, dtype, VALID_MAX, (const void*)&valid_max); add_nonscalar_attr(dataset, dtype, 9, FLAGS, (const void*)flag_values); add_string_attr(dataset, FLAGS_MEANING, "normal SST_mask Latitude_mask Land_filter_target_pixel RFI Land_mask Satellite_attitude_out Invalid_TB L1_Land_Ocean_Flag_Error"); /* Attach the dimension scale SCAN to the second dimension */ attach_dimscale(file, SCAN, dataset, 0); /* Attach the dimension scale PIXEL to the third dimension */ attach_dimscale(file, PIXEL, dataset, 1); /* Close the dataset and datatype */ ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); ret = H5Tclose(dtype); CHECK(ret, FAIL, "H5Tclose"); } #endif ret = H5Fclose(file); CHECK(ret, FAIL, "H5Fclose"); return(0); } /* main */ /******************************************************************************* Alternative approaches: - Instead of hardcoding the attribute values, they can be read from the previous attribute. *******************************************************************************/