mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-21 08:39:46 +08:00
784 lines
27 KiB
C
784 lines
27 KiB
C
/* This is part of the netCDF package.
|
|
Copyright 2018 University Corporation for Atmospheric Research/Unidata
|
|
See COPYRIGHT file for conditions of use.
|
|
|
|
Test HDF5 file code. These are not intended to be exhaustive tests,
|
|
but they use HDF5 the same way that netCDF-4 does, so if these
|
|
tests don't work, than netCDF-4 won't work either.
|
|
|
|
$Id: tst_h_dimscales.c,v 1.15 2010/06/01 15:34:51 ed Exp $
|
|
*/
|
|
#include "h5_err_macros.h"
|
|
#include <hdf5.h>
|
|
#include <H5DSpublic.h>
|
|
|
|
#define FILE_NAME "tst_h_dimscales.h5"
|
|
#define STR_LEN 255
|
|
#define MAX_DIMS 255
|
|
|
|
herr_t alien_visitor(hid_t did, unsigned dim, hid_t dsid,
|
|
void *visitor_data)
|
|
{
|
|
char name1[STR_LEN], name2[STR_LEN];
|
|
H5G_stat_t statbuf;
|
|
|
|
(*(hid_t *)visitor_data) = dsid;
|
|
if (H5Iget_name(did, name1, STR_LEN) < 0) ERR;
|
|
if (H5Iget_name(dsid, name2, STR_LEN) < 0) ERR;
|
|
/* printf("visiting did 0x%x dim %d dsid 0x%x name of did %s \n", */
|
|
/* did, dim, dsid, name1); */
|
|
/* printf("name of dsid: %s\n", name2); */
|
|
|
|
if (H5Gget_objinfo(did, ".", 1, &statbuf) < 0) ERR;
|
|
/* printf("statbuf.fileno = %d statbuf.objno = %d\n",
|
|
statbuf.fileno, statbuf.objno);*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
rec_scan_group(hid_t grpid)
|
|
{
|
|
hid_t spaceid, datasetid = 0, child_grpid;
|
|
hsize_t num_obj, i;
|
|
int obj_class;
|
|
char obj_name[STR_LEN + 1];
|
|
htri_t is_scale;
|
|
int num_scales;
|
|
hsize_t dims[MAX_DIMS], max_dims[MAX_DIMS];
|
|
int ndims, d;
|
|
|
|
/* Loop through datasets to find variables. */
|
|
if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
|
|
for (i=0; i<num_obj; i++)
|
|
{
|
|
/* Get the type (i.e. group, dataset, etc.), and the name of
|
|
* the object. */
|
|
if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
|
|
if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
|
|
/*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n",
|
|
obj_class, obj_name);*/
|
|
|
|
/* Deal with groups and datasets, ignore the rest. */
|
|
switch(obj_class)
|
|
{
|
|
case H5G_GROUP:
|
|
if ((child_grpid = H5Gopen1(grpid, obj_name)) < 0) ERR;
|
|
if (rec_scan_group(child_grpid)) ERR;
|
|
break;
|
|
case H5G_DATASET:
|
|
/* Open the dataset. */
|
|
if ((datasetid = H5Dopen1(grpid, obj_name)) < 0) ERR;
|
|
/*printf("\nobj_name %s\n", obj_name);*/
|
|
|
|
/* Get the dimensions of this dataset. */
|
|
if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
|
|
if ((ndims = H5Sget_simple_extent_ndims(spaceid)) < 0) ERR;
|
|
if (ndims > MAX_DIMS) ERR;
|
|
if (H5Sget_simple_extent_dims(spaceid, dims, max_dims) < 0) ERR;
|
|
|
|
/* Is this a dimscale? */
|
|
if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
|
|
if (is_scale)
|
|
{
|
|
/*printf("dimension scale! Hoorah for the Pirate King!\n");*/
|
|
}
|
|
else
|
|
{
|
|
hid_t visitor_data = 0;
|
|
|
|
/* Here's how to get the number of scales attached
|
|
* to the dataset's dimension 0. */
|
|
if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
|
|
if (num_scales != 1) ERR;
|
|
|
|
/* Go through all dimscales for this var and learn about them. */
|
|
for (d = 0; d < ndims; d++)
|
|
if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor,
|
|
&visitor_data) < 0) ERR;
|
|
}
|
|
if (H5Dclose(datasetid) < 0) ERR;
|
|
break;
|
|
case H5G_TYPE:
|
|
printf("found a type!\n");
|
|
break;
|
|
case H5G_LINK:
|
|
printf("found a link! Yikes!\n");
|
|
break;
|
|
default:
|
|
printf("Unknown object class %d!", obj_class);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main()
|
|
{
|
|
printf("\n*** Checking HDF5 dimension scales.\n");
|
|
#define GRP_NAME "simple_scales"
|
|
#define DIMSCALE_NAME "dimscale"
|
|
#define NAME_ATTRIBUTE "Billy-Bob"
|
|
#define VAR1_NAME "var1"
|
|
#define VAR2_NAME "var2"
|
|
#define VAR3_NAME "var3"
|
|
#define DIM1_LEN 3
|
|
#define DIM2_LEN 2
|
|
#define FIFTIES_SONG "Mamma said they'll be days like this. They'll be days like this, my mamma said."
|
|
|
|
printf("*** Creating simple dimension scales file...");
|
|
{
|
|
hid_t fileid, grpid, dimscaleid;
|
|
hid_t dimscale_spaceid, var1_spaceid, var3_spaceid;
|
|
hid_t var1_datasetid, var2_datasetid, var3_datasetid;
|
|
hsize_t dims[2] = {DIM1_LEN, DIM2_LEN};
|
|
hsize_t dimscale_dims[1] = {DIM1_LEN};
|
|
|
|
/* Open file and create group. */
|
|
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
|
|
H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
|
|
|
|
/* Create our dimension scale. Use the built-in NAME attribute
|
|
* on the dimscale. */
|
|
if ((dimscale_spaceid = H5Screate_simple(1, dimscale_dims,
|
|
dimscale_dims)) < 0) ERR;
|
|
if ((dimscaleid = H5Dcreate1(grpid, DIMSCALE_NAME, H5T_NATIVE_INT,
|
|
dimscale_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;
|
|
|
|
/* Create a 1D variable which uses the dimscale. Attach a label
|
|
* to this scale. */
|
|
if ((var1_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
|
|
if ((var1_datasetid = H5Dcreate1(grpid, VAR1_NAME, H5T_NATIVE_INT,
|
|
var1_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
if (H5DSattach_scale(var1_datasetid, dimscaleid, 0) < 0) ERR;
|
|
if (H5DSset_label(var1_datasetid, 0, FIFTIES_SONG) < 0) ERR;
|
|
|
|
/* Create a 1D variabls that doesn't use the dimension scale. */
|
|
if ((var2_datasetid = H5Dcreate1(grpid, VAR2_NAME, H5T_NATIVE_INT,
|
|
var1_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
|
|
/* Create a 2D dataset which uses the scale for one of its
|
|
* dimensions. */
|
|
if ((var3_spaceid = H5Screate_simple(2, dims, dims)) < 0) ERR;
|
|
if ((var3_datasetid = H5Dcreate1(grpid, VAR3_NAME, H5T_NATIVE_INT,
|
|
var3_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
if (H5DSattach_scale(var3_datasetid, dimscaleid, 0) < 0) ERR;
|
|
|
|
/* Close up the shop. */
|
|
if (H5Dclose(dimscaleid) < 0 ||
|
|
H5Dclose(var1_datasetid) < 0 ||
|
|
H5Dclose(var2_datasetid) < 0 ||
|
|
H5Dclose(var3_datasetid) < 0 ||
|
|
H5Sclose(var1_spaceid) < 0 ||
|
|
H5Sclose(var3_spaceid) < 0 ||
|
|
H5Sclose(dimscale_spaceid) < 0 ||
|
|
H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
|
|
/* HELP! If you are reading this in the future, and time
|
|
* machines have been invented, please come back to July 10,
|
|
* 2005, the Java Java coffee shop in Lafayette, 8:00 am MST +-
|
|
* 20 minutes. Bring back some advanced weapons systems to
|
|
* destroy the sound system here, which is playing 50's rock and
|
|
* roll. Do-op, do-op, la-ma la-ma, ding dong. Save me!!! (Mind
|
|
* you, James Brown is a different story!) */
|
|
}
|
|
SUMMARIZE_ERR;
|
|
printf("*** Checking that simple dimscale file can be read...");
|
|
{
|
|
hid_t fileid, grpid, datasetid = 0;
|
|
hsize_t num_obj, i;
|
|
int obj_class;
|
|
char obj_name[STR_LEN + 1];
|
|
htri_t is_scale;
|
|
int num_scales;
|
|
|
|
/* Reopen the file and group. */
|
|
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gopen1(fileid, GRP_NAME)) < 0) ERR;
|
|
|
|
/* Loop through datasets to find variables. */
|
|
if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
|
|
for (i=0; i<num_obj; i++)
|
|
{
|
|
/* Get the type (i.e. group, dataset, etc.), and the name of the
|
|
* object. Confusingly, this is a different type than the type
|
|
* of a variable. This type might be better called "class" or
|
|
* "type of type" */
|
|
if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
|
|
if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
|
|
/*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/
|
|
|
|
/* Deal with groups and datasets. */
|
|
switch(obj_class)
|
|
{
|
|
case H5G_GROUP:
|
|
break;
|
|
case H5G_DATASET:
|
|
|
|
/*Close the last datasetid, if one is open. */
|
|
if (datasetid > 0)
|
|
{
|
|
H5Dclose(datasetid);
|
|
}
|
|
|
|
if ((datasetid = H5Dopen1(grpid, obj_name)) < 0) ERR;
|
|
if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
|
|
if (is_scale && strcmp(obj_name, DIMSCALE_NAME)) ERR;
|
|
if (is_scale)
|
|
{
|
|
char nom_de_quincey[STR_LEN+1];
|
|
|
|
/* A dimscale comes with a NAME attribute, in
|
|
* addition to its real name. */
|
|
if (H5DSget_scale_name(datasetid, nom_de_quincey,
|
|
STR_LEN) < 0) ERR;
|
|
if (strcmp(nom_de_quincey, NAME_ATTRIBUTE)) ERR;
|
|
|
|
/*printf("found scale %s, NAME %s\n", obj_name, nom_de_quincey);*/
|
|
|
|
}
|
|
else
|
|
{
|
|
char label[STR_LEN+1];
|
|
|
|
/* Here's how to get the number of scales attached
|
|
* to the dataset. I would think that this would
|
|
* return 0 scales for a dataset that doesn't have
|
|
* scales, but instead it errors. So take an error
|
|
* to be the same as no dimension scales. */
|
|
num_scales = H5DSget_num_scales(datasetid, 0);
|
|
if (strcmp(obj_name, VAR1_NAME) == 0 && num_scales != 1) ERR;
|
|
if (strcmp(obj_name, VAR2_NAME) == 0 && num_scales > 0) ERR;
|
|
if (strcmp(obj_name, VAR3_NAME) == 0 && num_scales != 1) ERR;
|
|
|
|
/* There's also a label for dimension 0 of var1. */
|
|
if (strcmp(obj_name, VAR1_NAME) == 0)
|
|
{
|
|
if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
|
|
if (strcmp(label, FIFTIES_SONG)) ERR;
|
|
}
|
|
}
|
|
break;
|
|
case H5G_TYPE:
|
|
break;
|
|
case H5G_LINK:
|
|
break;
|
|
default:
|
|
printf("Unknown object class %d!", obj_class);
|
|
}
|
|
}
|
|
|
|
/* Close up the shop. */
|
|
if (H5Dclose(datasetid) < 0 ||
|
|
H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
printf("*** Creating simple dimension scales file with lots of datasets...");
|
|
|
|
#define NUM_DATASETS 500
|
|
{
|
|
hid_t fileid, grpid, dimscaleid;
|
|
hid_t dimscale_spaceid, var1_spaceid;
|
|
hid_t var1_datasetid[NUM_DATASETS];
|
|
hsize_t dims[2] = {DIM1_LEN, DIM2_LEN};
|
|
hsize_t dimscale_dims[1] = {DIM1_LEN};
|
|
char var_name[STR_LEN + 1];
|
|
int v;
|
|
|
|
/* Open file and create group. */
|
|
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
|
|
H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
|
|
|
|
/* Create our dimension scale. Use the built-in NAME attribute
|
|
* on the dimscale. */
|
|
if ((dimscale_spaceid = H5Screate_simple(1, dimscale_dims,
|
|
dimscale_dims)) < 0) ERR;
|
|
if ((dimscaleid = H5Dcreate1(grpid, DIMSCALE_NAME, H5T_NATIVE_INT,
|
|
dimscale_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;
|
|
|
|
/* Create many 1D datasets which use the dimscale. */
|
|
if ((var1_spaceid = H5Screate_simple(1, dims, dims)) < 0) ERR;
|
|
for (v = 0; v < NUM_DATASETS; v++)
|
|
{
|
|
sprintf(var_name, "var_%d", v);
|
|
if ((var1_datasetid[v] = H5Dcreate1(grpid, var_name, H5T_NATIVE_INT,
|
|
var1_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
if (H5DSattach_scale(var1_datasetid[v], dimscaleid, 0) < 0) ERR;
|
|
}
|
|
|
|
/* Close up the shop. */
|
|
for (v = 0; v < NUM_DATASETS; v++)
|
|
if (H5Dclose(var1_datasetid[v]) < 0) ERR;
|
|
if (H5Dclose(dimscaleid) < 0 ||
|
|
H5Sclose(var1_spaceid) < 0 ||
|
|
H5Sclose(dimscale_spaceid) < 0 ||
|
|
H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
printf("*** Creating a file with an unlimited dimension scale...");
|
|
|
|
{
|
|
hid_t fileid, grpid, spaceid, datasetid, dimscaleid, cparmsid;
|
|
hsize_t dims[1] = {1}, maxdims[1] = {H5S_UNLIMITED};
|
|
|
|
/* Create file and group. */
|
|
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
|
|
H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
|
|
|
|
if ((spaceid = H5Screate_simple(1, dims, maxdims)) < 0) ERR;
|
|
|
|
/* Modify dataset creation properties, i.e. enable chunking */
|
|
if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
|
|
if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;
|
|
|
|
/* Create our dimension scale, as an unlimited dataset. */
|
|
if ((dimscaleid = H5Dcreate1(grpid, DIMSCALE_NAME, H5T_NATIVE_INT,
|
|
spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSset_scale(dimscaleid, NAME_ATTRIBUTE) < 0) ERR;
|
|
|
|
/* Create a variable which uses it. */
|
|
if ((datasetid = H5Dcreate1(grpid, VAR1_NAME, H5T_NATIVE_INT,
|
|
spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSattach_scale(datasetid, dimscaleid, 0) < 0) ERR;
|
|
if (H5DSset_label(datasetid, 0, "dimension label") < 0) ERR;
|
|
|
|
/* Close up the shop. */
|
|
if (H5Dclose(dimscaleid) < 0 ||
|
|
H5Dclose(datasetid) < 0 ||
|
|
H5Sclose(spaceid) < 0 ||
|
|
H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
printf("*** Checking that unlimited dimscale file can be read...");
|
|
|
|
{
|
|
hid_t fileid, grpid, spaceid = 0, datasetid = 0;
|
|
hsize_t volatile num_obj, i;
|
|
int obj_class;
|
|
char obj_name[STR_LEN + 1];
|
|
htri_t is_scale;
|
|
int num_scales;
|
|
hsize_t dims[1], maxdims[1];
|
|
|
|
/* Reopen the file and group. */
|
|
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gopen1(fileid, GRP_NAME)) < 0) ERR;
|
|
|
|
/* Loop through datasets to find variables. */
|
|
if (H5Gget_num_objs(grpid, (hsize_t *)&num_obj) < 0) ERR;
|
|
for (i=0; i<num_obj; i++)
|
|
{
|
|
/* Get the type (i.e. group, dataset, etc.), and the name of
|
|
* the object. */
|
|
if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
|
|
if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
|
|
/*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/
|
|
|
|
/* Deal with groups and datasets. */
|
|
switch(obj_class)
|
|
{
|
|
case H5G_GROUP:
|
|
break;
|
|
case H5G_DATASET:
|
|
|
|
/*Close the last datasetid, if one is open. */
|
|
if (datasetid > 0)
|
|
{
|
|
H5Dclose(datasetid);
|
|
datasetid = 0;
|
|
}
|
|
|
|
/* Open the dataset. */
|
|
if ((datasetid = H5Dopen1(grpid, obj_name)) < 0) ERR;
|
|
|
|
/* This should be an unlimited dataset. */
|
|
if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
|
|
if (H5Sget_simple_extent_dims(spaceid, dims, maxdims) < 0) ERR;
|
|
if (maxdims[0] != H5S_UNLIMITED) ERR;
|
|
|
|
/* Is this a dimscale? */
|
|
if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
|
|
if (is_scale && strcmp(obj_name, DIMSCALE_NAME)) ERR;
|
|
if (is_scale)
|
|
{
|
|
char nom_de_quincey[STR_LEN+1];
|
|
|
|
/* A dimscale comes with a NAME attribute, in
|
|
* addition to its real name. */
|
|
if (H5DSget_scale_name(datasetid, nom_de_quincey, STR_LEN) < 0) ERR;
|
|
/*printf("found scale %s, NAME %s\n", obj_name, nom_de_quincey);*/
|
|
|
|
}
|
|
else
|
|
{
|
|
char label[STR_LEN+1];
|
|
hid_t visitor_data = 0;
|
|
|
|
/* Here's how to get the number of scales attached
|
|
* to the dataset's dimension 0. */
|
|
if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
|
|
if (num_scales != 1) ERR;
|
|
|
|
/* Go through all dimscales for this var and learn about them. */
|
|
if (H5DSiterate_scales(datasetid, 0, NULL, alien_visitor,
|
|
&visitor_data) < 0) ERR;
|
|
|
|
/* There's also a label for dimension 0. */
|
|
if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
|
|
|
|
/*printf("found non-scale dataset %s, label %s\n", obj_name, label);*/
|
|
}
|
|
break;
|
|
case H5G_TYPE:
|
|
break;
|
|
case H5G_LINK:
|
|
break;
|
|
default:
|
|
printf("Unknown object class %d!", obj_class);
|
|
}
|
|
}
|
|
|
|
/* Close up the shop. */
|
|
if (H5Dclose(datasetid) < 0 ||
|
|
H5Sclose(spaceid) < 0 ||
|
|
H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
printf("*** Creating some 3D datasets using shared dimscales...");
|
|
|
|
{
|
|
#define NDIMS 3
|
|
#define TIME_DIM 0
|
|
#define LAT_DIM 1
|
|
#define LON_DIM 2
|
|
#define LAT_LEN 2
|
|
#define LON_LEN 3
|
|
#define LAT_NAME "Lat"
|
|
#define LON_NAME "Lon"
|
|
#define TIME_NAME "Time"
|
|
#define PRES_NAME "Pressure"
|
|
#define TEMP_NAME "Temperature"
|
|
|
|
hid_t fileid, grpid, lat_spaceid, lon_spaceid, time_spaceid, spaceid;
|
|
hid_t lat_scaleid, lon_scaleid, time_scaleid;
|
|
hid_t pres_dsid, temp_dsid, cparmsid;
|
|
hsize_t dims[NDIMS], max_dims[NDIMS];
|
|
|
|
/* Create file and group. */
|
|
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
|
|
H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gcreate1(fileid, GRP_NAME, 0)) < 0) ERR;
|
|
|
|
/* Create 3 1D spaces for the 3 dimension scale datasets. Time
|
|
* starts out as size 0. It's an unlimited dimension scale. */
|
|
dims[0] = 0;
|
|
max_dims[0] = H5S_UNLIMITED;
|
|
if ((time_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
|
|
dims[0] = LAT_LEN;
|
|
max_dims[0] = LAT_LEN;
|
|
if ((lat_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
|
|
dims[0] = LON_LEN;
|
|
max_dims[0] = LON_LEN;
|
|
if ((lon_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
|
|
|
|
/* Enable chunking for unlimited time scale. */
|
|
if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
|
|
dims[TIME_DIM] = 1;
|
|
if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;
|
|
|
|
/* Create our dimension scales. */
|
|
if ((time_scaleid = H5Dcreate1(grpid, TIME_NAME, H5T_NATIVE_INT,
|
|
time_spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSset_scale(time_scaleid, TIME_NAME) < 0) ERR;
|
|
if ((lat_scaleid = H5Dcreate1(grpid, LAT_NAME, H5T_NATIVE_FLOAT,
|
|
lat_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
if (H5DSset_scale(lat_scaleid, LAT_NAME) < 0) ERR;
|
|
if ((lon_scaleid = H5Dcreate1(grpid, LON_NAME, H5T_NATIVE_FLOAT,
|
|
lon_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
if (H5DSset_scale(lon_scaleid, LON_NAME) < 0) ERR;
|
|
|
|
/* Create a space corresponding to these three dimensions. */
|
|
dims[TIME_DIM] = 0;
|
|
dims[LAT_DIM] = LAT_LEN;
|
|
dims[LON_DIM] = LON_LEN;
|
|
max_dims[TIME_DIM] = H5S_UNLIMITED;
|
|
max_dims[LAT_DIM] = LAT_LEN;
|
|
max_dims[LON_DIM] = LON_LEN;
|
|
if ((spaceid = H5Screate_simple(NDIMS, dims, max_dims)) < 0) ERR;
|
|
|
|
/* Create two variables which use them, and attach the dimension scales. */
|
|
dims[TIME_DIM] = 1;
|
|
if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;
|
|
if ((pres_dsid = H5Dcreate1(grpid, PRES_NAME, H5T_NATIVE_FLOAT,
|
|
spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSattach_scale(pres_dsid, time_scaleid, 0) < 0) ERR;
|
|
if (H5DSattach_scale(pres_dsid, lat_scaleid, 1) < 0) ERR;
|
|
if (H5DSattach_scale(pres_dsid, lon_scaleid, 2) < 0) ERR;
|
|
if (H5DSset_label(pres_dsid, TIME_DIM, TIME_NAME) < 0) ERR;
|
|
if (H5DSset_label(pres_dsid, LAT_DIM, LAT_NAME) < 0) ERR;
|
|
if (H5DSset_label(pres_dsid, LON_DIM, LON_NAME) < 0) ERR;
|
|
if ((temp_dsid = H5Dcreate1(grpid, TEMP_NAME, H5T_NATIVE_FLOAT,
|
|
spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSattach_scale(temp_dsid, time_scaleid, 0) < 0) ERR;
|
|
if (H5DSattach_scale(temp_dsid, lat_scaleid, 1) < 0) ERR;
|
|
if (H5DSattach_scale(temp_dsid, lon_scaleid, 2) < 0) ERR;
|
|
if (H5DSset_label(temp_dsid, TIME_DIM, TIME_NAME) < 0) ERR;
|
|
if (H5DSset_label(temp_dsid, LAT_DIM, LAT_NAME) < 0) ERR;
|
|
if (H5DSset_label(temp_dsid, LON_DIM, LON_NAME) < 0) ERR;
|
|
|
|
/* Close up the shop. */
|
|
if (H5Dclose(pres_dsid) < 0 ||
|
|
H5Dclose(temp_dsid) < 0 ||
|
|
H5Dclose(lat_scaleid) < 0 ||
|
|
H5Dclose(lon_scaleid) < 0 ||
|
|
H5Dclose(time_scaleid) < 0 ||
|
|
H5Sclose(spaceid) < 0 ||
|
|
H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
printf("*** Checking 3D datasets created with shared dimscales...");
|
|
|
|
{
|
|
hid_t fileid, grpid, spaceid = 0, datasetid = 0;
|
|
hsize_t num_obj, i;
|
|
int obj_class;
|
|
char obj_name[STR_LEN + 1];
|
|
htri_t is_scale;
|
|
int num_scales;
|
|
hsize_t dims[NDIMS], max_dims[NDIMS];
|
|
int d;
|
|
|
|
/* Reopen the file and group. */
|
|
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gopen1(fileid, GRP_NAME)) < 0) ERR;
|
|
|
|
/* Loop through datasets to find variables. */
|
|
if (H5Gget_num_objs(grpid, &num_obj) < 0) ERR;
|
|
for (i=0; i<num_obj; i++)
|
|
{
|
|
/* Get the type (i.e. group, dataset, etc.), and the name of
|
|
* the object. */
|
|
if ((obj_class = H5Gget_objtype_by_idx(grpid, i)) < 0) ERR;
|
|
if (H5Gget_objname_by_idx(grpid, i, obj_name, STR_LEN) < 0) ERR;
|
|
/*printf("\nEncountered: HDF5 object obj_class %d obj_name %s\n", obj_class, obj_name);*/
|
|
|
|
/* Deal with groups and datasets. */
|
|
switch(obj_class)
|
|
{
|
|
case H5G_GROUP:
|
|
break;
|
|
case H5G_DATASET:
|
|
/* Open the dataset. */
|
|
if ((datasetid = H5Dopen1(grpid, obj_name)) < 0) ERR;
|
|
/*printf("\nobj_name %s\n", obj_name);*/
|
|
|
|
/* Get the dimensions of this dataset. */
|
|
if ((spaceid = H5Dget_space(datasetid)) < 0) ERR;
|
|
if (H5Sget_simple_extent_dims(spaceid, dims, max_dims) < 0) ERR;
|
|
|
|
/* Is this a dimscale? */
|
|
if ((is_scale = H5DSis_scale(datasetid)) < 0) ERR;
|
|
if (is_scale)
|
|
{
|
|
char nom_de_quincey[STR_LEN+1];
|
|
|
|
/* A dimscale comes with a NAME attribute, in
|
|
* addition to its real name. */
|
|
if (H5DSget_scale_name(datasetid, nom_de_quincey,
|
|
STR_LEN) < 0) ERR;
|
|
/*printf("found scale %s, NAME %s id 0x%x\n", obj_name,
|
|
nom_de_quincey, datasetid);*/
|
|
|
|
/* Check size depending on name. */
|
|
if ((!strcmp(obj_name, LAT_NAME) && dims[TIME_DIM] != LAT_LEN) ||
|
|
(!strcmp(obj_name, LON_NAME) && dims[TIME_DIM] != LON_LEN) ||
|
|
(!strcmp(obj_name, TIME_NAME) &&
|
|
max_dims[TIME_DIM] != H5S_UNLIMITED)) ERR;
|
|
|
|
}
|
|
else
|
|
{
|
|
char label[STR_LEN+1];
|
|
hid_t visitor_data = 0;
|
|
|
|
/* SHould have these dimensions... */
|
|
if (dims[TIME_DIM] != 0 || dims[LAT_DIM] != LAT_LEN ||
|
|
dims[LON_DIM] != LON_LEN) ERR;
|
|
if (max_dims[TIME_DIM] != H5S_UNLIMITED) ERR;
|
|
|
|
/* Here's how to get the number of scales attached
|
|
* to the dataset's dimension 0. */
|
|
if ((num_scales = H5DSget_num_scales(datasetid, 0)) < 0) ERR;
|
|
if (num_scales != 1) ERR;
|
|
|
|
/* Go through all dimscales for this var and learn
|
|
* about them. What I want is the dataset id of each
|
|
* dimscale. Then... */
|
|
for (d = 0; d < NDIMS; d++)
|
|
if (H5DSiterate_scales(datasetid, d, NULL, alien_visitor,
|
|
&visitor_data) < 0) ERR;
|
|
/*printf("visitor_data: 0x%x\n", visitor_data);*/
|
|
|
|
/* There's also a label for each dimension. */
|
|
if (H5DSget_label(datasetid, 0, label, STR_LEN) < 0) ERR;
|
|
if (strcmp(label, TIME_NAME)) ERR;
|
|
if (H5DSget_label(datasetid, 1, label, STR_LEN) < 0) ERR;
|
|
if (strcmp(label, LAT_NAME)) ERR;
|
|
if (H5DSget_label(datasetid, 2, label, STR_LEN) < 0) ERR;
|
|
if (strcmp(label, LON_NAME)) ERR;
|
|
}
|
|
if (H5Dclose(datasetid) < 0) ERR;
|
|
break;
|
|
case H5G_TYPE:
|
|
break;
|
|
case H5G_LINK:
|
|
break;
|
|
default:
|
|
printf("Unknown object class %d!", obj_class);
|
|
}
|
|
}
|
|
|
|
/* Close up the shop. */
|
|
if (H5Sclose(spaceid) < 0 ||
|
|
H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
printf("*** Creating 3D datasets using shared dimscales in groups...");
|
|
|
|
{
|
|
#define FATHER "Adam"
|
|
#define GOOD_CHILD "Able"
|
|
#define BAD_CHILD "Cain"
|
|
#define DISTANCE_LEN 3
|
|
#define SMELLINESS_NAME "Smelliness"
|
|
#define DISTANCE_NAME "Distance"
|
|
#define TIME_NAME "Time"
|
|
#define TIME_DIM 0
|
|
#define SMELLINESS_DIM 1
|
|
#define DISTANCE_DIM 2
|
|
#define GOAT_NAME "Billy_goat_gruff"
|
|
#define CAMEL_NAME "Grumpy_the_camel"
|
|
|
|
hid_t fileid, smelliness_spaceid, distance_spaceid, time_spaceid, spaceid;
|
|
hid_t adam_grpid, able_grpid, cain_grpid;
|
|
hid_t time_scaleid, smelliness_scaleid, distance_scaleid;
|
|
hid_t goat_dsid, camel_dsid, cparmsid;
|
|
hsize_t dims[NDIMS], max_dims[NDIMS];
|
|
|
|
/* Create file and group. */
|
|
if ((fileid = H5Fcreate(FILE_NAME, H5F_ACC_TRUNC, H5P_DEFAULT,
|
|
H5P_DEFAULT)) < 0) ERR;
|
|
if ((adam_grpid = H5Gcreate1(fileid, FATHER, 0)) < 0) ERR;
|
|
if ((able_grpid = H5Gcreate1(adam_grpid, GOOD_CHILD, 0)) < 0) ERR;
|
|
if ((cain_grpid = H5Gcreate1(adam_grpid, BAD_CHILD, 0)) < 0) ERR;
|
|
|
|
/* Create 3 1D spaces for the 3 dimension scale datasets. Time
|
|
* and smelliness starts out as 0. They are unlimited dimension
|
|
* scales. */
|
|
dims[0] = 0;
|
|
max_dims[0] = H5S_UNLIMITED;
|
|
if ((time_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
|
|
dims[0] = 0;
|
|
max_dims[0] = H5S_UNLIMITED;
|
|
if ((smelliness_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
|
|
dims[0] = DISTANCE_LEN;
|
|
max_dims[0] = DISTANCE_LEN;
|
|
if ((distance_spaceid = H5Screate_simple(1, dims, max_dims)) < 0) ERR;
|
|
|
|
/* Enable chunking for unlimited time and smelliness scale. */
|
|
if ((cparmsid = H5Pcreate(H5P_DATASET_CREATE)) < 0) ERR;
|
|
dims[0] = 1;
|
|
if (H5Pset_chunk(cparmsid, 1, dims) < 0) ERR;
|
|
|
|
/* Create our dimension scales. */
|
|
if ((time_scaleid = H5Dcreate1(adam_grpid, TIME_NAME, H5T_NATIVE_INT,
|
|
time_spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSset_scale(time_scaleid, TIME_NAME) < 0) ERR;
|
|
if ((smelliness_scaleid = H5Dcreate1(adam_grpid, SMELLINESS_NAME, H5T_NATIVE_FLOAT,
|
|
smelliness_spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSset_scale(smelliness_scaleid, SMELLINESS_NAME) < 0) ERR;
|
|
if ((distance_scaleid = H5Dcreate1(adam_grpid, DISTANCE_NAME, H5T_NATIVE_FLOAT,
|
|
distance_spaceid, H5P_DEFAULT)) < 0) ERR;
|
|
if (H5DSset_scale(distance_scaleid, DISTANCE_NAME) < 0) ERR;
|
|
|
|
/* Create a space corresponding to these three dimensions. */
|
|
dims[TIME_DIM] = 0;
|
|
dims[SMELLINESS_DIM] = 0;
|
|
dims[DISTANCE_DIM] = DISTANCE_LEN;
|
|
max_dims[TIME_DIM] = H5S_UNLIMITED;
|
|
max_dims[SMELLINESS_DIM] = H5S_UNLIMITED;
|
|
max_dims[DISTANCE_DIM] = DISTANCE_LEN;
|
|
if ((spaceid = H5Screate_simple(NDIMS, dims, max_dims)) < 0) ERR;
|
|
|
|
/* Set up chunking for our 3D vars. */
|
|
dims[TIME_DIM] = 1;
|
|
dims[SMELLINESS_DIM] = 1;
|
|
if (H5Pset_chunk(cparmsid, NDIMS, dims) < 0) ERR;
|
|
|
|
/* Create two variables which use them, and attach the dimension scales. */
|
|
if ((goat_dsid = H5Dcreate1(able_grpid, GOAT_NAME, H5T_NATIVE_FLOAT,
|
|
spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSattach_scale(goat_dsid, time_scaleid, 0) < 0) ERR;
|
|
if (H5DSattach_scale(goat_dsid, smelliness_scaleid, 1) < 0) ERR;
|
|
if (H5DSattach_scale(goat_dsid, distance_scaleid, 2) < 0) ERR;
|
|
if ((camel_dsid = H5Dcreate1(cain_grpid, CAMEL_NAME, H5T_NATIVE_FLOAT,
|
|
spaceid, cparmsid)) < 0) ERR;
|
|
if (H5DSattach_scale(camel_dsid, time_scaleid, 0) < 0) ERR;
|
|
if (H5DSattach_scale(camel_dsid, smelliness_scaleid, 1) < 0) ERR;
|
|
if (H5DSattach_scale(camel_dsid, distance_scaleid, 2) < 0) ERR;
|
|
|
|
/* Close up the shop. */
|
|
if (H5Dclose(goat_dsid) < 0 ||
|
|
H5Dclose(camel_dsid) < 0 ||
|
|
H5Dclose(smelliness_scaleid) < 0 ||
|
|
H5Dclose(distance_scaleid) < 0 ||
|
|
H5Dclose(time_scaleid) < 0 ||
|
|
H5Sclose(spaceid) < 0 ||
|
|
H5Gclose(cain_grpid) < 0 ||
|
|
H5Gclose(able_grpid) < 0 ||
|
|
H5Gclose(adam_grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
printf("*** Checking 3D datasets in groups created with shared dimscales...");
|
|
|
|
{
|
|
hid_t fileid, grpid;
|
|
|
|
/* Reopen the file and group. */
|
|
if ((fileid = H5Fopen(FILE_NAME, H5F_ACC_RDWR, H5P_DEFAULT)) < 0) ERR;
|
|
if ((grpid = H5Gopen1(fileid, FATHER)) < 0) ERR;
|
|
|
|
/* If we can't scan the group, crash into a flaming heap of
|
|
* smoking, smoldering rubbish. */
|
|
if (rec_scan_group(grpid)) ERR;
|
|
|
|
/* Close up the shop. */
|
|
if (H5Gclose(grpid) < 0 ||
|
|
H5Fclose(fileid) < 0) ERR;
|
|
}
|
|
|
|
SUMMARIZE_ERR;
|
|
FINAL_RESULTS;
|
|
}
|