Recipe: C program to read data from downloaded file

From GEOS-5

Back to G5NR Data Access Guide.

Problem

We want to read a downloaded data file using C.

Solution

For the purpose of this example, we assume that the file c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4 has already been downloaded from the ftp server. For more information about file naming conventions, and how to download a file from the ftp server, please follow the links in the #See Also section. Here we use the NetCDF-4 library to read the downloaded file (since NetCDF-4 uses HDF-5 as the underlying data format, HDF-5 library can also be used directly). First, we ensure that out NetCDF-4 library has been built with HDF5 support. If the query

> nc-config --has-hdf5

returns "yes", we have a compatible NetCDF-4 library. Here nc-config is a utility bundled with NetCDF-4 package.

Code

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<netcdf.h>  // for reading NR files
 4 
 5 /* Handle errors by printing an error message and exiting with a
 6  * non-zero status. */
 7 #define ERRCODE 2
 8 #define ERR(e) {printf("Error: %s\n", nc_strerror(e)); exit(ERRCODE);}
 9 
10 int main(void){
11 
12   // file name
13   char* T_file = NULL;
14 
15   // store temperature data in T
16   float *T = NULL;
17 
18   // miscellaneous
19   int rc, ctr;
20   int im, jm, lm;
21   int ncid, varid;
22 
23   // file name and dimensions
24   T_file = "c1440_NR.inst01hr_3d_T_Cv.20060918_0900z.nc4";
25 
26   // netCDF ID for the file and data variable
27   im = 720; // lon
28   jm = 361; // lat
29   lm = 72;  // lev
30 
31   // open file and get var id
32   if (rc = nc_open(T_file, NC_NOWRITE, &ncid)) ERR(rc);
33   if (rc = nc_inq_varid(ncid, "T", &varid)) ERR(rc);
34 
35   // read global temperature data
36   int asyz = 1*lm*jm*im;
37   T = malloc(asyz*sizeof(float));
38   size_t start[4] = {0, 0, 0, 0};
39   size_t count[4] = {1, lm, jm, im}; // 1 time step, 3D (lev, lat, lon) array
40   printf("Reading T..."); fflush(stdout);
41   if (rc = nc_get_vara_float(ncid, varid, start, count, T)) ERR(rc);
42   printf("done.\n"); fflush(stdout);
43 
44   // min/max of T
45   float minval, maxval;
46   minval = 1.0e15;
47   maxval = -1.0e15;
48   for (ctr=0; ctr<asyz; ctr++){
49     if (T[ctr]<minval){
50       minval = T[ctr];
51     }
52     if (T[ctr]>maxval){
53       maxval = T[ctr];
54     }
55   }
56   printf("min(T): %f\n", minval);
57   printf("max(T): %f\n", maxval);
58 
59   // free memory
60   free(T);
61 
62   return 0;
63 }

Compile and link

We use the utility nc-config (included in the NetCDF-4 installation) to identify the linking rules.

For a typical NetCDF-4 installation, the above code, g5nr_reader_global.c can be compiled and linked to to the NetCDF-f library via

gcc -o g5nr_reader_global.x `nc-config --cflags` g5nr_reader_global.c `nc-config --libs`

creating the executable g5nr_reader_global.x

NOTE:

  1. We can use our favorite C compiler instead of gcc
  2. If the NetCDF-4 library was built with parallel I/O support, we will need to use <mpicc> to link, even if our code does not use the MPI library.

Run

Running the executable

> ./g5nr_reader_global.x

produces the output

Reading T...done.
min(T): 180.366745
max(T): 315.651245

Discussions

Modifications to read a subset of data

The above C code can be easily modified to read a subset of the temperature data instead. If we want to read temperature inside the box bounded by latitudes 25oN, 50oN and longitudes -130oN, -65oN, we need to modify the values of the dimensions im, jm and the argument start of the call to nc_get_vara_float.

Our new dimensions are

1 // array indices from boundary lat/lon
2 // bounding box:
3 //   lons = -130:0.5:-65
4 //   lats =   25:0.5:50
5 imin = (int) round((-130. + 180.)/0.5) - 1;
6 imax = (int) round((- 65. + 180.)/0.5) - 1;
7 jmin = (int) round((  25. +  90.)/0.5) - 1;
8 jmax = (int) round((  50. +  90.)/0.5) - 1;

The new start argument to nc_get_vara_float defining the first indices of the slice of array to be read, is

 size_t start[4] = {0, 0, jmin, imin};

The modified version of the code is g5nr_reader_subset.c.txt.

Running the modified version

./g5nr_reader_subset.x

produces the output

Reading T (subset)...done.
min(T): 191.695648
max(T): 305.604828

See Also

  1. File Spec: File:G5NR-Ganymed-7km FileSpec-ON6-V1.0.pdf
  2. Recipe: Retrieve (global) data from FTP server
  3. Recipe: C program as OPeNDAP client

No Warranty

Copyright