#include "hdf5.h" #include "h5test.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) /* Print the current location on the standard output stream. */ #define AT() printf (" at %s:%d in %s()...\n", \ __FILE__, __LINE__, FUNC); #define TEST_ERROR {H5_FAILED(); AT(); goto error;} /* 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 5 /* 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 */ if ((space = H5Screate(H5S_SCALAR)) < 0) TEST_ERROR attr = H5Acreate2(obj_id, attr_name, dtype, space, H5P_DEFAULT, H5P_DEFAULT); if (attr < 0) TEST_ERROR /* Write data to the attribute */ if ((ret = H5Awrite(attr, dtype, attr_value)) < 0) TEST_ERROR /* Close attribute and dataspace */ if ((ret = H5Aclose(attr)) < 0) TEST_ERROR if ((ret = H5Sclose(space)) < 0) TEST_ERROR error: } /* 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 */ if ((space = H5Screate_simple(1, dims, NULL)) < 0) TEST_ERROR /* Create new attribute */ attr = H5Acreate2(obj_id, attr_name, dtype, space, H5P_DEFAULT, H5P_DEFAULT); if (attr < 0) TEST_ERROR /* Write data to the attribute */ if ((ret = H5Awrite(attr, dtype, attr_value)) < 0) TEST_ERROR /* Close attribute and dataspace */ if ((ret = H5Aclose(attr)) < 0) TEST_ERROR if ((ret = H5Sclose(space)) < 0) TEST_ERROR error: } /* 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; if (attr_name == NULL) { fprintf(stderr, "add_string_attr: invalid attribute name"); TEST_ERROR } if (attr_value == NULL) { fprintf(stderr, "add_string_attr: invalid attribute value buffer"); TEST_ERROR } /* Make the datatype variable-length string for the new attribute */ if ((vlstr_type = H5Tcopy(H5T_C_S1)) < 0) TEST_ERROR if ((ret = H5Tset_size(vlstr_type, H5T_VARIABLE)) < 0) TEST_ERROR /* Create dataspace for attribute */ if ((space = H5Screate(H5S_SCALAR)) < 0) TEST_ERROR /* Create new attribute */ attr = H5Acreate2(obj_id, attr_name, vlstr_type, space, H5P_DEFAULT, H5P_DEFAULT); if (attr < 0) TEST_ERROR /* Write data to the attribute */ if ((ret = H5Awrite(attr, vlstr_type, &attr_value)) < 0) TEST_ERROR /* Close all items */ if ((ret = H5Sclose(space)) < 0) TEST_ERROR if ((ret = H5Tclose(vlstr_type)) < 0) TEST_ERROR if ((ret = H5Aclose(attr)) < 0) TEST_ERROR error: H5E_BEGIN_TRY { H5Sclose(space); H5Tclose(vlstr_type); H5Aclose(attr); } H5E_END_TRY; exit(1); } /* 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 *dims, hsize_t *max_dims, const void* buf, hid_t dcpl) */ void add_dimscale(hid_t file, const char *dms_name, hid_t ds_type, hsize_t dim_size, hsize_t max_dim_size, const void* buf) { hid_t dataset = FAIL; hid_t space = FAIL; hid_t dcpl = H5P_DEFAULT; hsize_t dim[1] = {dim_size}; hsize_t max_dim[1] = {max_dim_size}; herr_t ret = SUCCEED; if (max_dim_size == H5S_UNLIMITED) { /* Create dataset creation property list for chunking because NRAY has unlimited dim */ if ((dcpl = H5Pcreate(H5P_DATASET_CREATE)) < 0) TEST_ERROR /* Set chunked layout */ if ((H5Pset_chunk(dcpl, 1, dim)) < 0) TEST_ERROR } /* Create a simple dataspace */ if ((space = H5Screate_simple(DS_RANK, dim, max_dim)) < 0) TEST_ERROR fprintf(stderr, "creating dataset %s\n", dms_name); dataset = H5Dcreate2(file, dms_name, ds_type, space, H5P_DEFAULT, dcpl, H5P_DEFAULT); if (dataset < 0) TEST_ERROR /* Write data to the dataset. */ if ((ret = H5Dwrite(dataset, ds_type, H5S_ALL , H5S_ALL, H5P_DEFAULT, buf)) < 0) TEST_ERROR /* Close everything */ if ((ret = H5Sclose(space)) < 0) TEST_ERROR if ((ret = H5Dclose(dataset)) < 0) TEST_ERROR error: } /* 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 */ if ((dim_scale = H5Dopen2(file, dms_name, H5P_DEFAULT)) < 0) TEST_ERROR /* Attach the dimension scale to the idx'th dimension of the dataset */ if ((ret = H5DSattach_scale(dataset, dim_scale, idx)) < 0) TEST_ERROR if ((ret = H5Dclose(dim_scale)) < 0) TEST_ERROR error: } /* 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 */ if ((dataset = H5Dopen2(file, ds_name, H5P_DEFAULT)) < 0) TEST_ERROR /* Get dataset's datatype and its size */ if ((dtype = H5Dget_type(dataset)) < 0) TEST_ERROR if ((type_size = H5Tget_size(dtype)) < 0) TEST_ERROR /* Get dataset's dataspace */ if ((dspace = H5Dget_space(dataset)) < 0) TEST_ERROR /* Get the size for buffer */ if ((num_elems = H5Sget_simple_extent_npoints(dspace)) < 0) TEST_ERROR /* Allocate buffer for dataset values */ if ((ds_buf = malloc(num_elems * type_size + 1)) < 0) TEST_ERROR /* Read in the values */ if ((ret = H5Dread(dataset, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, ds_buf)) < 0) TEST_ERROR /* * Create new attribute and write data from the dataset. */ attr = H5Acreate2(file, new_attr_name, dtype, dspace, H5P_DEFAULT, H5P_DEFAULT); if (attr < 0) TEST_ERROR /* Write data to the attribute */ if ((ret = H5Awrite(attr, dtype, ds_buf)) < 0) TEST_ERROR /* Close everything and free buffer */ if ((ret = H5Sclose(dspace)) < 0) TEST_ERROR if ((ret = H5Tclose(dtype)) < 0) TEST_ERROR if ((ret = H5Aclose(attr)) < 0) TEST_ERROR if ((ret = H5Dclose(dataset)) < 0) TEST_ERROR free(ds_buf); error: } /* 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 */ if ((ret = H5Oget_info(old_dset, &oinfo)) < 0) TEST_ERROR /* 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); if (old_attr < 0) TEST_ERROR if ((ret = H5Aget_name(old_attr, ATTR_NAME_LEN, attr_name)) < 0) TEST_ERROR if ((dtype = H5Aget_type(old_attr)) < 0) TEST_ERROR /* Process depending on the type */ if (H5Tget_class(dtype) == H5T_STRING) { /* UNIT */ /* Get the string size */ if ((tsize = H5Tget_size(dtype)) < 0) TEST_ERROR buf = (char *)malloc(sizeof(char) * tsize); if (buf == NULL) TEST_ERROR if ((ret = H5Aread(old_attr, dtype, buf)) < 0) TEST_ERROR /* Add the unit attribute to the new dataset */ add_string_attr(new_dset, attr_name, buf); } else /* SCALE FACTOR */ { float buf = 0.0; if ((ret = H5Aread(old_attr, dtype, &buf)) < 0) TEST_ERROR /* Add scale factor to the new dataset */ add_dstype_attr(new_dset, dtype, attr_name, (const void*)&buf); } /* not H5T_STRING */ if ((ret = H5Aclose(old_attr)) < 0) TEST_ERROR } } /* 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 */ if ((dataset = H5Dopen2(file, old_name, H5P_DEFAULT)) < 0) TEST_ERROR if ((dtype = H5Dget_type(dataset)) < 0) TEST_ERROR /* Create dataspace for new dataset */ if ((space = H5Screate_simple(rank, dims, NULL)) < 0) TEST_ERROR if ((ret = H5Dread(dataset, dtype, space, H5S_ALL, H5P_DEFAULT, buf)) < 0) TEST_ERROR /* Create new dataset */ new_dataset = H5Dcreate2(file, new_name, dtype, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); if (new_dataset < 0) TEST_ERROR /* 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); if (ret < 0) TEST_ERROR /* Close IDs */ if ((ret = H5Tclose(dtype)) < 0) TEST_ERROR if ((ret = H5Dclose(new_dataset)) < 0) TEST_ERROR if ((ret = H5Dclose(dataset)) < 0) TEST_ERROR /* Delete old dataset */ if ((ret = H5Ldelete(file, old_name, H5P_DEFAULT)) < 0) TEST_ERROR } static int link_iterate_cb(hid_t group_id, const char *link_name, const H5L_info_t *info, void *_op_data) { link_iter_info_t *op_data = (link_iter_info_t *)_op_data; /* User data */ char objname[NAME_BUF_SIZE]; /* Object name */ H5L_info_t my_info; /* Local link info */ /* Increment # of times the callback was called */ op_data->ncalled++; /* Get the link information directly to compare */ if(H5Lget_info(group_id, link_name, &my_info, H5P_DEFAULT) < 0) return(H5_ITER_ERROR); /* Check more things for link iteration (vs. group iteration) */ if(info) { /* Check for correct order of iteration */ /* (if we are operating in increasing or decreasing order) */ if(op_data->order != H5_ITER_NATIVE) if(info->corder != op_data->curr) return(H5_ITER_ERROR); /* Compare link info structs */ if(info->type != my_info.type) return(H5_ITER_ERROR); if(info->corder_valid != my_info.corder_valid) return(H5_ITER_ERROR); if(info->corder != my_info.corder) return(H5_ITER_ERROR); if(info->cset != my_info.cset) return(H5_ITER_ERROR); if(H5F_addr_ne(info->u.address, my_info.u.address)) return(H5_ITER_ERROR); } /* end if */ /* Verify name of link */ sprintf(objname, "filler %02u", (unsigned)my_info.corder); if(HDstrcmp(link_name, objname)) return(H5_ITER_ERROR); /* Check if we've visited this link before */ if((size_t)op_data->curr >= op_data->max_visit) return(H5_ITER_ERROR); if(op_data->visited[op_data->curr]) return(H5_ITER_ERROR); op_data->visited[op_data->curr] = TRUE; /* Advance to next value, in correct direction */ if(op_data->order != H5_ITER_DEC) op_data->curr++; else op_data->curr--; /* Check for stopping in the middle of iterating */ if(op_data->stop > 0) if(--op_data->stop == 0) return(CORDER_ITER_STOP); return(H5_ITER_CONT); } /* end link_iterate_cb() */ /* 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; hid_t dcpl = FAIL; hsize_t dim, max_dim; hsize_t dimu[1], max_dimu[1]; 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 */ if ((file = H5Fopen(FILENAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) TEST_ERROR /* 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); } } /* * Adding dimension scales */ /* Add dimension scale NRAY */ for (ii = 0; ii < NRAY_SIZE; ii++) nray_buf[ii] = ii; /* Create and write to NRAY, dim = NRAY_SIZE, max dim = H5S_UNLIMITED */ dim_scale = add_dimscale(file, NRAY, H5T_NATIVE_UINT16, NRAY_SIZE, H5S_UNLIMITED, (void*) nray_buf); add_string_attr(dim_scale, LONG_NAME, "along-track ray"); if ((ret = H5Dclose(dim_scale)) < 0) TEST_ERROR /* Add dimension scale NBIN */ for (ii = 0; ii < NBIN_SIZE; ii++) nbin_buf[ii] = ii; dim_scale = add_dimscale(file, NBIN, H5T_NATIVE_UINT8, NBIN_SIZE, NULL, (void*) nbin_buf); add_string_attr(dim_scale, LONG_NAME, "bin number"); if ((ret = H5Dclose(dim_scale)) < 0) TEST_ERROR /* Add dimension scale CMPLX_PART */ cptype = H5Tcopy(H5T_C_S1); if ((ret = H5Tset_size(cptype, CP_LEN)) < 0) TEST_ERROR dim_scale = add_dimscale(file, CMPLX_PART, cptype, CMPLX_PART_SIZE, NULL, (void*) cp_buf); add_string_attr(dim_scale, LONG_NAME, "complex number part"); if ((ret = H5Dclose(dim_scale)) < 0) TEST_ERROR /* Open group /ScienceData, then for each DS that has an attribute longName, add an attribute long_name using longName's value */ group_ScienceData = H5Gopen2(file, SCIENCE_DATA, H5P_DEFAULT) if (group_ScienceData < 0) TEST_ERROR /* Get the datasets and if any has attribute longName, create a new attribute */ { /* link_iterate */ idx_type = H5_INDEX_CRT_ORDER; order = H5_ITER_INC; skip = 0; if(link_iterate_check(group_id, idx_type, order, u, &iter_info) < 0) TEST_ERROR if(H5Literate(group_ScienceData, idx_type, order, &skip, link_iterate_cb, iter_info) < 0) TEST_ERROR } /* end of link_iterate */ #if 0 /* * 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 */ if ((ret = H5Dclose(dataset)) < 0) TEST_ERROR 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 */ if ((ret = H5Dclose(dataset); CHECK(ret, FAIL, "H5Dclose"); if ((ret = H5Tclose(dtype)) < 0) TEST_ERROR 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 */ if ((ret = H5Dclose(dataset)) < 0) TEST_ERROR CHECK(ret, FAIL, "H5Dclose"); if ((ret = H5Tclose(dtype)) < 0) TEST_ERROR 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 */ if ((ret = H5Dclose(dataset)) < 0) TEST_ERROR CHECK(ret, FAIL, "H5Dclose"); if ((ret = H5Tclose(dtype)) < 0) TEST_ERROR 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); if ((dataset = H5Dopen2(file, PIXEL_DATA_QUALITY, H5P_DEFAULT)) < 0) TEST_ERROR if ((dtype = H5Dget_type(dataset)) < 0) TEST_ERROR /* 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 */ if ((ret = H5Dclose(dataset)) < 0) TEST_ERROR if ((ret = H5Tclose(dtype)) < 0) TEST_ERROR } #endif if ((ret = H5Fclose(file)) < 0) TEST_ERROR return(0); error: } /* main */