read_netcdf_var_2d.c

Go to the documentation of this file.
00001 /* ***************************************************** */
00002 /* read_netcdf_var_2d Read a 2D NetCDF variable.         */
00003 /* read_netcdf_var_2d.c                                  */
00004 /* ***************************************************** */
00005 /* Author: Christian Page, CERFACS, Toulouse, France.    */
00006 /* ***************************************************** */
00007 /* Date of creation: oct 2008                            */
00008 /* Last date of modification: feb 2015                   */
00009 /* ***************************************************** */
00010 /* Original version: 1.0                                 */
00011 /* Current revision: 1.1                                 */
00012 /* ***************************************************** */
00013 /* Revisions                                             */
00014 /* 1.1: Added rotated_latlon projection support: C. Page */
00015 /* ***************************************************** */
00020 /* LICENSE BEGIN
00021 
00022 Copyright Cerfacs (Christian Page) (2015)
00023 
00024 christian.page@cerfacs.fr
00025 
00026 This software is a computer program whose purpose is to downscale climate
00027 scenarios using a statistical methodology based on weather regimes.
00028 
00029 This software is governed by the CeCILL license under French law and
00030 abiding by the rules of distribution of free software. You can use, 
00031 modify and/ or redistribute the software under the terms of the CeCILL
00032 license as circulated by CEA, CNRS and INRIA at the following URL
00033 "http://www.cecill.info". 
00034 
00035 As a counterpart to the access to the source code and rights to copy,
00036 modify and redistribute granted by the license, users are provided only
00037 with a limited warranty and the software's author, the holder of the
00038 economic rights, and the successive licensors have only limited
00039 liability. 
00040 
00041 In this respect, the user's attention is drawn to the risks associated
00042 with loading, using, modifying and/or developing or reproducing the
00043 software by the user in light of its specific status of free software,
00044 that may mean that it is complicated to manipulate, and that also
00045 therefore means that it is reserved for developers and experienced
00046 professionals having in-depth computer knowledge. Users are therefore
00047 encouraged to load and test the software's suitability as regards their
00048 requirements in conditions enabling the security of their systems and/or 
00049 data to be ensured and, more generally, to use and operate it in the 
00050 same conditions as regards security. 
00051 
00052 The fact that you are presently reading this means that you have had
00053 knowledge of the CeCILL license and that you accept its terms.
00054 
00055 LICENSE END */
00056 
00057 
00058 
00059 
00060 
00061 
00062 
00063 #include <io.h>
00064 
00066 int
00067 read_netcdf_var_2d(double **buf, info_field_struct *info_field, proj_struct *proj, char *filename, char *varname,
00068                    char *dimxname, char *dimyname, int *nlon, int *nlat, int outinfo) {
00084   int istat; /* Diagnostic status */
00085 
00086   size_t dimval; /* Variable used to retrieve dimension length */
00087 
00088   int ncinid; /* NetCDF input file handle ID */
00089   int varinid; /* NetCDF variable ID */
00090   int projinid; /* Projection variable ID */
00091   nc_type vartype_main; /* Type of the variable (NC_FLOAT, NC_DOUBLE, etc.) */
00092   int varndims; /* Number of dimensions of variable */
00093   int vardimids[NC_MAX_VAR_DIMS]; /* Variable dimension ids */
00094   int londiminid; /* Longitude dimension ID */
00095   int latdiminid; /* Latitude dimension ID */
00096 
00097   size_t start[3]; /* Start position to read */
00098   size_t count[3]; /* Number of elements to read */
00099 
00100   float valf; /* Variable used to retrieve fillvalue */
00101   int vali; /* Variable used to retrieve integer values */
00102   char *tmpstr = NULL; /* Temporary string */
00103   size_t t_len; /* Length of string attribute */
00104 
00105   float *proj_latin = NULL; /* Parallel latitudes of projection */
00106   int npts = 0; /* Number of points for 1D variables */
00107   char *grid_mapping = NULL;
00108 
00109   /* Allocate memory */
00110   tmpstr = (char *) malloc(MAXPATH * sizeof(char));
00111   if (tmpstr == NULL) alloc_error(__FILE__, __LINE__);
00112 
00113   /* Read data in NetCDF file */
00114 
00115   /* Open NetCDF file for reading */
00116   if (outinfo == TRUE)
00117     printf("%s: Opening for reading NetCDF input file %s\n", __FILE__, filename);
00118   istat = nc_open(filename, NC_NOWRITE, &ncinid);  /* open for reading */
00119   if (istat != NC_NOERR) {
00120     printf("%s: Failed Opening for reading NetCDF input file %s\n", __FILE__, filename);
00121     handle_netcdf_error(istat, __FILE__, __LINE__);
00122     return -1;
00123   }
00124 
00125   if (outinfo == TRUE)
00126     printf("%s: READ %s %s\n", __FILE__, varname, filename);
00127 
00128   /* Get dimensions length */
00129   istat = nc_inq_dimid(ncinid, dimyname, &latdiminid);  /* get ID for lat dimension */
00130   if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00131   istat = nc_inq_dimlen(ncinid, latdiminid, &dimval); /* get lat length */
00132   if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00133   *nlat = (int) dimval;
00134 
00135   istat = nc_inq_dimid(ncinid, dimxname, &londiminid);  /* get ID for lon dimension */
00136   if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00137   istat = nc_inq_dimlen(ncinid, londiminid, &dimval); /* get lon length */
00138   if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00139   *nlon = (int) dimval;
00140   
00141   /* Get main variable ID */
00142   istat = nc_inq_varid(ncinid, varname, &varinid); /* get main variable ID */
00143   if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00144 
00147   /* Get variable information */
00148   istat = nc_inq_var(ncinid, varinid, (char *) NULL, &vartype_main, &varndims, vardimids, (int *) NULL);
00149   if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00150 
00151   /* Verify that variable is really 2D or 1D */
00152   if (varndims != 2 && varndims != 1) {
00153     (void) fprintf(stderr, "%s: Error NetCDF type and/or dimensions nlon %d nlat %d. The dimensions of the data variable is neither 1D or 2D...\n", __FILE__, *nlon, *nlat);
00154     (void) free(tmpstr);
00155     istat = ncclose(ncinid);
00156     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00157     return -1;
00158   }
00159 
00160   if (varndims == 1) {
00161     if ((*nlat) != (*nlon)) {
00162       (void) fprintf(stderr, "%s: Error NetCDF type and/or dimensions nlon %d nlat %d. When dimensions are specified as 1D, nlon must be equal to nlat because the grid cannot be assumed to be regular in latitude and longitude.\n", __FILE__, *nlon, *nlat);
00163       (void) free(tmpstr);
00164       istat = ncclose(ncinid);
00165       if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00166       return -1;
00167     }
00168     npts = *nlon;
00169     *nlat = 0;
00170   }
00171 
00172   /* If info_field si not NULL, get some information about the read variable */
00173   if (info_field != NULL) {
00174     /* Get missing value */
00175     if (vartype_main == NC_FLOAT) {
00176       istat = nc_get_att_float(ncinid, varinid, "missing_value", &valf);
00177       if (istat != NC_NOERR)
00178         info_field->fillvalue = -9999.0;
00179       else
00180         info_field->fillvalue = (double) valf;
00181     }
00182     else if (vartype_main == NC_DOUBLE) {
00183       istat = nc_get_att_double(ncinid, varinid, "missing_value", &(info_field->fillvalue));
00184       if (istat != NC_NOERR)
00185         info_field->fillvalue = -9999.0;
00186     }
00187     
00188     /* Get coordinates */
00189     istat = nc_inq_attlen(ncinid, varinid, "coordinates", &t_len);
00190     if (istat == NC_NOERR) {
00191       istat = nc_get_att_text(ncinid, varinid, "coordinates", tmpstr);
00192       if (istat == NC_NOERR) {
00193         if (tmpstr[t_len-1] != '\0')
00194           tmpstr[t_len] = '\0';
00195         info_field->coordinates = strdup(tmpstr);
00196       }
00197       else
00198         info_field->coordinates = strdup("lon lat");
00199     }
00200     else
00201       info_field->coordinates = strdup("lon lat");
00202     
00203     /* Get grid projection */
00204     istat = nc_inq_attlen(ncinid, varinid, "grid_mapping", &t_len);
00205     if (istat == NC_NOERR) {
00206       istat = nc_get_att_text(ncinid, varinid, "grid_mapping", tmpstr);
00207       if (istat == NC_NOERR) {
00208         if (tmpstr[t_len-1] != '\0')
00209           tmpstr[t_len] = '\0';
00210         info_field->grid_mapping = strdup(tmpstr);
00211       }
00212       else
00213         info_field->grid_mapping = strdup("unknown");
00214     }
00215     else
00216       info_field->grid_mapping = strdup("unknown");
00217     
00218     /* Get units */
00219     istat = nc_inq_attlen(ncinid, varinid, "units", &t_len);
00220     if (istat == NC_NOERR) {
00221       istat = nc_get_att_text(ncinid, varinid, "units", tmpstr);
00222       if (istat == NC_NOERR) {
00223         if (tmpstr[t_len-1] != '\0')
00224           tmpstr[t_len] = '\0';
00225         info_field->units = strdup(tmpstr);
00226       }
00227       else
00228         info_field->units = strdup("unknown");
00229     }
00230     else
00231       info_field->units = strdup("unknown");
00232     
00233     /* Get height */
00234     istat = nc_inq_attlen(ncinid, varinid, "height", &t_len);
00235     if (istat == NC_NOERR) {
00236       istat = nc_get_att_text(ncinid, varinid, "height", tmpstr);
00237       if (istat == NC_NOERR) {
00238         if (tmpstr[t_len-1] != '\0')
00239           tmpstr[t_len] = '\0';
00240         info_field->height = strdup(tmpstr);
00241       }
00242       else
00243         info_field->height = strdup("unknown");
00244     }
00245     else
00246       info_field->height = strdup("unknown");
00247 
00248     /* Get long name */
00249     istat = nc_inq_attlen(ncinid, varinid, "long_name", &t_len);
00250     if (istat == NC_NOERR) {
00251       istat = nc_get_att_text(ncinid, varinid, "long_name", tmpstr);
00252       if (istat == NC_NOERR) {
00253         if (tmpstr[t_len-1] != '\0')
00254           tmpstr[t_len] = '\0';
00255         info_field->long_name = strdup(tmpstr);
00256       }
00257       else
00258         info_field->long_name = strdup(varname);
00259     }
00260     else
00261       info_field->long_name = strdup(varname);
00262   }
00263 
00264   /* if proj is not NULL, retrieve informations about the horizontal projection parameters */
00265   if (proj != NULL) {
00266     if (info_field == NULL)
00267       grid_mapping = strdup("unknown");
00268     else
00269       grid_mapping = strdup(info_field->grid_mapping);
00270     /* Get projection variable ID */
00271     if ( !strcmp(grid_mapping, "Lambert_Conformal") ) {
00272       istat = nc_inq_varid(ncinid, grid_mapping, &projinid); /* get projection variable ID */
00273       if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00274     }
00275     else if ( !strcmp(grid_mapping, "rotated_latitude_longitude") ) {
00276       istat = nc_inq_varid(ncinid, grid_mapping, &projinid); /* get projection variable ID */
00277       if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00278     }
00279     if (proj->name != NULL) {
00280       if ( strcmp(grid_mapping, "Lambert_Conformal") && strcmp(grid_mapping, "Latitude_Longitude") &&
00281            ( !strcmp(proj->name, "Latitude_Longitude") || !strcmp(proj->name, "Lambert_Conformal") ) ) {
00282         (void) free(grid_mapping);
00283         grid_mapping = strdup(proj->name);
00284       }
00285       else if ( strcmp(grid_mapping, "rotated_latitude_longitude") && !strcmp(proj->name, "rotated_pole") ) {
00286         (void) free(grid_mapping);
00287         grid_mapping = strdup("rotated_latitude_longitude");
00288       }
00289     }
00290     if ( !strcmp(grid_mapping, "Lambert_Conformal") ) {
00291       /*              int Lambert_Conformal ;
00292                       Lambert_Conformal:grid_mapping_name = "lambert_conformal_conic" ;
00293                       Lambert_Conformal:standard_parallel = 45.89892f, 47.69601f ;
00294                       Lambert_Conformal:longitude_of_central_meridian = 2.337229f ;
00295                       Lambert_Conformal:latitude_of_projection_origin = 46.8f ;
00296                       Lambert_Conformal:false_easting = 600000.f ;
00297                       Lambert_Conformal:false_northing = 2200000.f ;
00298       */
00299       istat = nc_get_var1_int(ncinid, projinid, 0, &vali);
00300       if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00301       proj->name = strdup(grid_mapping);
00302       istat = get_attribute_str(&(proj->grid_mapping_name), ncinid, projinid, "grid_mapping_name");
00303       
00304       proj_latin = (float *) malloc(2 * sizeof(float));
00305       if (proj_latin == NULL) alloc_error(__FILE__, __LINE__);
00306       istat = nc_get_att_float(ncinid, projinid, "standard_parallel", proj_latin);
00307       proj->latin1 = (double) proj_latin[0];
00308       proj->latin2 = (double) proj_latin[1];
00309       (void) free(proj_latin);
00310       
00311       istat = nc_get_att_double(ncinid, projinid, "longitude_of_central_meridian", &(proj->lonc));
00312       istat = nc_get_att_double(ncinid, projinid, "latitude_of_projection_origin", &(proj->lat0));
00313       istat = nc_get_att_double(ncinid, projinid, "false_easting", &(proj->false_easting));
00314       istat = nc_get_att_double(ncinid, projinid, "false_northing", &(proj->false_northing));
00315       
00316     }
00317     else if ( !strcmp(grid_mapping, "rotated_latitude_longitude") ) {
00318       /*        int rotated_pole ;
00319                 rotated_pole:grid_mapping_name = "rotated_latitude_longitude" ;
00320                 rotated_pole:grid_north_pole_latitude = 39.25 ;
00321                 rotated_pole:grid_north_pole_longitude = -162. ;
00322       */
00323       istat = nc_get_var1_int(ncinid, projinid, 0, &vali);
00324       if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);  
00325       proj->name = strdup("rotated_pole");
00326       istat = get_attribute_str(&(proj->grid_mapping_name), ncinid, projinid, "grid_mapping_name");
00327     
00328       istat = nc_get_att_double(ncinid, projinid, "grid_north_pole_latitude", &(proj->latpole));
00329       istat = nc_get_att_double(ncinid, projinid, "grid_north_pole_longitude", &(proj->lonpole));
00330     
00331     }
00332     else if ( !strcmp(grid_mapping, "Latitude_Longitude") ) {
00333       proj->name = strdup(grid_mapping);
00334       proj->grid_mapping_name = strdup("Latitude_Longitude");
00335       proj->latin1 = 0.0;
00336       proj->latin2 = 0.0;
00337       proj->lonc = 0.0;
00338       proj->lat0 = 0.0;
00339       proj->false_easting = 0.0;
00340       proj->false_northing = 0.0;
00341     }
00342     else if ( !strcmp(grid_mapping, "list") ) {
00343       proj->name = strdup(grid_mapping);
00344       proj->grid_mapping_name = strdup("list");
00345       proj->latin1 = 0.0;
00346       proj->latin2 = 0.0;
00347       proj->lonc = 0.0;
00348       proj->lat0 = 0.0;
00349       proj->false_easting = 0.0;
00350       proj->false_northing = 0.0;
00351     }
00352     else {
00353       (void) fprintf(stderr, "%s: WARNING: No projection parameter available for %s.\n", __FILE__, grid_mapping);
00354       (void) fprintf(stderr, "%s: WARNING: Assuming list of longitude and latitude points.\n", __FILE__);
00355       proj->name = strdup("list");
00356       proj->grid_mapping_name = strdup("list");
00357       proj->latin1 = 0.0;
00358       proj->latin2 = 0.0;
00359       proj->lonc = 0.0;
00360       proj->lat0 = 0.0;
00361       proj->false_easting = 0.0;
00362       proj->false_northing = 0.0;
00363     }
00364     (void) free(grid_mapping);
00365   }
00366   
00367   if (varndims == 2) {
00368     /* Allocate memory and set start and count */
00369     start[0] = 0;
00370     start[1] = 0;
00371     start[2] = 0;
00372     count[0] = (size_t) *nlat;
00373     count[1] = (size_t) *nlon;
00374     count[2] = 0;
00375     /* Allocate memory */
00376     (*buf) = (double *) malloc((*nlat)*(*nlon) * sizeof(double));
00377     if ((*buf) == NULL) alloc_error(__FILE__, __LINE__);
00378   }
00379   else if (varndims == 1) {
00380     /* Allocate memory and set start and count */
00381     start[0] = 0;
00382     start[1] = 0;
00383     start[2] = 0;
00384     count[0] = (size_t) npts;
00385     count[1] = 0;
00386     count[2] = 0;
00387     /* Allocate memory */
00388     (*buf) = (double *) malloc(npts * sizeof(double));
00389     if ((*buf) == NULL) alloc_error(__FILE__, __LINE__);
00390   }
00391 
00392   /* Read values from netCDF variable */
00393   istat = nc_get_vara_double(ncinid, varinid, start, count, *buf);
00394   if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00395 
00396   /* Close the input netCDF file. */
00397   istat = ncclose(ncinid);
00398   if (istat != NC_NOERR) { handle_netcdf_error(istat, __FILE__, __LINE__); return -1; }
00399 
00400   /* Free memory */
00401   (void) free(tmpstr);
00402 
00403   /* Success status */
00404   return 0;
00405 }

Generated on 12 May 2016 for DSCLIM by  doxygen 1.6.1