ncdf4a13/libsrc/nccoord.c

Go to the documentation of this file.
00001 /*
00002 This file is part of netcdf-4, a netCDF-like interface for HDF5, or a
00003 HDF5 backend for netCDF, depending on your point of view.
00004 
00005 This file handles the nc4 coordinate systems.
00006 
00007 Copyright 2003, University Corporation for Atmospheric Research. See
00008 netcdf-4/docs/COPYRIGHT file for copying and redistribution
00009 conditions.
00010 
00011 $Id: nccoord.c,v 2.6 2006/01/10 15:34:01 ed Exp $
00012 */
00013 
00014 #include <netcdf.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 
00018 #define COORDINATE_AXIS_TYPE "_CoordinateAxisType"
00019 #define COORDINATE_AXES "_CoordinateAxes"
00020 #define COORDINATE_Z_IS_POSITIVE "_CoordinateZisPositive"
00021 #define Z_UP "up"
00022 #define Z_DOWN "down"
00023 #define COORDINATE_SYSTEMS "_CoordinateSystems"
00024 #define TRANSFORM_NAME "transform_name"
00025 #define TRANSFORM_TYPE "_CoordinateTransformType"
00026 #define COORDINATE_TRANSFORMS "_CoordinateTransforms"
00027 
00028 static char* axis_type_name[] = {"", "Lat", "Lon", "GeoX", "GeoY", "GeoZ", 
00029                                  "Height", "Height", "Pressure", "Time", 
00030                                  "RadialAzimuth", "RadialElevation", 
00031                                  "RadialDistance"};
00032 
00033 /* Here are functions for coordinate axis stuff. */
00034 int
00035 nc_def_axis_type(int ncid, int varid, int axis_type)
00036 {
00037    int dimid;
00038    char var_name[NC_MAX_NAME + 1];
00039    int retval;
00040 
00041    /* Is the axis type valid? */
00042    if (axis_type < 0 || axis_type > NC_RADDIST)
00043       return NC_EINVAL;
00044 
00045    /* Make sure there's a dimension with the same name in this
00046     * ncid. */
00047    if ((retval = nc_inq_varname(ncid, varid, var_name)))
00048       return retval;
00049    if ((retval = nc_inq_dimid(ncid, var_name, &dimid)))
00050       return retval;
00051 
00052    /* Now write the attribute which stores the axis type. */
00053    if ((retval = nc_put_att_text(ncid, varid, COORDINATE_AXIS_TYPE, 
00054                                  strlen(axis_type_name[axis_type]) + 1, 
00055                                  axis_type_name[axis_type])))
00056       return retval;
00057 
00058    /* For height we write another attribute, indicating up
00059     * vs. down. */
00060    if (axis_type == NC_HEIGHT_UP)
00061    {
00062       if ((retval = nc_put_att_text(ncid, varid, COORDINATE_Z_IS_POSITIVE, 
00063                                     strlen(Z_UP) + 1, Z_UP)))
00064          return retval;
00065    }
00066    else if (axis_type == NC_HEIGHT_DOWN)
00067    {
00068       if ((retval = nc_put_att_text(ncid, varid, COORDINATE_Z_IS_POSITIVE, 
00069                                     strlen(Z_UP) + 1, Z_UP)))
00070          return retval;
00071    }
00072 
00073    return NC_NOERR;
00074 }
00075 
00076 int
00077 nc_inq_axis_type(int ncid, int varid, int *axis_type)
00078 {
00079    char value[NC_MAX_NAME + 1];
00080    int i;
00081    int retval;
00082 
00083    /* Get the attribute which stores the axis type. */
00084    if ((retval = nc_get_att_text(ncid, varid, COORDINATE_AXIS_TYPE, 
00085                                  value)))
00086       return retval;
00087 
00088    /* Which axis type is this? */
00089    for (i = 1; i <= NC_RADDIST; i++)
00090       if (!strcmp(value, axis_type_name[i]))
00091          break;
00092 
00093    /* For height we also have to look at another attribute to find out
00094     * whether it is up or down. At this point, i will equal
00095     * NC_HEIGHT_UP, find out whether it should be HEIGHT_DOWN. */
00096    if (i == NC_HEIGHT_UP)
00097    {
00098       if ((retval = nc_get_att_text(ncid, varid, COORDINATE_Z_IS_POSITIVE, 
00099                                     value)))
00100          return retval;
00101       if (!strcmp(value, Z_DOWN))
00102          i = NC_HEIGHT_DOWN;
00103    }
00104 
00105    /* Return a valid type if we found one, otherwise zero. */
00106    if (i > NC_RADDIST)
00107       return NC_NOAXISTYPE;
00108    
00109    if (axis_type)
00110       *axis_type = i;
00111    
00112    return NC_NOERR;
00113 }
00114 
00115 
00116 /* Define a coordinate system. This creates a var with contains a text
00117  * attribute, which is the names of the (coordinate) vars which make
00118  * up the axes of a coordinate system. */
00119 int
00120 nc_def_coord_system(int ncid, const char *name, int naxes, int *axis_varids, 
00121                     int *system_varid)
00122 {
00123    int dimid, a;
00124    int varid;
00125    char var_name[NC_MAX_NAME + 1];
00126    char *coord_axes_str;
00127    int retval;
00128    
00129    /* naxes must be positive and less than max_dims. */
00130    if (naxes < 0)
00131       return NC_EINVAL;
00132    if (naxes > NC_MAX_DIMS)
00133       return NC_EMAXDIMS;
00134 
00135    /* Create a scalar var, type NC_CHAR, to hold the attribute that
00136     * defines this system. */
00137    if ((retval = nc_def_var(ncid, name, NC_CHAR, 0, NULL, &varid)))
00138       return retval;
00139    
00140    /* If the user wants it, return the varid of this system. */
00141    if (system_varid)
00142       *system_varid = varid;
00143 
00144    /* malloc space for the string which will hold the names of all the
00145     * axes. */
00146    if (!(coord_axes_str = malloc(naxes * NC_MAX_NAME + naxes)))
00147       return NC_NOERR;
00148    coord_axes_str[0] = 0;
00149 
00150    /* Store the names of the axes in an attribute. At the same time,
00151     * make sure that all the axis_varids are actually coordinate
00152     * variables - that is, there is a dimension withn the same
00153     * name. */
00154    for (a = 0; a < naxes; a++)
00155    {
00156       if ((retval = nc_inq_varname(ncid, axis_varids[a], var_name)))
00157          break;
00158       if ((retval = nc_inq_dimid(ncid, var_name, &dimid)))
00159          break;
00160       strcat(coord_axes_str, var_name);
00161       if (a < naxes - 1)
00162          strcat(coord_axes_str, " ");
00163    }
00164    
00165    /* If we arrived here without error, then write the coord_axes_str
00166     * to the appropriate attribute, to save the system in the file. */
00167    if (!retval)
00168       retval = nc_put_att_text(ncid, varid, COORDINATE_AXES, 
00169                                strlen(coord_axes_str) + 1, coord_axes_str);
00170 
00171    /* Free the memory we allocated. */
00172    free(coord_axes_str);
00173    
00174    return retval;
00175 }
00176 
00177 /* Inquire about a coordinate system. */
00178 EXTERNL int
00179 nc_inq_coord_system(int ncid, int system_varid, char *name, 
00180                     int *naxes, int *axis_varids)
00181 {
00182    size_t len;
00183    int retval;
00184    char *coord_axes_str;
00185    char axis_name[NC_MAX_NAME + 1], system_name[NC_MAX_NAME + 1];
00186    int num_axes = 0, axes[NC_MAX_DIMS];
00187    char *p, *a;
00188    int a1;
00189 
00190    /* Get the name of this coordinate system, which is the same as the
00191     * name of this variable. */
00192    if ((retval = nc_inq_varname(ncid, system_varid, system_name)))
00193       return retval;
00194 
00195    /* If the caller wants the name, let them have it. */
00196    if (name)
00197       strcpy(name, system_name);
00198 
00199    /* Does the COORDINATE_AXES attribute exist. */
00200    if ((retval = nc_inq_att(ncid, system_varid, COORDINATE_AXES, 
00201                             NULL, &len)))
00202       return retval;
00203 
00204    /* Allocate space to read in the system string. */
00205    if (!(coord_axes_str = malloc(len)))
00206       return NC_NOERR;
00207 
00208    /* Read in the system string. */
00209    retval = nc_get_att_text(ncid, system_varid, COORDINATE_AXES, 
00210                             coord_axes_str);
00211 
00212    /* If we got the coord axes string, parse it to find the name's of
00213     * the coordinate vars which make up this system. */
00214    for (p = coord_axes_str; !retval && (p - coord_axes_str) < strlen(coord_axes_str);)
00215    {
00216       for (a = axis_name; *p && *p != ' '; )
00217          *a++ = *p++;
00218       p++;
00219       *a = '\0';
00220       
00221       retval = nc_inq_varid(ncid, axis_name, &axes[num_axes++]);
00222    }
00223 
00224    /* Thanks for the memories! */
00225    free(coord_axes_str);
00226 
00227    /* Give the user what they asked for. */
00228    if (naxes)
00229       *naxes = num_axes;
00230    if (axis_varids)
00231       for (a1 = 0; a1 < num_axes; a1++)
00232          axis_varids[a1] = axes[a1];
00233    
00234    return retval;
00235 }
00236 
00237 /* Given the varid of a system, write an attribute to a varid, whcih
00238  * indicates that it (the var) partakes of the system. Recall that the
00239  * system is just a collection of var names which are axes of the
00240  * coordinate system. */
00241 int
00242 nc_assign_coord_system(int ncid, int varid, int system_varid)
00243 {
00244    char system_name[NC_MAX_NAME + 1];
00245    char *systems_str;
00246    size_t len, new_len = 0;
00247    int retval;
00248 
00249    /* Find the name of this system. */
00250    if ((retval = nc_inq_varname(ncid, system_varid, system_name)))
00251       return retval;
00252 
00253    /* Is the att already here? If so, get it's length, then it's
00254     * contents, then append a space and the new system name. */
00255    retval = nc_inq_att(ncid, varid, COORDINATE_SYSTEMS, NULL, &len);
00256    if (retval != NC_ENOTATT && retval != NC_NOERR)
00257       return retval;
00258    if (!retval)
00259       new_len += len;
00260    new_len += strlen(system_name) + 1;
00261    if (!(systems_str = malloc(new_len)))
00262       return NC_NOERR;
00263    systems_str[0] = 0;
00264    if (!retval)
00265    {
00266       if ((retval = nc_get_att_text(ncid, varid, COORDINATE_SYSTEMS, 
00267                                     systems_str)))
00268          return retval;
00269       strcat(systems_str, " ");
00270    }
00271    strcat(systems_str, system_name);
00272 
00273    /* Write an att, called _CoordinateSystems, which
00274     * contains a list of the system names related to this variable. */
00275    retval = nc_put_att_text(ncid, varid, COORDINATE_SYSTEMS, 
00276                             strlen(systems_str) + 1, systems_str);
00277       
00278 
00279    /* Free the memory we allocated. */
00280    free(systems_str);
00281    
00282    return retval;
00283 }
00284 
00285 /* Define a transform. This will create a scalar var of type NC_CHAR
00286  * to hold some attributes. */
00287 int
00288 nc_def_transform(int ncid, const char *name, const char *transform_type,
00289                  const char *transform_name, int *transform_varid)
00290 {
00291    int varid;
00292    int retval;
00293    
00294    /* Create a scalar var, type NC_CHAR, to hold the attribute that
00295     * defines this transform. */
00296    if ((retval = nc_def_var(ncid, name, NC_CHAR, 0, NULL, &varid)))
00297       return retval;
00298    
00299    /* If the user wants it, return the varid of this system. */
00300    if (transform_varid)
00301       *transform_varid = varid;
00302 
00303    /* Store the transform_type, if provided by the user. */
00304    if (transform_type)
00305       if ((retval = nc_put_att_text(ncid, varid, TRANSFORM_TYPE, 
00306                                     strlen(transform_type) + 1, transform_type)))
00307          return retval;
00308 
00309    /* Store the transform name, if provided by the user. */
00310    if (transform_type)
00311       if ((retval = nc_put_att_text(ncid, varid, TRANSFORM_NAME, 
00312                                     strlen(transform_name) + 1, transform_name)))
00313          return retval;
00314 
00315    return NC_NOERR;
00316 }
00317 
00318 EXTERNL int
00319 nc_inq_transform(int ncid, int transform_varid, char *name, size_t *type_len, 
00320                  char *transform_type, size_t *name_len, char *transform_name)
00321 {
00322    int retval;
00323 
00324    /* Find the name of the transform var, if desired. */
00325    if (name)
00326       if ((retval = nc_inq_varname(ncid, transform_varid, name)))
00327          return retval;
00328 
00329    /* If the user wants the length of the transform_type, find it. */
00330    if (type_len)
00331       if ((retval = nc_inq_attlen(ncid, transform_varid, TRANSFORM_TYPE, 
00332                                   type_len)))
00333          return retval;
00334 
00335    /* If the user wants the transform type string, get it. */
00336    if (transform_type)
00337       if ((retval = nc_get_att_text(ncid, transform_varid, 
00338                                     TRANSFORM_TYPE, transform_type)))
00339          return retval;
00340 
00341    /* If the user wants the length of the transform_name, find it. */
00342    if (type_len)
00343       if ((retval = nc_inq_attlen(ncid, transform_varid, TRANSFORM_NAME, 
00344                                   name_len)))
00345          return retval;
00346 
00347    /* If the user wants the transform name string, get it. */
00348    if (transform_name)
00349       if ((retval = nc_get_att_text(ncid, transform_varid, 
00350                                    TRANSFORM_NAME, transform_name)))
00351          return retval;
00352 
00353    return NC_NOERR;
00354 }
00355 
00356 int
00357 nc_assign_transform(int ncid, int system_varid, int transform_varid)
00358 {
00359    char transform_name[NC_MAX_NAME + 1];
00360    int retval;
00361 
00362    /* Find the name of the transform. */
00363    if ((retval = nc_inq_varname(ncid, transform_varid, transform_name)))
00364       return retval;
00365 
00366    /* Write the transform name as an att of the system to which it
00367     * applies. */
00368    if ((retval = nc_put_att_text(ncid, system_varid, COORDINATE_TRANSFORMS, 
00369                                  strlen(transform_name) + 1, transform_name)))
00370       return retval;
00371    
00372    return NC_NOERR;
00373 }
00374 
00375 

Generated on Thu Mar 16 18:10:09 2006 for nco by  doxygen 1.4.4