Go to the previous, next section, or Table of Contents.
This chapter provides examples to illustrate how to use EPS library routines to read and write EPS data files (netCDF files or classic EPIC files). Both C and FORTRAN versions of examples will be listed. User should refer to Chapter 4 to Chapter 8 for detailed description of the EPS interfaces and their usage.
Please also refer to other EPS EXAMPLES (C, Fortran and PPC) Programs.
The Basic steps to read an existing file are:
Step 2 to 5 can be repeated until the last data file listed in the pointer file is reached.
The very first EPS routine to call for reading an existing EPS file is ep_open or epopen for Fortran. Here is an example using this function to open an existing EPS file for reading; the pointer file name is `foo.ptr' and it consists of either classic EPIC file names or netCDF file names:
C Interface:
#include "epsystem.h"
...
Dbase *epfin; /* EPS data structure */
...
ep_open(&epfin, "foo.ptr", EPREAD);
...
Fortran Interface:
include 'epsystem.fh'
...
integer epfin ! pointer file identifier
...
call epopen(epfin, 'foo.ptr', EPREAD)
...
The EPS file identifier epfin returned from this function call will be used to refer to the EPS file. The pointer file name, the second argument, to this function can be a netCDF file name when EPS file contains only a single netCDF file is read.
After the pointer file is opened, ep_set_next or epsetnext for Fortran needs to be called to open the next data file listed in the pointer file. This function returns the data file name which is just opened for reading. The first time this function is called, the first data file will be opened. This function also closes previously opened data file if there is one. Here is an example using ep_set_next or epsetnext to position the next data file for reading:
C Interface
#include "epsystem.h"
...
Dbase *epfin; /* EPS data structure */
char *currentfile; /* current data fil name */
...
currentfile = (char *)ep_set_next(epfin, (char *)NULL));
...
Fortran Interface
include 'epsystem.fh'
...
integer epfin ! pointer file identifier
character currentfile*80 ! current data file name
...
call epsetnext(epfin, currentfile)
The variable code for each variable is the essential key to access the variable in the data file. When reading a netCDF file, the variable code is obtained from variable attribute epic_code or if epic_code attribute is not found, a negative number will be assigned; when reading a classic EPIC file, all variable codes are obtained from the data file and these variable codes must be defined in epic.key file, otherwise errors will occur. Here is an example using sequences of EPS routine calls to get variable information and get the float typed variable value:
C Interface
#include "epsystem.h"
#define TIMES 1
#define DEPS 50
#define LONS 1
#define LATS 1
#define MAXNVAR 20 /* maximum number of variable in a data file*/
...
Dbase *epfin; /* EPS data structure */
int varlist[MAXNVAR]; /* array to hold variable codes */
int nvar; /* total number of variables */
char *sname,*lname,*frmt,*units; /* short, long name, format, units */
int dtype; /* variable data type */
float var[TIMES*LATS*LONS*DEPS]; /* array hold variable data */
static int dims[4]={LONS,LATS,DEPS,TIMES}; /* dimensions of data array */
int lci[4], uci[4]; /* lower and upper corner index */
int i;
...
ep_get_var_list(epfin,varlist,MAXNVAR,&nvar); /*get variable code list*/
for(i=0; i
...
Fortran Interface
include 'epsystem.fh'
...
parameter(TIMES=1, DEPS=50, LATS=1, LONS=1)
parameter(MAXNVAR=20) ! maximum number of variable in the data file
integer epfin ! pointer file identifier
integer varlist(MAXNVAR) ! array to hold variable codes
integer nvar ! total number of variables
character*80 sname, lname, frmt, units ! for variable short name,
! long name, format and units
integer dtype ! variable data type
real var(LONS,LATS,DEPS,TIMES) ! array to hold variable data
data dims/LONS,LATS,DEPS,TIMES/ ! dimensions of data array
integer lci(4), uci(4) ! lower and upper corner index
integer i
...
call epgetvarlist(epfin,varlist,MAXNVAR,nvar) ! get variable code list
do 100 i=1, nvar
! Get variable information from its variable code
call epinqvar(epfin,varlist(i),sname,lname,frmt,units,dtype)
! Get variable shape from its variable code. The variable shape is
! described by a lower corner index lci(4) and an upper corner index
! uci(4). For example, if the input EPS file is a CTD data file and
! variable dimension length in depth is 40, then the lower and upper
! corner index returned from epgetvarshap will be lci = {1,1,1,1}
! and uci = {1,1,40,1}.
call epgetvarshap(epfin,varlist(i),lci,uci)
call epgetvar(epfin,varlist(i),lci,uci,var,dims) ! get variable data
...
100 continue
...
To get an axis information (ie. axis code, name, format, units, type and interval spacing) and its value, the variable code for the variable that the axis is associated with must be known. There are EPS functions designed for accessing spatial axis and time axis separately. Here is an example using sequences of EPS routine calls to obtain the variable code for a variable named `T', and get its axis information and axis values:
C Interface
#include "epsystem.h"
#define TIMES 1
#define DEPS 50
#define LONS 1
#define LATS 1
...
Dbase *epfin; /* EPS data structure */
int varcde; /* hold variable code */
float lon[LONS],lat[LATS],dep[DEPS]; /* hold x,y,z axis array */
long time[TIMES*2]; /* hold time axis array */
int xid, yid, zid; /* x, y, z axis code */
char *xname,*xfrmt,*xunits,*xtype, /* name, format, units */
*yname,*yfrmt,*yunits,*ytype, /* and type of x, y, z */
*zname,*zfrmt,*zunits,*ztype, /* and time axis */
*tname,*tfrmt,*tunits,*ttype;
float xspc, yspc, zspc; /* x, y, and z interval spacing */
long tspc[2]; /* time axis interval spacing */
int lci[4], uci[4]; /* lower and upper corner index */
...
ep_var_name_to_id(epfin,"T",&varcde); /* get variable code */
ep_get_var_shape(epfin,varcde,lci,uci); /* get variable shape */
/* following 4 lines get x,y,z and time axis information */
ep_inq_axis(epfin,varcde,1,&xid,&xname,&xfrmt,&xunits,&xtype,&xspc);
ep_inq_axis(epfin,varcde,2,&yid,&yname,&yfrmt,&yunits,&ytype,&yspc);
ep_inq_axis(epfin,varcde,3,&zid,&zname,&zfrmt,&zunits,&ztype,&zspc);
ep_inq_t_axis(epfin,varcde, &tname, &tfrmt, &tunits, &ttype, tspc);
/* following 4 lines get x,y,z and time axis value */
ep_get_axis(epfin, varcde, 1, lci, uci, lon, LONS);
ep_get_axis(epfin, varcde, 2, lci, uci, lat, LATS);
ep_get_axis(epfin, varcde, 3, lci, uci, dep, DEPS);
ep_get_t_axis(epfin, varcde, lci, uci, time, TIMES);
...
Fortran Interface
include 'epsystem.fh'
...
parameter(TIMES=1, DEPS=50, LATS=1, LONS=1) ! dimension size
integer epfin ! pointer file identifier
integer varcde ! hold variable code
real lon(LONS),lat(LATS),dep(DEPS) ! hold x,y,z axis array
integer time(TIMES,2) ! hold time axis array
integer xid, yid, zid ! x, y, z axis code
character*80 xname,xfrmt,xunits,xtype ! name, format, units and type
character*80 yname,yfrmt,yunits,ytype ! of x, y, z and time axis
character*80 zname,zfrmt,zunits,ztzpe !
character*80 tname,tfrmt,tunits,ttzpe !
real xspc,yspc,zspc ! x, y, and z interval spacing
integer tspc(2) ! time axis interval spacing
integer lci(4), uci(4) ! lower and upper corner index
...
call epvarnmetoid(epfin,'T',varcde) ! get variable code
call epgetvarshap(epfin,varcde,lci,uci) ! get variable shape
! following 4 lines get x,y,z and time axis information
call epinqaxis(epfin,varcde,1,xid,xname,xfrmt,xunits,xtype,xspcing)
call epinqaxis(epfin,varcde,2,yid,yname,yfrmt,yunits,ytype,yspcing)
call epinqaxis(epfin,varcde,3,zid,zname,zfrmt,zunits,ztype,zspcing)
call epinqtaxis(epfin,varcde, tname, tfrmt, tunits, ttype, tspcing)
! following 4 lines get x,y,z and time axis value
call epgetaxis(epfin, varcde, 1, lci, uci, lon, LONS)
call epgetaxis(epfin, varcde, 2, lci, uci, lat, LATS)
call epgetaxis(epfin, varcde, 3, lci, uci, dep, DEPS)
call epgettaxis(epfin, varcde, lci, uci, time, TIMES)
...
Here is an example using sequences of EPS routine calls to get information and values of all global attributes in the file. Similar function calls are available for obtaining information and values of variable attributes and axis attributes in a netCDF files:
C Interface
#include "epsystem.h"
#define MAXATLEN 20 /* maximum attribute array length */
...
Dbase *epfin; /* EPS data structure */
int natts; /* total number of global attributes */
char *attname; /* global attribute name */
int atlen, attype; /* attribute length and type */
char attc[80]; /* hold character string attribute value */
float attf[MAXATLEN]; /* hold float typed attribute array */
double arrd[MAXATLEN]; /* hold double typed attribute array */
int atti[MAXATLEN]; /* hold integer typed attribute array */
int i;
...
ep_get_att_num(epfin, &natts); /* get total number global attributes */
for(i = 1; i <= natts; i++) {
ep_att_name(epfin, i, &attname); /* get attribute name */
ep_inq_att(epfin, attname, &atlen, &attype); /* get attribute info */
if(attype == EPCHAR)
ep_get_att_value(epf, attname, attc); /* get character string */
else if(attype == EPINT)
ep_get_att_value(epf, attname, atti); /* get integer attribute */
else if(attype == EPREAL)
ep_get_att_value(epf, attname, attf); /* get float attribute */
else if(attype == EPDOUBLE)
ep_get_att_value(epf, attname, attd); /* get double attribute */
...
...
Fortran Interface
include 'epsystem.fh'
...
parameter(MAXATLEN=20) ! maximum attribute array length
integer epfin ! pointer file identifier
integer natts ! total number of global attributes
character attname(80) ! global attribute name
integer atlen, attype ! attribute length and type
character attc(80) ! hold character string attribute
real attf(MAXATLEN) ! hold float typed attribute array
real*8 arrd(MAXATLEN) ! hold double typed attribute array
integer atti(MAXATLEN) ! hold integer typed attribute array
integer i
...
call epgetattnum(epfin, natts) ! get total number of global attributes
do 200 i = 1, natts
call epattname(epfin, i, attname) !get attribute name from its number
call epinqatt(epfin, attname, atlen, attype) ! get attribute info
if(attype .eq. EPCHAR) then
call epgetattvalc(epf, attname, attc) ! get character string
else if(attype .eq. EPINT) then
call epgetattval(epf, attname, atti) ! get integer attribute
else if(attype .eq. EPREAL) then
call epgetattval(epf, attname, attf) ! get float attribute
else if(attype == EPDOUBLE) then
call epgetattval(epf, attname, attd) ! get double attribute
...
...
Note: In Fortran, epgetattvalc is used to get character string and epgetattval is used to get other types data.
When you finish reading the EPS file, you must call ep_close (or epclose for Fortran) to close the EPS file. This function call closes the pointer file and the last-opened data file. Here is an example using this function to close an EPS file:
C Interface
#include "epsystem.h"
...
Dbase *epfin; /* EPS data structure */
...
ep_close(epfin);
Fortran Interface
include 'epsystem.fh'
...
integer epfin ! pointer file identifier
...
call epclose(epfin)
The basic steps to create (write) an EPS file are:
Step 2 to 6 can be repeated until the last data file is written.
Like reading an EPS file, the first EPS routine to call for writing an EPS file is also ep_open or epopen for Fortran. Here is an example using this function to open an EPS file for creating netCDF files; the pointer file name is `foo.ptr' and it will consists of names of output data files:
C Interface
#include "epsystem.h"
...
Dbase *epfout; /* EPS data structure */
...
ep_open(&epfout, "foo.ptr", EPCREATE+EPCDF);
...
Fortran Interface
include 'epsystem.fh'
...
integer epfout ! pointer file identifier
...
call epopen(epfout, 'foo.ptr', EPCREATE+EPCDF)
...
Replace EPCDF by EPEPIC if the output files are classic EPIC files. The EPS file identifier epfout returned from this function call will be used to refer to the EPS file. The pointer file name, the second argument, to this function can NOT be replaced by a single netCDF file name for writing.
The next EPS function to call is ep_set_next (or epsetnext for Fortran) which opens the next data file for writing. For creating a data file, the data file name should be input to this function and the function then will record the data file name to the pointer file. This function also closes a previously opened data file if there is one. Here is an example using ep_set_next or epsetnext to position the next (new) data file named ``foodata.cdf'' for writing:
C Interface
#include "epsystem.h"
...
Dbase *epfout; /* EPS data structure */
char *currentfile; /* current data file name */
...
currentfile = (char *) ep_set_next(epfout, "foodata.cdf");
...
Fortran Interface
include 'epsystem.fh'
...
integer epfout ! pointer file identifier
character currentfile*80 ! current data file name
...
currentfile = 'foodata.cdf'
call epsetnext(epfout, currentfile)
In an EPS file, each variable must have its unique variable code and this variable code will be the key used to access the variable it represents. The variable codes along with variable information for some commonly used variables are defined in the epic.key file.
There are three ways to initialize a variable code for a variable:
Here is an example to initialize variable code for variable temperature ``T'' which is defined in epic.key file with variable code 20, average temperature ``AVE_T'' which is not defined in epic.key file and salinity ``S'' which is defined in epic.key file and its generic name is ``sal'':
C Interface
#include "epsystem.h"
...
int vcdeT, vcdeVAR_T, vcdeS; /* variable codes */
int ier; /* for EPS error code */
...
vcdeT = 20; /* variable code for temperature defined in epic.key file */
vcdeVAR_T = -1; /* variable code for average temperature */
ep_find_code("sal",vcdeS,ier); /* get variable code from generic name */
if(ier) vcdeS = -2; /* if not found, assign a negative number */
...
Fortran Interface
include 'epsystem.fh'
...
integer vcdeT, vcdeVAR_T, vcdeS ! variable codes
integer ier ! for EPS error code
vcdeT = 20 ! variable code for temperature defined in epic.key file
vcdeVAR_T = -1 ! variable code for average temperature
call epfindcode('sal',vcdeS,ier) ! get variable code from generic name
if(ier .eq. 1) vcdeS = -2 ! if not found, assign a negative number
...
Note: The function ep_find_code or epfindcode for Fortran returns the variable code of the first variable whose generic name matches the input generic name. In the above example, if `sal' generic name is not found in epic.key file, then -2 will be assigned as variable code for salinity ``S''. User may want to refer to Epic.key file for the valid variable code.
Before writing out a variable, we must set the variable shape, its axis information, axis values and other variable information. Here is an example using sequences of EPS routine calls to set variable shape, axis information, axis value, then to write out values for temperature variable whose dimension size in {x,y,z,t} direction is {1,1,40,1} and the data type is EPREAL:
C Interface
#include "epsystem.h"
#define TIMES 1
#define DEPS 50
#define LONS 1
#define LATS 1
...
Dbase *epfout; /* EPS data structure */
int vcdeT; /* variable code for temperature */
int lci[4], uci[4]; /* lower and upper corner index */
int origin[4]; /* variable origin */
float lon[LONS],lat[LATS],
depth[DEPS]; /* array for lon, lat and depth */
long epstime[TIMES*2] /* array for EPS time representation */
float var[TIMES*LATS*LONS*DEPS]; /* array hold temperature data */
static int dims[4]={LONS,LATS,DEPS,TIMES}; /* var dimensions */
int mon, day, yr, hr, min; /* hold input time */
float sec;
int i;
...
/* read_input_data() is user's function reads in input data. */
read_input_data(lon,lat,depth,&yr,&mon,&day,&hr,&min,&sec,var);
...
vcdeT = 20; /* variable code for temperature */
ep_set_index(1,1,1,1,lci); /* set lower corner index */
ep_set_index(1,1,40,1,uci); /* set upper corner index */
ep_set_index(1,1,1,1,origin); /* set variable origin */
/* Following 4 lines set information for x,y,z and time axis of */
/* variable temperature, its variable code is vcdeT. */
ep_set_axis(epfout,vcdeT,1,502,"lon"," ","degree_east",EPEVEN);
ep_set_axis(epfout,vcdeT,2,500,"lat"," ","degree_north",EPEVEN);
ep_set_axis(epfout,vcdeT,3, 3,"depth"," ","m",EPEVEN);
ep_set_t_axis(epfout,vcdeT,"time"," ","",EPEVEN);
mdyhms_to_ep_time(mon,day,yr,hr,min,sec,epstime);
/* converts MDYHMS to EPS time */
/* Following 4 lines write out axis values */
ep_put_axis(epfout,vcdeT,1,origin,lci,uci,lon);
ep_put_axis(epfout,vcdeT,2,origin,lci,uci,lat);
ep_put_axis(epfout,vcdeT,3,origin,lci,uci,depth);
ep_put_t_axis(epfout,vcdeT,origin,lci,uci,epstime);
/* Set temperature variable information */
ep_set_var(epfout,vcdeT,"T","TEMPERATURE (C)","temp",
"f10.2","C",EPREAL);
/* Write out temperature variable */
ep_put_var(epfout,vcdeT,origin,lci,uci,var,dims);
...
Fortran Interface
include 'epsystem.fh'
...
parameter(TIMES=1, DEPS=50, LATS=1, LONS=1) ! dimension size
integer dims(4) ! dimensions of data array
data dims/LONS,LATS,DEPS,TIMES/
integer epfout ! pointer file identifier
integer vcdeT ! variable code for temperature
integer lci(4), uci(4) ! lower and upper corner index
integer origin(4) ! variable origin
real lon(LONS),lat(LATS),dep(DEPS) ! hold x,y,z axis array
integer epstime(TIMES,2) ! hold time axis array
real var(LONS,LATS,DEPS,TIMES) ! array to hold variable data
integer mon, day, yr, hr, min ! hold input time */
real sec
integer i
...
! read_input_data() is user's function reads in input data.
call read_input_data(lon,lat,depth,yr,mon,day,hr,min,sec,var);
...
vcdeT = 20; ! variable code for temperature
call epsetindx(1,1,1,1,lci) ! set lower corner index
call epsetindx(1,1,ndep,1,uci) ! set upper corner index
call epsetindx(1,1,1,1,origin) ! set variable origin
! Following 4 lines set information for x,y,z and time axis of
! variable temperature, its variable code is vcdeT.
call epsetaxis(epfout,vcdeT,1,502,'lon',' ','degree_east',EPEVEN)
call epsetaxis(epfout,vcdeT,2,500,'lat',' ','degree_north',EPEVEN)
call epsetaxis(epfout,vcdeT,3, 3,'depth',' ','m',EPEVEN)
call epsettaxis(epfout,varcdeT,'time',' ',' ',EPEVEN)
! converts MDYHMS to EPS time
mdyhmstoeptime(mon,day,yr,hr,min,sec,epstime)
! Following 4 lines write out axis values
call epputaxis(epfout,vcdeT,1,origin,lci,uci,lon)
call epputaxis(epfout,vcdeT,2,origin,lci,uci,lat)
call epputaxis(epfout,vcdeT,3,origin,lci,uci,depth)
call epputtaxis(epfout,vcdeT,origin,lci,uci,epstime)
! Set temperature variable information
call epsetvar(epfout,vcdeT,'T','TEMPERATURE (C)','temp',
* 'f10.2','C',EPREAL)
! Write out temperature variable
call epputvar(epfout,vcdeT,origin,lci,uci,var,dims)
...
In the above example, the third argument to function ep_set_axis (or epsetaxis for Fortran) is the axis variable code, ie. 502 for longitude, 500 for latitude and 3 for depth. The axis variable code can be set in the same way.
The function ep_set_var or epsetvar for Fortran doesn't need to be called if the variable code is defined in epic.key file and variable data type is EPREAL. We listed this function call in the example just to show how this function can be used.
Note: The functions that write variable attributes and axis attributes for a netCDF file are not shown in above example. If these functions need to be called, they must be called before ep_put_var or epputvar for Fortran.
The functions which write out the global attributes can be called either before writing axis and variable value or after that. Here is an example using ep_put_att_value and ep_add_prog_comment, or epputattval, epputvalc and epaddprogcmnt for Fortran to write global attributes to an EPS file:
C Interface
#include "epsystem.h"
...
Dbase *epfout; /* EPS data structure */
int att1;
float att2;
...
ep_put_att_value(epfout,EPCRUISE,EPCHAR,5,"JGOFS");/* char string */
att1 = 0;
ep_put_att_value(epfout,EPBOTTLE,EPINT,1,&att1); /* integer */
att2 = 28.1;
ep_put_att_value(epfout,EPAIRTEMP,EPREAL,1,&att2); /* real */
/* add program comment */
ep_add_prog_comment(epfout,"Conversion from ASCII to netCDF");
...
Fortran Interface
include 'epsystem.fh'
...
integer epfout ! pointer file identifier
...
call epputattvalc(epfout,EPCRUISE,5,'JGOFS') ! character string
call epputattval(epfout,EPBOTTLE,EPINT,1,0) ! integer
call epputattval(epfout,EPAIRTEMP,EPREAL,1,28.1) ! real
! Add program comment
call epaddprogcmnt(epfout,'Conversion from ASCII to netCDF')
...
The function ep_add_prog_comment or epaddprogcmnt for Fortran pushes the input character string onto the program comment attribute stack which can hold up to 4 program comments named EPPROGCMNT1, EPPROGCMNT2, EPPROGCMNT3 and EPPROGCMNT4. These attributes as well as EPCRUISE, EPBOTTLE and EPAIRTEMP used in above example are attribute parameter names defined in ``epsystem.h'' or ``epsystem.fh'' for Fortran. They are also listed in the attribute tables of Chapter 2, EPS File Components.
Note: In Fortran, epputattvalc must be used to write a character string attribute.
Like reading the EPS file, when you finish writing an EPS file you must call ep_close (or epclose for Fortran) to close the EPS file. Refer to the example of closing pointer file listed in the previous section.
To use EPS library, you must also have ``netcdf'' library (libnetcdf.a) on your system. The source code for these libraries are available for anonymous FTP access from:
HOST: unidata.ucar.edu
FILE: pub/netcdf/netcdf.tar.Z
On Unix system
Compile a C program:
% cc myfile.c -o myfile -leps -lnetcdf -lm
Compile a Fortran program:
% f77 myfile.f -o myfile -leps -lnetcdf -lm
On VAX
Compile a C program:
$ cc myfile.c
Compile a Fortran program:
$ fort myfile.f
then link the object files with the libraries:
$ link/executable=myfile.exe myfile.obj, -
ep_lib:epslib/lib,-
ep_lib:netcdf/lib, -
sys$library:vaxcrtl/lib
where ``ep_lib'' is a logical name for the directory where the libraries epslib and netcdf are installed (eg. ep_lib defined as disk1:[epic.lib] on PMEL's VAX system). The sys$library:vaxcrtl is the system library.
Go to the previous, next section, or Table of Contents.