/* Copyright 2005 University Corporation for Atmospheric Research/Unidata See COPYRIGHT file for conditions of use. See www.unidata.ucar.edu for more info. This file is part of the libcf package; it tests libcf coordinate systems. Ed Hartnett 10/1/05 $Id: tst_coords.c,v 1.1.1.1 2009/07/06 15:06:30 ed Exp $ */ #include #include #include #define DIM_LEN 4 #define DIM1_NAME "lat" #define VAR_NAME "earth" #define COORD_SYSTEM "coord_system" #define COORD_NAME "coord_name" #define TRANSFORM_NAME "transform_name" #define TRANSFORM_TYPE1 "transform_type" #define TRANSFORM_NAME "transform_name" #define COORDINATE_AXES "_CoordinateAxes" #define COORDINATE_Z_IS_POSITIVE "_CoordinateZisPositive" #define Z_UP "up" #define Z_DOWN "down" /* These are used to implement tests that end up like John Caron's * examples of coordinate systems. */ #define EARTH "earth" #define AIR "air" #define TIME "time" #define LEVEL "level" #define LEVEL_LEN 17 #define LAT "lat" #define LAT_LEN 73 #define LON "lon" #define LON_LEN 144 #define NDIMS 4 #define LAT_LON_COORDINATE_SYSTEM "LatLonCoordinateSytem" #define COORDINATE_SYSTEMS "_CoordinateSystems" #define TRANSFORM_NAME "transform_name" #define COORDINATE_TRANSFORMS "_CoordinateTransforms" #define LAMBERT_CONFORMAL_PROJECTION "LambertConformalProjection" #define PROJECTION "Projection" #define LAMBERT_CONFORMAL_CONIC "lambert_conformal_conic" /* Test everything for classic and 64-bit offsetfiles. If netcdf-4 is * included, that means another whole round of testing. */ #ifdef USE_NETCDF4 #define NUM_FORMATS (4) #else #define NUM_FORMATS (2) #endif static void test_axis(const char *testfile) { int ncid, dimid, varid, dimids[1] = {0}; int axis_type; int nvars, ndims, natts, unlimdimid; char value[NC_MAX_NAME + 1]; /* Create a file. */ if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR; /* Create an dimension and a coordinate var to go with it. */ if (nc_def_dim(ncid, DIM1_NAME, DIM_LEN, &dimid)) ERR; if (dimid != 0) ERR; if (nc_def_var(ncid, DIM1_NAME, NC_FLOAT, 1, dimids, &varid)) ERR; if (varid != 0) ERR; if (nccf_def_axis_type(ncid, varid, NCCF_LONGITUDE)) ERR; if (nccf_inq_axis_type(ncid, varid, &axis_type)) ERR; if (axis_type != NCCF_LONGITUDE) ERR; /* Write the file. */ if (nc_close(ncid)) ERR; /* Reopen the file, check the axis type. */ if (nc_open(testfile, NC_NOWRITE, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 1 && nvars != 2 && natts != 0 && unlimdimid != -1) ERR; if (nccf_inq_axis_type(ncid, 0, &axis_type)) ERR; if (axis_type != NCCF_LONGITUDE) ERR; if (nc_close(ncid)) ERR; /* Now create a file with the HEIGHT_UP axis. */ if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR; /* Create an dimension and a coordinate var to go with it. */ if (nc_def_dim(ncid, DIM1_NAME, DIM_LEN, &dimid)) ERR; if (dimid != 0) ERR; if (nc_def_var(ncid, DIM1_NAME, NC_FLOAT, 1, dimids, &varid)) ERR; if (varid != 0) ERR; if (nccf_def_axis_type(ncid, varid, NCCF_HEIGHT_UP)) ERR; if (nccf_inq_axis_type(ncid, varid, &axis_type)) ERR; if (axis_type != NCCF_HEIGHT_UP) ERR; /* Write the file. */ if (nc_close(ncid)) ERR; /* Reopen the file, check the axis type. */ if (nc_open(testfile, NC_NOWRITE, &ncid)) ERR; if (nccf_inq_axis_type(ncid, 0, &axis_type)) ERR; if (axis_type != NCCF_HEIGHT_UP) ERR; if (nc_get_att_text(ncid, varid, COORDINATE_Z_IS_POSITIVE, value)) ERR; if (strcmp(value, Z_UP)) ERR; if (nc_close(ncid)) ERR; } static void test_system(const char *testfile) { int ncid, dimid, axis_varid, system_varid, dimids[1] = {0}; int axes_varids[1] = {0}; int nvars, ndims, natts, unlimdimid; char name_in[NC_MAX_NAME + 1]; int naxes_in, axes_varids_in[1]; /* Create a file. */ if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR; /* Create an dimension and a coordinate var to go with it. */ if (nc_def_dim(ncid, DIM1_NAME, DIM_LEN, &dimid)) ERR; if (nc_def_var(ncid, DIM1_NAME, NC_FLOAT, 1, dimids, &axis_varid)) ERR; if (axis_varid != 0) ERR; if (nccf_def_coord_system(ncid, COORD_SYSTEM, 1, axes_varids, &system_varid)) ERR; if (system_varid != 1) ERR; if (nccf_inq_coord_system(ncid, 1, name_in, &naxes_in, axes_varids_in)) ERR; if (strcmp(name_in, COORD_SYSTEM) || naxes_in != 1 || axes_varids_in[0] != axes_varids[0]) ERR; /* Write the file. */ if (nc_close(ncid)) ERR; /* Reopen the file and check it. */ if (nc_open(testfile, NC_NOWRITE, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 1 && nvars != 2 && natts != 0 && unlimdimid != -1) ERR; if (nccf_inq_coord_system(ncid, 1, name_in, &naxes_in, axes_varids_in)) ERR; if (strcmp(name_in, COORD_SYSTEM) || naxes_in != 1 || axes_varids_in[0] != axes_varids[0]) ERR; if (nc_close(ncid)) ERR; } /* Test the creation of a system, and it's assignment to a data * variable. THis matches example 2 from John's document (with some of * the other attributes left out.) */ static void test_system_assign(const char *testfile) { int ncid, axis_varids[NDIMS], system_varid, dimids[NDIMS]; int nvars, ndims, natts, unlimdimid; int dimids_in[NDIMS], ndims_in; size_t len_in; char name_in[NC_MAX_NAME + 1]; char systems_in[NC_MAX_NAME + 1]; int naxes_in, axis_varids_in[NDIMS], natts_in; char *dim_name[] = {TIME, LEVEL, LAT, LON}; size_t dim_len[NDIMS] = {NC_UNLIMITED, LEVEL_LEN, LAT_LEN, LON_LEN}; int earth_varid, air_varid; int varid_in; nc_type type_in; int d; /* Create a file. */ if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR; /* Create 4 dimensions, and a coordinate var to go with each. */ for (d = 0; d < NDIMS; d++) { if (nc_def_dim(ncid, dim_name[d], dim_len[d], &dimids[d])) ERR; if (nc_def_var(ncid, dim_name[d], NC_FLOAT, 1, &dimids[d], &axis_varids[d])) ERR; } /* Create two data vars, earth and air. (Don't know what happened * to fire and water Aristotle!) */ if (nc_def_var(ncid, EARTH, NC_FLOAT, NDIMS, dimids, &earth_varid)) ERR; if (nc_def_var(ncid, AIR, NC_FLOAT, NDIMS, dimids, &air_varid)) ERR; /* Unite our 4 dims in a coordinate system. */ if (nccf_def_coord_system(ncid, LAT_LON_COORDINATE_SYSTEM, NDIMS, axis_varids, &system_varid)) ERR; /* Check things out. */ if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 4 && nvars != 7 && natts != 0 && unlimdimid != dimids[3]) ERR; if (nc_inq_varid(ncid, LAT_LON_COORDINATE_SYSTEM, &varid_in)) ERR; if (varid_in != system_varid) ERR; if (nc_inq_var(ncid, system_varid, name_in, &type_in, &ndims_in, dimids_in, &natts_in)) ERR; if (strcmp(name_in, LAT_LON_COORDINATE_SYSTEM) || type_in != NC_CHAR || ndims_in != 0 || natts_in != 1); if (nc_inq_att(ncid, system_varid, COORDINATE_AXES, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nccf_inq_coord_system(ncid, system_varid, name_in, &naxes_in, axis_varids_in)) ERR; if (strcmp(name_in, LAT_LON_COORDINATE_SYSTEM) || naxes_in != NDIMS) ERR; for (d = 0; d < NDIMS; d++) if (axis_varids_in[d] != axis_varids[d]) ERR; /* Assign the system to the earth and air data variables. */ if (nccf_assign_coord_system(ncid, earth_varid, system_varid)) ERR; if (nccf_assign_coord_system(ncid, air_varid, system_varid)) ERR; /* Check to ensure that the assignments happened. */ if (nc_inq_varnatts(ncid, earth_varid, &natts_in)) ERR; if (natts_in != 1) ERR; if (nc_inq_att(ncid, earth_varid, COORDINATE_SYSTEMS, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nc_inq_varnatts(ncid, air_varid, &natts_in)) ERR; if (natts_in != 1) ERR; if (nc_get_att_text(ncid, earth_varid, COORDINATE_SYSTEMS, systems_in)) ERR; if (strcmp(systems_in, LAT_LON_COORDINATE_SYSTEM)) ERR; if (nc_inq_att(ncid, air_varid, COORDINATE_SYSTEMS, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nc_get_att_text(ncid, air_varid, COORDINATE_SYSTEMS, systems_in)) ERR; if (strcmp(systems_in, LAT_LON_COORDINATE_SYSTEM)) ERR; /* Write the file. */ if (nc_close(ncid)) ERR; /* Reopen the file and check it. */ if (nc_open(testfile, NC_NOWRITE, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 4 && nvars != 7 && natts != 0 && unlimdimid != dimids[3]) ERR; if (nc_inq_var(ncid, system_varid, name_in, &type_in, &ndims_in, dimids_in, &natts_in)) ERR; if (strcmp(name_in, LAT_LON_COORDINATE_SYSTEM) || type_in != NC_CHAR || ndims_in != 0 || natts_in != 1); if (nc_inq_att(ncid, system_varid, COORDINATE_AXES, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nccf_inq_coord_system(ncid, system_varid, name_in, &naxes_in, axis_varids_in)) ERR; if (strcmp(name_in, LAT_LON_COORDINATE_SYSTEM) || naxes_in != NDIMS) ERR; for (d = 0; d < NDIMS; d++) if (axis_varids_in[d] != axis_varids[d]) ERR; /* Check to ensure that the assignments happened. */ if (nc_inq_varnatts(ncid, earth_varid, &natts_in)) ERR; if (natts_in != 1) ERR; if (nc_inq_att(ncid, earth_varid, COORDINATE_SYSTEMS, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nc_inq_varnatts(ncid, air_varid, &natts_in)) ERR; if (natts_in != 1) ERR; if (nc_get_att_text(ncid, earth_varid, COORDINATE_SYSTEMS, systems_in)) ERR; if (strcmp(systems_in, LAT_LON_COORDINATE_SYSTEM)) ERR; if (nc_inq_att(ncid, air_varid, COORDINATE_SYSTEMS, &type_in, &len_in)) ERR; if (type_in != NC_CHAR) ERR; if (nc_get_att_text(ncid, air_varid, COORDINATE_SYSTEMS, systems_in)) ERR; if (strcmp(systems_in, LAT_LON_COORDINATE_SYSTEM)) ERR; if (nc_close(ncid)) ERR; } static void test_transform(const char *testfile) { int ncid, transform_varid; int nvars, ndims, natts, unlimdimid; char name_in[NC_MAX_NAME + 1]; char transform_name_in[NC_MAX_NAME + 1], transform_type_in[NC_MAX_NAME + 1]; size_t type_len, name_len; /* Create a file. */ if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR; /* Create a transform. */ if (nccf_def_transform(ncid, TRANSFORM_NAME, TRANSFORM_TYPE1, TRANSFORM_NAME, &transform_varid)) ERR; if (transform_varid != 0) ERR; if (nccf_inq_transform(ncid, transform_varid, name_in, &type_len, transform_type_in, &name_len, transform_name_in)) ERR; if (strcmp(name_in, TRANSFORM_NAME) || type_len != strlen(TRANSFORM_TYPE1) + 1 || strcmp(transform_type_in, TRANSFORM_TYPE1) || name_len != strlen(TRANSFORM_NAME) + 1 || strcmp(transform_name_in, TRANSFORM_NAME)) ERR; /* Write the file. */ if (nc_close(ncid)) ERR; /* Reopen the file and check it. */ if (nc_open(testfile, NC_NOWRITE, &ncid)) ERR; if (nc_inq(ncid, &ndims, &nvars, &natts, &unlimdimid)) ERR; if (ndims != 0 && nvars != 1 && natts != 0 && unlimdimid != -1) ERR; if (nccf_inq_transform(ncid, 0, name_in, &type_len, transform_type_in, &name_len, transform_name_in)) ERR; if (strcmp(name_in, TRANSFORM_NAME) || type_len != strlen(TRANSFORM_TYPE1) + 1 || strcmp(transform_type_in, TRANSFORM_TYPE1) || name_len != strlen(TRANSFORM_NAME) + 1 || strcmp(transform_name_in, TRANSFORM_NAME)) ERR; if (nc_close(ncid)) ERR; } /* Create a coordinate system and transform, and create a file like * John's example 4. */ static void test_transform_assign(const char *testfile) { int ncid, axis_varids[NDIMS], system_varid, dimids[NDIMS]; int transform_varid; size_t len_in, name_len, type_len; char name_in[NC_MAX_NAME + 1]; char transform_in[NC_MAX_NAME + 1]; char transform_type_in[NC_MAX_NAME + 1], transform_name_in[NC_MAX_NAME + 1]; char *dim_name[NDIMS] = {TIME, LEVEL, LAT, LON}; size_t dim_len[NDIMS] = {NC_UNLIMITED, LEVEL_LEN, LAT_LEN, LON_LEN}; int axis_type[NDIMS] = {NCCF_TIME, NCCF_HEIGHT_DOWN, NCCF_LATITUDE, NCCF_LONGITUDE}; int earth_varid, air_varid; int d; /* Create a file. */ if (nc_create(testfile, NC_CLOBBER, &ncid)) ERR; /* Create 4 dimensions, and a coordinate var to go with each. Also * set the axis type for each axis. */ for (d = 0; d < NDIMS; d++) { if (nc_def_dim(ncid, dim_name[d], dim_len[d], &dimids[d])) ERR; if (nc_def_var(ncid, dim_name[d], NC_FLOAT, 1, &dimids[d], &axis_varids[d])) ERR; if (nccf_def_axis_type(ncid, axis_varids[d], axis_type[d])) ERR; } /* Create two data vars, earth and air. */ if (nc_def_var(ncid, EARTH, NC_FLOAT, NDIMS, dimids, &earth_varid)) ERR; if (nc_def_var(ncid, AIR, NC_FLOAT, NDIMS, dimids, &air_varid)) ERR; /* Unite our 4 dims in a coordinate system. */ if (nccf_def_coord_system(ncid, LAT_LON_COORDINATE_SYSTEM, NDIMS, axis_varids, &system_varid)) ERR; /* Assign the system to the earth and air data variables. */ if (nccf_assign_coord_system(ncid, earth_varid, system_varid)) ERR; if (nccf_assign_coord_system(ncid, air_varid, system_varid)) ERR; /* Create a coordinate transform called LambertConformalProjection. */ if (nccf_def_transform(ncid, LAMBERT_CONFORMAL_PROJECTION, PROJECTION, LAMBERT_CONFORMAL_CONIC, &transform_varid)) ERR; if (nccf_inq_transform(ncid, transform_varid, name_in, &len_in, transform_type_in, &name_len, transform_name_in)) ERR; if (strcmp(name_in, LAMBERT_CONFORMAL_PROJECTION) || len_in != strlen(PROJECTION) + 1 || strcmp(transform_type_in, PROJECTION) || name_len != strlen(LAMBERT_CONFORMAL_CONIC) + 1 || strcmp(transform_name_in, LAMBERT_CONFORMAL_CONIC)) ERR; /* Assign the transform to the coordinate system. */ if (nccf_assign_transform(ncid, system_varid, transform_varid)) ERR; /* Check it out. */ if (nc_get_att_text(ncid, system_varid, COORDINATE_TRANSFORMS, transform_in)) ERR; if (strcmp(transform_in, LAMBERT_CONFORMAL_PROJECTION)) ERR; /* Write the file. */ if (nc_close(ncid)) ERR; /* Reopen the file and check it. */ if (nc_open(testfile, NC_NOWRITE, &ncid)) ERR; if (nccf_inq_transform(ncid, transform_varid, name_in, &type_len, transform_type_in, &name_len, transform_name_in)) ERR; if (strcmp(name_in, LAMBERT_CONFORMAL_PROJECTION) || type_len != strlen(PROJECTION) + 1 || strcmp(transform_type_in, PROJECTION) || name_len != strlen(LAMBERT_CONFORMAL_CONIC) + 1 || strcmp(transform_name_in, LAMBERT_CONFORMAL_CONIC)) ERR; if (nc_get_att_text(ncid, system_varid, COORDINATE_TRANSFORMS, transform_in)) ERR; if (strcmp(transform_in, LAMBERT_CONFORMAL_PROJECTION)) ERR; if (nc_close(ncid)) ERR; } int main(int argc, char **argv) { int i; char testfile[NC_MAX_NAME + 1]; printf("\n*** Testing coordinate systems.\n"); /*nc_set_log_level(3);*/ /* Go thru formats and run all tests for each of two (for netCDF-3 * only builds), or 3 (for netCDF-4 builds) different formats. */ for (i = NUM_FORMATS; i >= 1; i--) { switch (i) { case NC_FORMAT_CLASSIC: nc_set_default_format(NC_FORMAT_CLASSIC, NULL); fprintf(stderr, "\nSwitching to netCDF classic format.\n"); strcpy(testfile, "tst_coords_classic.nc"); break; case NC_FORMAT_64BIT: nc_set_default_format(NC_FORMAT_64BIT, NULL); fprintf(stderr, "\nSwitching to 64-bit offset format.\n"); strcpy(testfile, "tst_coords_64bit.nc"); break; #ifdef USE_NETCDF4 case NC_FORMAT_NETCDF4_CLASSIC: nc_set_default_format(NC_FORMAT_NETCDF4_CLASSIC, NULL); strcpy(testfile, "tst_coords_netcdf4_classic.nc"); fprintf(stderr, "\nSwitching to netCDF-4 format (with NC_CLASSIC_MODEL).\n"); break; case NC_FORMAT_NETCDF4: /* actually it's _CLASSIC. */ nc_set_default_format(NC_FORMAT_NETCDF4, NULL); strcpy(testfile, "tst_coords_netcdf4.nc"); fprintf(stderr, "\nSwitching to netCDF-4 format.\n"); break; #endif default: fprintf(stderr, "Unexpected format!\n"); return 2; } printf("*** creating coordinate axis..."); test_axis(testfile); SUMMARIZE_ERR; printf("*** creating coordinate system..."); test_system(testfile); SUMMARIZE_ERR; printf("*** assigning a coordinate system..."); test_system_assign(testfile); SUMMARIZE_ERR; printf("*** creating coordinate transform..."); test_transform(testfile); SUMMARIZE_ERR; printf("*** assigning a coordinate transform..."); test_transform_assign(testfile); SUMMARIZE_ERR; } FINAL_RESULTS; }