Skip to main content
  • Home
  • Documentation
  • FAQ
  • Downloads
  • Support
  • Current Release Notes
  • Ferret Users Guide
    • Users Guide Index
    • Commands Reference
    • 1. Introduction
    • 2. Data Set Basics
    • 3. Variables & Expressions
    • 4. Grids & Regions
    • 5. Animations & Gif Images
    • 6. Customizing Plots
    • 7. Handling String Data Symbols
    • 8. Working with Special Data Sets
    • 9. Computing Environment
    • 10. Converting to NetCDF
    • 11. Writing External Functions
    • Glossary
    • Appendix A: Functions
    • Appendix B: PPLUS Guide
    • Appendix C: Ferret-Specific PPLUS Enhancements
  • Previous Release Notes
  • Tutorials and Demos
    • Ferret Tour
    • DSG files: Discrete Sampling Geometries Demo
    • Ferret sorting demo
    • Fast Fourier Transforms demo
    • Empirical Orthogonal Functions demo
    • Ferret objective analysis demo
    • Ferret Palette Demo
    • Map projections
    • Ferret polygon vector demo
    • Ferret Graticules demo
    • Ferret Polytube Demo
    • Ferret Polymark Demo
    • Ferret Constant-Array demo
    • Ferret land_detail demo
    • COADS Tour
    • Levitus Tour
    • Use OPeNDAP
    • Ferret binary read demo
  • PyFerret
    • PyFerret Downloads and Install ../../faq/ferret-faqs.html
    • What is PyFerret?
    • Why use PyFerret?
    • PyFerret for the Ferret user
    • PyFerret command syntax: quick-start notes
    • PyFerret for the Python user
    • Graphics in PyFerret ?
    • New Ferret functionality
    • PyFerret Python functions and constants
    • PyFerret Python objects and methods
    • Ferret external functions in Python
    • Ferret Fortran external functions
    • PyFerret metadata-and-data dictionaries
  • OPeNDAP
    • OPeNDAP usage in Ferret
    • Use OPeNDAP Demo
    • Test OPeNDAP

10.2 SIMPLE CONVERSIONS USING FERRET

In straightforward conversion operations where ASCII or unformatted binary data files are already readable by Ferret, the conversion to direct access, self-describing netCDF formatted data can be accomplished by Ferret itself. The following set of examples illustrates these procedures:

Example 1

Consider an ASCII file uv.data, with two variables, u and v, defined on a grid 360 by 180. The following set of commands will properly read in u and v and convert them to a netCDF formatted data set:

yes? DEFINE AXIS/x=1:360:1/units=degrees xaxis
yes? DEFINE AXIS/y=1:180:1/units=degrees yaxis
yes? DEFINE GRID/x=xaxis/y=yaxis uv_grid
yes? FILE/GRID=uv_grid/BAD=-999/VAR="u,v" uv.data
yes? SET VARIABLE/TITLE="zonal velocity" u
yes? SAVE/FILE=uv.cdf u,v

See command DEFINE AXIS in the Commands Reference. See the chapter "Grids and Regions" for setting up formatted latitude, longitude and time axes.

Example 2

Consider now two separate ASCII files, u.data and v.data, defined on a grid 360 by 180. The following set of commands will properly read in u and v and convert them to a single netCDF formatted data set:

yes? DEF AXIS/x=1:360:1/units=degrees xaxis
yes? DEF AXIS/y=1:180:1/units=degrees yaxis
yes? DEF GRID/x=xaxis/y=yaxis uv_grid
yes? FILE/GRID=uv_grid/BAD=-999/VAR=u u.data
yes? FILE/GRID=uv_grid/BAD=-999/VAR=v v.data
yes? SAVE/FILE=uv2.cdf u[D=1]
yes? SAVE/APPEND/FILE=uv2.cdf v[D=2]

Example 3‚ multiple time steps

Consider 12 ASCII files, uv.data1 to uv.data12, each defined on the same grid as above but each representing a successive time step. The following set of commands illustrates how to save these data into a single netCDF data set (time series):

yes? DEF AXIS/x=1:360:1 xaxis
yes? DEF AXIS/y=1:180:1 yaxis
yes? DEF AXIS/t=1:1:1 taxis1
yes? DEF GRID/x=xaxis/y=yaxis/t=taxis1 uv_grid1
yes? FILE/GRID=uv_grid1/BAD=-999/VAR="u,v" uv.data1
yes? SAVE/FILE=uv1_12t.cdf u,v
yes? CANCEL DATA uv.data1
yes? DEF AXIS/t=2:2:1 taxis1
yes? FILE/GRID=uv_grid1/BAD=-999/VAR="u,v" uv.data2
yes? SAVE/APPEND/FILE=uv1_12t.cdf u,v
. . .

and so on, redefining the time axis to be 3:3:1, 4:4:1, .. each time a new file is set.

When the input data is in netCDF files, please see the following FAQ on using data from a set of input files. Note particularly the example showing how to add time information to the variable when the grid of the input data has no time axis.

FAQ: How can I use data as a time series when it exists in multiple files?

Example 4, merging two netCDF files that contain different X-Y regions

The procedure used in example 3, above, is possible because netCDF files can be extended along the time axis. In order to append multiple regions in any dimension other than time, the netCDF file must first be created including the full span of of the non-time dimensions.

Consider two files with different XY ranges. The grids in these files agree in time, but if they differ in their time or other dimensions, add regridding in those directions to the LET commands so that the grids match. 

yes? use a1
yes? use b1
 
yes? show data
currently SET data sets:
1> ./a1.nc
name     title                             I         J         K         L
SST      SEA SURFACE TEMPERATURE          1:90      1:55      ..       1:1
 
2> ./b1.nc  (default)
name     title                             I         J         K         L
TEMP     sea surface temperature          1:90      1:46      ..       1:1
 
yes? show grid sst[d=1]
GRID GMH1
name       axis              # pts   start                end                 subset
XAXIS     LONGITUDE           90mr   1E                   179E                full
YAXIS     LATITUDE            55 r   19S                  89N                 full
normal    Z
TIME      TIME                 1mr   01-JAN-2017 00:00    01-JAN-2017 00:00   full
 
yes? show grid temp[d=2]
GRID GLS1
name       axis              # pts   start                end                 subset
LONGITUDE LONGITUDE           90mr   179W(-179)           1W(-1)              full
LATITUDE  LATITUDE            46 r   45S                  45N                 full
normal    Z
TIME      TIME                 1mr   01-JAN-2017 00:00    01-JAN-2017 00:00   full
 
 
yes? ! Define axes that span both grids. This will be the output grid of the data.
 
 
yes?  define axis/x=1:359:2/units=degrees_east xbig
yes?  define axis/y=-45:89:2/units=degrees_north ybig
 
yes? set data 1
yes? let/like=sst sst_merged =  sst[gx=xbig,gy=ybig]
 
yes? ! Create the file using /XLIMITS and /YLIMITS to write the entire span of these axes
yes? ! to the file, and /X= and /Y= to specify the range of the variable we are writing
 
yes?  save/clobber/file=bigfile.nc/xlimits=1:359/ylimits=-45:89/x=1:179/y=-19:89 sst_merged
LISTing to file bigfile.nc
 
yes? ! Now, from the second file, define a variable with the same name.
 
yes? set data 2
yes? let/like=sst[d=1] sst_merged = temp[gx=xbig,gy=ybig]
 
yes? ! Write this data using the /APPEND qualifier. The data will overwrite
yes? ! the data in the file, only over the range of coordinates specified
 
yes? save/append/file=bigfile.nc/x=181:359/y=-45:45 sst_merged
LISTing to file bigfile.nc
 
yes? ! Now look at what we have created.  The listing spans data from both original datasets.
 
yes? cancel data/all
yes? cancel variable/all
 
yes? use bigfile.nc
yes? show grid sst_merged
    GRID GPJ1
 name       axis              # pts   start                end                 subset
 XBIG      LONGITUDE          180mr   1E                   1W                  full
 YBIG      LATITUDE            68 r   45S                  89N                 full
 normal    Z
 TIME      TIME                 1mr   01-JAN-2017 00:00    01-JAN-2017 00:00   full
 
 
yes? list/x=170:190/y=0 sst_merged
VARIABLE : SEA SURFACE TEMPERATURE (Deg C)
FILENAME : bigfile.nc
SUBSET   : 10 points (LONGITUDE)
LATITUDE : 1S
TIME     : 01-JAN-2017 00:00
1S    
23
171E   / 86:  29.00
173E   / 87:  28.59
175E   / 88:  28.31
177E   / 89:  28.69
179E   / 90:  28.20
179W   / 91:  28.86
177W   / 92:  27.98
175W   / 93:  27.80
173W   / 94:  28.29
171W   / 95:  27.94

 

Example 5‚ multiple slabs

The procedure used in example 3 above, is possible because netCDF files can be extended along the time axis. In order to append multiple levels (Z axis), the netCDF file must first be created including all of its vertical levels (the levels initially are filled with a missing data flag).

Consider 5 ASCII files, uv.data1 to uv.data5, each defined on the same grid as above but each representing a successive vertical level. Note that the output grid has an axis containing all the Z levels that the file will contain (and that the other Z axes, zaxis1, zaxis2, .. are defined only for the purpose of reading the data in). The following set of commands illustrates how to save these data into a single netCDF data set.

NOTE: It is best to define a fixed-length axis in the "append" direction, as in the example below.  If the axis in that direction is an abstract axis, for instance from a function such as XSEQUENCE or ESEQUENCE, the results will not be appended in Ferret v7.4 and previous versions.

yes? DEF AXIS/x=1:360:1 xaxis
yes? DEF AXIS/y=1:180:1 yaxis
yes? DEF AXIS/Z=0:100:25/DEPTH zaxis
yes? DEF GRID/X=xaxis/Y=yaxis/Z=zaxis uv_grid
yes? DEF AXIS/Z=0:0:1 zaxis1
yes? DEF GRID/LIKE=uv_grid/Z=zaxis1 uv_grid1
 
yes? FILE/GRID=uv_grid1/BAD=-999/VAR="u,v" uv.data1
yes? LET/TITLE="My U data" u1 = u[G=uv_grid@NRST]
yes? LET/TITLE="My V data" v1 = v[G=uv_grid@NRST]
yes? SAVE/FILE=uv1_5z.cdf/KLIMITS=1:5/K=1 u1, v1
 
yes? CANCEL DATA uv.data1
yes? DEF AXIS/Z=25:25:1 zaxis1
yes? FILE/GRID=uv_grid1/BAD=-999/VAR="u,v" uv.data2
yes? SAVE/FILE=uv1_5z.cdf/K=2/APPEND u1,v1
. . .
yes? CANCEL DATA/ALL ! Cancel definitions before using new file
yes? CANCEL VAR/ALL
yes? USE uv1_5z.cdf

The @NRST above ensures that the regridding between the uv_grid and uv_grid1 will always work correctly.  If the coordinate values are not simple integers, our definition of the axis zaxis and the value used to define the axis zaxis1 may not exactly match.  @NRST regridding is needed so that the result will be on our grid uv_grid.

What if the data is in netCDF files to begin with, each file containing a Z level?  Often separate files for different levels do not have a grid in the Z direction, so we'll need to handle that.  Say the files are ocean_lev0m.nc, ocean_lev5m.nc, ocean_lev20m.nc containing data at those three depths.  There might be some attributes in the file that describe the depth, or the information may be just in the dataset name; but there is no z axis.

yes? use ocean_lev0m.nc
yes? show data
currently SET data sets:
1> ./ocean_lev0m.nc  (default)
name     title                    I         J         K         L
U        Zonal Current           1:180     1:90      ..       1:12
V        Meridional Current      1:180     1:90      ..       1:12

Define the appropriate output Z axis with all of the depths.  Define variables ucur and vcur which are simply the data from the file repeated at each depth.  This uses the concept of "conformability", how variables with unlike grids may be combined. Define the new variable that has a Z axis from that newly named file variable, and set the attributes for the new variable  to be inherited from the file variable.

yes? define axis/z/depth/units=meters zdepth = {0,5,20}
 
yes? use ocean_lev0m.nc
yes? sh dat
 
yes? let ucur = u + 0*z[gz=zdepth]
yes? set attributes/like=u ucur
yes? save/clobber/file=ocean_data.nc/klimits=1:3/k=1 ucur
 
! Define and save v.
! The first SAVE for each variable needs /KLIMITS
 
yes? let vcur = v + 0*z[gz=zdepth]
yes? set attributes/like=v vcur
yes? save/append/file=ocean_data.nc/klimits=1:3/k=1 vcur
 
yes? cancel data ocean_lev0m.nc
 
! The definitions for ucur and vcur remain and apply to the
! current default dataset as we open each one.
 
yes? use ocean_lev5m.nc
yes? save/append/file=ocean_data.nc/k=2 ucur
yes? save/append/file=ocean_data.nc/k=2 vcur
 
yes? cancel data ocean_lev5m.nc
 
yes? use ocean_lev20m.nc
yes? save/append/file=ocean_data.nc/k=3 ucur
yes? save/append/file=ocean_data.nc/k=3 vcur
 
yes? cancel data/all
yes? cancel variables/all
 
yes? use ocean_data.nc
yes? show data
 
currently SET data sets:
1> ./ocean_data.nc  (default)
name     title                             I         J         K         L
UCUR     zonal current                    1:180     1:90      1:3       1:12
VCUR     meridional current               1:180     1:90      1:3       1:12
 
yes? show grid ucur
GRID GLO1
name       axis              # pts   start                end                 subset
XAX_SUBSET LONGITUDE         180mr   20.5E                18.5E(378.5)        full
YAX_SUBSET LATITUDE           90 r   89.5S                88.5N               full
ZDEPTH    DEPTH (m)            3 i-  0                    20                  full
TIME      TIME                12mr   16-JAN 06:00         16-DEC 01:20        full

 

Example 6‚ another with multiple slabs

Here we define a variable at each X location of an existing variable, and write them, appending them to a netCDF file. The expression uses the @MAX transformation in the X direction, so the result has no x axis. We'll define a new one-point x axis at each point.
 

yes? USE levitus_climatology
 
! Define a variable containing the xaxis locations
yes? LET lon = x[gx=temp]
 
! Define the variable at the first X, put it on a one-point X axis,
! and then onto the full x axis of the variable.
 
yes? DEFINE AXIS/X/UNITS="`temp,return=xunits`" xout = `lon[i=1]`
yes? SHOW AXIS xout
name axis # pts start end
XOUT LONGITUDE 1mr 20.5E 20.5E
Axis span (to cell edges) = 1 (modulo length = 360)
 
yes? LET mtmp1 = temp[X=`lon[i=1]`:300@MAX] + 0*x[GX=xout]
!-> DEFINE VARIABLE mtmp1 = temp[X=20.5:300@MAX] + 0*x[GX=xout]
 
! see its grid has a single-point x axis
yes? SHOW GRID mtmp1 
GRID (G003)
name axis # pts start end
XOUT LONGITUDE 1mr 20.5E 20.5E
YAXLEVITR LATITUDE 180 r 89.5S 89.5N
ZAXLEVITR DEPTH (m) 20 i- 0 5000
normal T
 
! put the variable onto the full X grid.
 
yes? LET mtmp = mtmp1[GX=temp]

 ! This is the result at the first location saved to the full x axis.
! Write out the first x value, and use /ILIMITS to set up the full 
! range in x that we'll be writing to the file
 
yes? SAVE/CLOBBER/FILE=mout.nc/ILIMITS=1:90/I=1 mtmp
 
! Now do the same for each other X location. The variable
 ! at each X-step needs its own one-point x axis.
yes? PAUSE
 
yes? REPEAT/RANGE=2:30/NAME=inx (LET xstart = lon[I=`inx`];\
DEFINE AXIS/X/UNITS="`temp,RETURN=xunits`" xout = `xstart`;\
LET mtmp1 = temp[X=`xstart`:300@MAX] + 0*x[GX=xout];\
LET mtmp = mtmp1[GX=temp@ave];\
SAVE/APPEND/FILE=mout.nc/i=`inx` mtmp)
 

 

The netCDF utilities "ncdump" and "ncgen" can also be combined with a text editor to make final refinements to the netCDF files created by SAVE. (These utilities can be obtained from https://www.unidata.ucar.edu/. Here is a simple example that removes all "history" attributes from a netCDF file using pipes and the Unix "grep" utility:

% ncdump old_file.cdf | grep -v history | ncgen -o new_file.cdf

In addition, the toolset "NetCDF Operator", or NCO, contains a number of operators for manipulating netCDF files. This software can be found at https://nco.sourceforge.net/