read_netcdf_var_3d.c

Go to the documentation of this file.
00001 /* ***************************************************** */
00002 /* read_netcdf_var_3d Read a 3D NetCDF variable.         */
00003 /* read_netcdf_var_3d.c                                  */
00004 /* ***************************************************** */
00005 /* Author: Christian Page, CERFACS, Toulouse, France.    */
00006 /* ***************************************************** */
00007 /* Date of creation: sep 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_3d(double **buf, info_field_struct *info_field, proj_struct *proj, char *filename, char *varname,
00068                    char *dimxname, char *dimyname, char *timename, int *nlon, int *nlat, int *ntime, int outinfo) {
00086   int istat; /* Diagnostic status */
00087 
00088   size_t dimval; /* Variable used to retrieve dimension length */
00089 
00090   int ncinid; /* NetCDF input file handle ID */
00091   int varinid; /* NetCDF variable ID */
00092   int projinid; /* Projection variable ID */
00093   nc_type vartype_main; /* Type of the variable (NC_FLOAT, NC_DOUBLE, etc.) */
00094   int varndims; /* Number of dimensions of variable */
00095   int vardimids[NC_MAX_VAR_DIMS]; /* Variable dimension ids */
00096   int timediminid; /* Time dimension ID */
00097   int londiminid; /* Longitude dimension ID */
00098   int latdiminid; /* Latitude dimension ID */
00099 
00100   size_t start[3]; /* Start position to read */
00101   size_t count[3]; /* Number of elements to read */
00102 
00103   float valf; /* Variable used to retrieve fillvalue */
00104   int vali; /* Variable used to retrieve integer values */
00105   char *tmpstr = NULL; /* Temporary string */
00106   size_t t_len; /* Length of string attribute */
00107 
00108   float *proj_latin = NULL; /* Parallel latitudes of projection */
00109   int npts = 0; /* Number of points for 1D variables */
00110   char *grid_mapping = NULL;
00111 
00112   /* Allocate memory */
00113   tmpstr = (char *) malloc(MAXPATH * sizeof(char));
00114   if (tmpstr == NULL) alloc_error(__FILE__, __LINE__);
00115 
00116   /* Read data in NetCDF file */
00117 
00118   /* Open NetCDF file for reading */
00119   if (outinfo == TRUE)
00120     printf("%s: Opening for reading NetCDF input file %s\n", __FILE__, filename);
00121   istat = nc_open(filename, NC_NOWRITE, &ncinid);  /* open for reading */
00122   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00123 
00124   if (outinfo == TRUE)
00125     printf("%s: READ %s %s\n", __FILE__, varname, filename);
00126 
00127   /* Get dimensions length */
00128   istat = nc_inq_dimid(ncinid, timename, &timediminid);  /* get ID for time dimension */
00129   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00130   istat = nc_inq_dimlen(ncinid, timediminid, &dimval); /* get time length */
00131   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00132   *ntime = (int) dimval;
00133 
00134   istat = nc_inq_dimid(ncinid, dimyname, &latdiminid);  /* get ID for lat dimension */
00135   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00136   istat = nc_inq_dimlen(ncinid, latdiminid, &dimval); /* get lat length */
00137   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00138   *nlat = (int) dimval;
00139 
00140   istat = nc_inq_dimid(ncinid, dimxname, &londiminid);  /* get ID for lon dimension */
00141   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00142   istat = nc_inq_dimlen(ncinid, londiminid, &dimval); /* get lon length */
00143   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00144   *nlon = (int) dimval;
00145   
00146   /* Get main variable ID */
00147   istat = nc_inq_varid(ncinid, varname, &varinid);
00148   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00149 
00152   /* Get variable information */
00153   istat = nc_inq_var(ncinid, varinid, (char *) NULL, &vartype_main, &varndims, vardimids, (int *) NULL);
00154   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00155 
00156   /* Verify that variable is really 3D or 2D */
00157   if (varndims != 3 && varndims != 2) {
00158     (void) fprintf(stderr, "%s: Error NetCDF type and/or dimensions nlon %d nlat %d.\n", __FILE__, *nlon, *nlat);
00159     (void) free(tmpstr);
00160     istat = ncclose(ncinid);
00161     if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00162     return -1;
00163   }
00164 
00165   if (varndims == 2) {
00166     if ((*nlat) != (*nlon)) {
00167       (void) fprintf(stderr, "%s: Error NetCDF type and/or dimensions nlon %d nlat %d.\n", __FILE__, *nlon, *nlat);
00168       (void) free(tmpstr);
00169       istat = ncclose(ncinid);
00170       if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00171       return -1;
00172     }
00173     npts = *nlon;
00174     *nlat = 0;
00175   }
00176 
00177   /* If info_field si not NULL, get some information about the read variable */
00178   if (info_field != NULL) {
00179     /* Get missing value */
00180     if (vartype_main == NC_FLOAT) {
00181       istat = nc_get_att_float(ncinid, varinid, "missing_value", &valf);
00182       if (istat != NC_NOERR)
00183         info_field->fillvalue = -9999.0;
00184       else
00185         info_field->fillvalue = (double) valf;
00186     }
00187     else if (vartype_main == NC_DOUBLE) {
00188       istat = nc_get_att_double(ncinid, varinid, "missing_value", &(info_field->fillvalue));
00189       if (istat != NC_NOERR)
00190         info_field->fillvalue = -9999.0;
00191     }
00192 
00193     /* Get coordinates */
00194     istat = nc_inq_attlen(ncinid, varinid, "coordinates", &t_len);
00195     if (istat == NC_NOERR) {
00196       istat = nc_get_att_text(ncinid, varinid, "coordinates", tmpstr);
00197       if (istat == NC_NOERR) {
00198         if (tmpstr[t_len-1] != '\0')
00199           tmpstr[t_len] = '\0';
00200         info_field->coordinates = strdup(tmpstr);
00201       }
00202       else
00203         info_field->coordinates = strdup("lon lat");
00204     }
00205     else
00206       info_field->coordinates = strdup("lon lat");
00207 
00208     /* Get grid projection */
00209     istat = nc_inq_attlen(ncinid, varinid, "grid_mapping", &t_len);
00210     if (istat == NC_NOERR) {
00211       handle_netcdf_error(istat, __FILE__, __LINE__);
00212       istat = nc_get_att_text(ncinid, varinid, "grid_mapping", tmpstr);
00213       if (istat == NC_NOERR) {
00214         if (tmpstr[t_len-1] != '\0')
00215           tmpstr[t_len] = '\0';
00216         info_field->grid_mapping = strdup(tmpstr);
00217       }
00218       else
00219         info_field->grid_mapping = strdup("unknown");
00220     }
00221     else
00222       info_field->grid_mapping = strdup("unknown");
00223 
00224     /* Get units */
00225     istat = nc_inq_attlen(ncinid, varinid, "units", &t_len);
00226     if (istat == NC_NOERR) {
00227       handle_netcdf_error(istat, __FILE__, __LINE__);
00228       istat = nc_get_att_text(ncinid, varinid, "units", tmpstr);
00229       if (istat == NC_NOERR) {
00230         if (tmpstr[t_len-1] != '\0')
00231           tmpstr[t_len] = '\0';
00232         info_field->units = strdup(tmpstr);
00233       }
00234       else
00235         info_field->units = strdup("unknown");
00236     }
00237     else
00238       info_field->units = strdup("unknown");
00239 
00240     /* Get height */
00241     istat = nc_inq_attlen(ncinid, varinid, "height", &t_len);
00242     if (istat == NC_NOERR) {
00243       handle_netcdf_error(istat, __FILE__, __LINE__);
00244       istat = nc_get_att_text(ncinid, varinid, "height", tmpstr);
00245       if (istat == NC_NOERR) {
00246         if (tmpstr[t_len-1] != '\0')
00247           tmpstr[t_len] = '\0';
00248         info_field->height = strdup(tmpstr);
00249       }
00250       else
00251         info_field->height = strdup("unknown");
00252     }
00253     else
00254       info_field->height = strdup("unknown");
00255 
00256     /* Get long name */
00257     istat = nc_inq_attlen(ncinid, varinid, "long_name", &t_len);
00258     if (istat == NC_NOERR) {
00259       handle_netcdf_error(istat, __FILE__, __LINE__);
00260       istat = nc_get_att_text(ncinid, varinid, "long_name", tmpstr);
00261       if (istat == NC_NOERR) {
00262         if (tmpstr[t_len-1] != '\0')
00263           tmpstr[t_len] = '\0';
00264         info_field->long_name = strdup(tmpstr);
00265       }
00266       else
00267         info_field->long_name = strdup(varname);
00268     }
00269     else
00270       info_field->long_name = strdup(varname);
00271   }
00272 
00273   /* if proj is not NULL, retrieve informations about the horizontal projection parameters */
00274   if (proj != NULL) {
00275     if (info_field == NULL)
00276       grid_mapping = strdup("unknown");
00277     else
00278       grid_mapping = strdup(info_field->grid_mapping);
00279     /* Get projection variable ID */
00280     if ( !strcmp(grid_mapping, "Lambert_Conformal") ) {
00281       istat = nc_inq_varid(ncinid, grid_mapping, &projinid); /* get projection variable ID */
00282       if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00283     }
00284     else if ( !strcmp(grid_mapping, "rotated_latitude_longitude") ) {
00285       istat = nc_inq_varid(ncinid, grid_mapping, &projinid); /* get projection variable ID */
00286       if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00287     }
00288     if (proj->name != NULL) {
00289       if ( strcmp(grid_mapping, "Lambert_Conformal") && strcmp(grid_mapping, "Latitude_Longitude") &&
00290            ( !strcmp(proj->name, "Latitude_Longitude") || !strcmp(proj->name, "Lambert_Conformal") ) ) {
00291         (void) free(grid_mapping);
00292         grid_mapping = strdup(proj->name);
00293       }
00294       else if ( strcmp(grid_mapping, "rotated_latitude_longitude") && !strcmp(proj->name, "rotated_pole") ) {
00295         (void) free(grid_mapping);
00296         grid_mapping = strdup("rotated_latitude_longitude");
00297       }
00298     }
00299     if ( !strcmp(grid_mapping, "Lambert_Conformal") ) {
00300       /*              int Lambert_Conformal ;
00301                       Lambert_Conformal:grid_mapping_name = "lambert_conformal_conic" ;
00302                       Lambert_Conformal:standard_parallel = 45.89892f, 47.69601f ;
00303                       Lambert_Conformal:longitude_of_central_meridian = 2.337229f ;
00304                       Lambert_Conformal:latitude_of_projection_origin = 46.8f ;
00305                       Lambert_Conformal:false_easting = 600000.f ;
00306                       Lambert_Conformal:false_northing = 2200000.f ;
00307       */
00308       istat = nc_get_var1_int(ncinid, projinid, 0, &vali);
00309       if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);  
00310       if (proj->name != NULL)
00311         (void) free(proj->name);
00312       proj->name = strdup(grid_mapping);
00313       if (proj->grid_mapping_name != NULL)
00314         (void) free(proj->grid_mapping_name);
00315       istat = get_attribute_str(&(proj->grid_mapping_name), ncinid, projinid, "grid_mapping_name");
00316     
00317       proj_latin = (float *) malloc(2 * sizeof(float));
00318       if (proj_latin == NULL) alloc_error(__FILE__, __LINE__);
00319       istat = nc_get_att_float(ncinid, projinid, "standard_parallel", proj_latin);
00320       proj->latin1 = (double) proj_latin[0];
00321       proj->latin2 = (double) proj_latin[1];
00322       (void) free(proj_latin);
00323     
00324       istat = nc_get_att_double(ncinid, projinid, "longitude_of_central_meridian", &(proj->lonc));
00325       istat = nc_get_att_double(ncinid, projinid, "latitude_of_projection_origin", &(proj->lat0));
00326       istat = nc_get_att_double(ncinid, projinid, "false_easting", &(proj->false_easting));
00327       istat = nc_get_att_double(ncinid, projinid, "false_northing", &(proj->false_northing));
00328     
00329     }
00330     else if ( !strcmp(grid_mapping, "rotated_latitude_longitude") ) {
00331       /*        int rotated_pole ;
00332                 rotated_pole:grid_mapping_name = "rotated_latitude_longitude" ;
00333                 rotated_pole:grid_north_pole_latitude = 39.25 ;
00334                 rotated_pole:grid_north_pole_longitude = -162. ;
00335       */
00336       istat = nc_get_var1_int(ncinid, projinid, 0, &vali);
00337       if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);  
00338       if (proj->name != NULL)
00339         (void) free(proj->name);
00340       proj->name = strdup(grid_mapping);
00341       if (proj->grid_mapping_name != NULL)
00342         (void) free(proj->grid_mapping_name);
00343       istat = get_attribute_str(&(proj->grid_mapping_name), ncinid, projinid, "grid_mapping_name");
00344     
00345       istat = nc_get_att_double(ncinid, projinid, "grid_north_pole_latitude", &(proj->latpole));
00346       istat = nc_get_att_double(ncinid, projinid, "grid_north_pole_longitude", &(proj->lonpole));
00347     
00348     }
00349     else if ( !strcmp(grid_mapping, "Latitude_Longitude") ) {
00350       if (proj->name != NULL)
00351         (void) free(proj->name);
00352       proj->name = strdup(grid_mapping);
00353       if (proj->grid_mapping_name != NULL)
00354         (void) free(proj->grid_mapping_name);
00355       proj->grid_mapping_name = strdup("Latitude_Longitude");
00356       proj->latin1 = 0.0;
00357       proj->latin2 = 0.0;
00358       proj->lonc = 0.0;
00359       proj->lat0 = 0.0;
00360       proj->false_easting = 0.0;
00361       proj->false_northing = 0.0;
00362     }
00363     else if ( !strcmp(grid_mapping, "list") ) {
00364       if (proj->name != NULL)
00365         (void) free(proj->name);
00366       proj->name = strdup(grid_mapping);
00367       if (proj->grid_mapping_name != NULL)
00368         (void) free(proj->grid_mapping_name);
00369       proj->grid_mapping_name = strdup("list");
00370       proj->latin1 = 0.0;
00371       proj->latin2 = 0.0;
00372       proj->lonc = 0.0;
00373       proj->lat0 = 0.0;
00374       proj->false_easting = 0.0;
00375       proj->false_northing = 0.0;
00376     }
00377     else {
00378       (void) fprintf(stderr, "%s: WARNING: No projection parameter available for %s.\n", __FILE__, grid_mapping);
00379       (void) fprintf(stderr, "%s: WARNING: Assuming list of longitude and latitude points.\n", __FILE__);
00380       if (proj->name != NULL)
00381         (void) free(proj->name);
00382       proj->name = strdup("list");
00383       if (proj->grid_mapping_name != NULL)
00384         (void) free(proj->grid_mapping_name);
00385       proj->grid_mapping_name = strdup("list");
00386       proj->latin1 = 0.0;
00387       proj->latin2 = 0.0;
00388       proj->lonc = 0.0;
00389       proj->lat0 = 0.0;
00390       proj->false_easting = 0.0;
00391       proj->false_northing = 0.0;
00392     }
00393     (void) free(grid_mapping);
00394   }
00395 
00396   if (varndims == 3) {
00397     /* Allocate memory and set start and count */
00398     start[0] = 0;
00399     start[1] = 0;
00400     start[2] = 0;
00401     count[0] = (size_t) *ntime;
00402     count[1] = (size_t) *nlat;
00403     count[2] = (size_t) *nlon;
00404     /* Allocate memory */
00405     (*buf) = (double *) malloc((*nlat)*(*nlon)*(*ntime) * sizeof(double));
00406     if ((*buf) == NULL) alloc_error(__FILE__, __LINE__);
00407   }
00408   else if (varndims == 2) {
00409     /* Allocate memory and set start and count */
00410     start[0] = 0;
00411     start[1] = 0;
00412     start[2] = 0;
00413     count[0] = (size_t) *ntime;
00414     count[1] = (size_t) npts;
00415     count[2] = 0;
00416     /* Allocate memory */
00417     (*buf) = (double *) malloc(npts*(*ntime) * sizeof(double));
00418     if ((*buf) == NULL) alloc_error(__FILE__, __LINE__);
00419   }
00420 
00421   /* Read values from netCDF variable */
00422   istat = nc_get_vara_double(ncinid, varinid, start, count, *buf);
00423   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00424 
00425   /* Close the input netCDF file. */
00426   istat = ncclose(ncinid);
00427   if (istat != NC_NOERR) handle_netcdf_error(istat, __FILE__, __LINE__);
00428 
00429   /* Free memory */
00430   (void) free(tmpstr);
00431 
00432   /* Success status */
00433   return 0;
00434 }

Generated on 12 May 2016 for DSCLIM by  doxygen 1.6.1