Read a NetCDF variable. More...
#include <io.h>
Go to the source code of this file.
Functions | |
int | read_netcdf_var_2d (double **buf, info_field_struct *info_field, proj_struct *proj, char *filename, char *varname, char *dimxname, char *dimyname, int *nlon, int *nlat, int outinfo) |
Read a 2D variable in a NetCDF file, and return information in info_field_struct structure and proj_struct. |
Read a NetCDF variable.
Definition in file read_netcdf_var_2d.c.
int read_netcdf_var_2d | ( | double ** | buf, | |
info_field_struct * | info_field, | |||
proj_struct * | proj, | |||
char * | filename, | |||
char * | varname, | |||
char * | dimxname, | |||
char * | dimyname, | |||
int * | nlon, | |||
int * | nlat, | |||
int | outinfo | |||
) |
Read a 2D variable in a NetCDF file, and return information in info_field_struct structure and proj_struct.
[out] | buf | 2D variable |
[out] | info_field | Information about the output variable |
[out] | proj | Information about the horizontal projection of the output variable |
[in] | filename | NetCDF input filename |
[in] | varname | NetCDF variable name |
[in] | dimxname | Longitude dimension name |
[in] | dimyname | Latitude dimension name |
[out] | nlon | Longitude dimension length |
[out] | nlat | Latitude dimension length |
[in] | outinfo | TRUE if we want information output, FALSE if not |
Read data variable
Definition at line 67 of file read_netcdf_var_2d.c.
References alloc_error(), info_field_struct::coordinates, proj_struct::false_easting, proj_struct::false_northing, info_field_struct::fillvalue, get_attribute_str(), info_field_struct::grid_mapping, proj_struct::grid_mapping_name, handle_netcdf_error(), info_field_struct::height, proj_struct::lat0, proj_struct::latin1, proj_struct::latin2, proj_struct::latpole, proj_struct::lonc, info_field_struct::long_name, proj_struct::lonpole, MAXPATH, proj_struct::name, TRUE, and info_field_struct::units.
Referenced by output_downscaled_analog(), read_learning_fields(), read_learning_obs_eof(), read_learning_rea_eof(), and read_mask().
00068 { 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 }