Appendix A: EXTERNAL FUNCTIONS 

A number of external functions are included with the Ferret distribution. This number is expected to grow as Ferret developers and users contribute more functions. See the chapter "Writing External Functions" (p. 293) for how to adapt your Fortran code to a Ferret external function. Send your contributions to the Users Guide editor at oar.pmel.contact_ferret@noaa.gov

Many of these functions, originally developed as external functions, are now linked into the Ferret executable as static functions. The code for them is still available on the Ferret external functions web page. 

The functions are listed in the following sections. To see what functions are available to you, type 

yes? SHOW FUNCTION/EXTERNAL 

or 

yes? SHOW FUNCTIONS/DETAILS/EXTERNAL function_name 

gives further details on how the arguments influence the grid for the function's result. 


Appendix A Sec1.  COMPRESSI 

COMPRESSI(DAT)    Returns data, compressed along the I axis: Missing points moved to the end 

Arguments: 

DAT 

DAT: variable to compress in I 

Result Axes: 

ABSTRACT, same length as DAT x-axis 

 

Inherited from DAT 

 

Inherited from DAT 

 

Inherited from DAT 

Note:
It is generally advisable to include explicit limits when working with functions that replace axes. for example, consider the function compressi(v). The expression 

list/i=6:10 compressi(v) 

is not equivalent to 

list compressi(v[i=6:10]) 

The former will list the 6th through 10th compressed indices from the entire i range of variable v. the latter will list all of the indices that result from compressing v[i=6:10]. 


Appendix A Sec2.  COMPRESSJ 

COMPRESSJ(DAT)    Returns data, compressed along the J axis: Missing points moved to the end 

Arguments: 

DAT 

DAT: variable to compress in J 

Result Axes: 

Inherited from DAT 

 

ABSTRACT, same length as DAT y-axis 

 

Inherited from DAT 

 

Inherited from DAT 

Note: see the note under COMPRESSI on specifying axis limits (p. 75


Appendix A Sec3.  COMPRESSK 

COMPRESSK(DAT)    Returns data, compressed along the I axis: Missing points moved to the end 

Arguments: 

DAT 

DAT: variable to compress in K 

Result Axes: 

Inherited from DAT 

 

Inherited from DAT 

 

ABSTRACT, same length as DAT z-axis 

 

Inherited from DAT 

Note: see the note under COMPRESSI on specifying axis limits (p. 75


Appendix A Sec4.  COMPRESSL 

COMPRESSL(DAT)    Returns data, compressed along the L axis: Missing points moved to the end 

Arguments: 

DAT 

DAT: variable to compress in L 

Result Axes: 

Inherited from DAT 

 

Inherited from DAT 

 

Inherited from DAT 

 

ABSTRACT, same length as DAT t-axis 

Note: see the note under COMPRESSI on specifying axis limits (p. 75


Appendix A Sec5.  COMPRESSI_BY 

COMPRESSI_BY (var, mask), Compress data according to a mask 

Arguments: 

VAR 

Variable to compress according to MASK 

 

MASK 

mask to use in compressing the data 

Result Axes: 

Abstract 

 

Inherited from VAR and MASK 

 

Inherited from VAR and MASK 

 

Inherited from VAR and MASK 

Compress variable "dat" along its I axis using the (multi-dimensional) mask supplied in the second  argument. 

For example: 

yes? LET mask = {1,,1,,1} + 0*L[l=101:102] + 0*K[k=10:11]
yes? LIST mask
               {1,,1,,1} + 0*L[L=101:102] + 0*K[K=10:11]
                   1      2      3      4      5
                   1      2      3      4      5
     ---- L:101 T:   101
     10   / 10:  1.000   ....  1.000   ....  1.000
     11   / 11:  1.000   ....  1.000   ....  1.000
     ---- L:102 T:   102
     10   / 10:  1.000   ....  1.000   ....  1.000
     11   / 11:  1.000   ....  1.000   ....  1.000

yes?  LIST compressi_by({11,22,33,44,55},mask)
                 COMPRESSI_BY({11,22,33,44,55},MASK)
                   1      2      3      4      5
                   1      2      3      4      5
     ---- L:101 T:   101
     10   / 10:  11.00  33.00  55.00   ....   ....
     11   / 11:  11.00  33.00  55.00   ....   ....
     ---- L:102 T:   102
     10   / 10:  11.00  33.00  55.00   ....   ....
     11   / 11:  11.00  33.00  55.00   ....   .... 



Appendix A Sec6.  COMPRESSJ_BY 

COMPRESSJ_BY (var, mask), Compress data according to a mask 

Compress variable "dat" along its J axis using the (multi-dimensional) mask supplied in the second  argument. See the example under COMPRESSI_by. 


Appendix A Sec7.  COMPRESSK_BY 

COMPRESSK_BY (var, mask), Compress data according to a mask 

Arguments: 

VAR 

Variable to compress according to MASK 

 

MASK 

mask to use in compressing the data 

Result Axes: 

Inherited from VAR and MASK 

 

Inherited from VAR and MASK 

 

Abstract 

 

Inherited from VAR and MASK 

Compress variable "dat" along its K axis using the (multi-dimensional) mask supplied in the second  argument. See the example under COMPRESSI_by. 


Appendix A Sec8.  COMPRESSL_BY 

COMPRESSL_BY (var, mask), Compress data according to a mask 

Arguments: 

VAR 

Variable to compress according to MASK 

 

MASK 

mask to use in compressing the data 

Result Axes: 

Inherited from VAR and MASK 

 

Inherited from VAR and MASK 

 

Inherited from VAR and MASK 

 

Abstract 

 Compress variable "dat" along its L axis using the (multi-dimensional) mask supplied in the second  argument. See the example under COMPRESSI_by. 


Appendix A Sec9.  CONVOLVEI 

CONVOLVEI (VAR, WEIGHT), CONVOLVEJ (VAR, WEIGHT) ,
CONVOLVEK (VAR, WEIGHT),  CONVOLVE L (VAR, WEIGHT)
 
Convolve I (J,K,or L)component of variable with weight function 

Arguments: 

VAR 

COM:  variable  to convolve 

 

WEIGHT 

Weight function 

Result Axes: 

Inherited from VAR 

 

Inherited from VAR 

 

Inherited from VAR 

 

Inherited from VAR 

This function (and likewise CONVOLVEJ, CONVOLVEK, and CONVOLVEL) convolves the variable VAR, with the weight function, wt  along the X axis. Note that the variable's context may not be of adequate size for the full calculation. Missing data flags will be inserted where computation is impossible. 

When bad data points are encountered in the component data all result data depending on it are flagged as bad, too. 

The weight function is applied at each point from i-hlen to i+hlen, where hlen is half the length of the weight function. If the function is of even length, a zero weight is used at the upper end. Thus if the weights were {0.1, 0.4, 0.4, 0.1} the result at point I would be computed as the sum 0.1* COM(i-2) + 0.4* com(i-1) + 0.4* COM(i) + 0.1* COM(i+1) + 0.* COM(i+2) 

Example: 

Use the function to smooth a variable. 

yes? LET weight = {0.25, 0.5, 0.25}
yes? LET c = SIN(x[x=0:10:.1]) + RANDU(X[X=0:10:.1])/5
yes? PLOT c
yes? PLOT/OVER/TITLE="convolvei" CONVOLVEI(c,weight) 



Appendix A Sec10.  CURV_TO_RECT_MAP 

CURV_TO_RECT_MAP(lon_in, lat_in, grid_out, radius) 

Computes mapping parameters for regridding from a curvilinear grid (see p. 252) to a rectilinear latitude-longitude grid. The mapping is applied to data with the function CURV_TO_RECT which interpolates the data to the rectilinear grid. This computation uses a spherical interpolation code written at GFDL; the Ferret developers are responsible for its implementation as an external function. 

The output of this function is a set of mapping parameters; this mapping may be saved and applied to interpolate any field on the curvilinear grid onto the output rectangular grid. 

Arguments: 

lon_in 

Source grid longitudes, in degrees (2-D field of longitudes describing the curvilinear grid) 

 

lat_in 

Source grid latitudes, in degrees (2-D field of latitudes describing the curvilinear grid) 

 

grid_out 

Any variable on the output recangular lon-lat grid. This grid may have irregularly spaced longitude and/or latitude axes 

 

radius     

Source points falling within radius (in degrees) of destination point are included in the mapping to the destination point. Described further below. 

Result Axes: 

Inherited from grid_out 

 

Inherited from grid_out 

 

Abstract 

 

Abstract 

This function does large amounts of calculation, and so runs slowly. It is recommended that you compute mappings from the curvilinear grid to desired rectilinear grid(s) and save them for use with your data fields. For an example of a call to this function see the documentation for the function CURV_TO_RECT, below (p. 467). 

The following figure illustrates a destination grid location (*) with a radius of influence R. Valid source curvilinear grid locations (o) which fall within the radius of influence of the destination point are used in the mapping. Missing source points (x) do not contribute to the mapping. In this case, 13 valid source grid points fall within the radius of influence.  

AppA_schematic

The radius parameter should be chosen to be somewhat larger than the size of the input curvilinear grid cells so that any output grid location will have some input data contributing to its value. 

e the value.The variable MAP, the result of a call to function CURV_TO_RECT_MAP, contains weights and  the indices of the longitudes and latitudes of the curvilinear grid that correspond to the coordinates of the output grid. Below, in_curv_lon and in_curv_lat are the index value from the input curvilinear grid that correspond to the longitude and latitude of the rectangular output grid. The parameter num_neighbors is 4;  the code looks around at four neighboring grid cells. 

The weights are based on the distance from the source to the result grid points. The output variable map, then contains: 

        for each  m = 1, nlon_out 

        for each  n = 1, nlat_out 


            for each k=1, num_neighbors 


               MAP(m,n,k,1) = weight(m,n,k) 

               MAP(m,n,k,2) = in_curv_lon(m,n,k) 

               MAP(m,n,k,3) = in_curv_lat(m,n,k) 

This may be used to determine the range of indices required in order to specify a subset of data on a curvilinear grid. See the FAQ,  Plotting subsets of data on a curvilinear grid http://ferret.pmel.noaa.gov/FERRET_17sep07/FAQ/custom_plots/subsetting_curvi_data.html, for an outline of the procedure. 


Appendix A Sec11.  CURV_TO_RECT 

CURV_TO_RECT (V, mapping) 

Applies the mapping computed by function CURV_TO_RECT_MAP to interpolate data from a curvilinear to a rectilinear latitude-longitude grid. This computation employs a spherical interpolation code written at GFDL; the Ferret developers are responsible for its implementation as an external function. 

Arguments: 

Variable on the source curvilinear grid 

 

mapping 

mapping from the source grid to a rectilinear grid 

Result Axes: 

Inherited from mapping 

 

Inherited from mapping 

 

Inherited from V 

 

Inherited from V 

This is a grid-changing function. Indicate limitson the argument axes with square brackets []. See the note on grid-changing functions in Chapter 3 (p. 77

Example of calls to CURV_TO_RECT_MAP and CURV_TO_RECT: 

yes? use my_curvilinear_data.nc
yes? show data
    currently SET data sets:
   1> /.my_curvilinear_data.nc  (default)
name     title                         I      J      K    L
GEOLON  geographic longitude of grid  1:180  1:173   ...   ...
GEOLAT  geographic latitude of grid   1:180  1:173   ...   ...
SALT    salinity                      1:180  1:173  1:30  1:12
AIRT  air temperature                 1:180  1:173  1:30  1:12
 

yes? ! For convenience define variables with the input grid 

yes? let lonin = geolon[d=1]
yes? let latin = geolat[d=1]
 

yes? ! Define output grid and a variable on the output grid 

yes? define axis/x=0:360:5/modulo/units=degrees xax
yes? def axis/y=0:85:5/units=degrees yax
yes? let lonlatout = y[gy=yax] + x[gx=xax]
 

yes? ! Compute the mapping to the rectangular grid, save to a file
yes? let map = curv_to_rect_map ( lonin,latin,lonlatout,10)
yes? save/clobber/file=curv_map.nc  map
 

yes? ! Apply the mapping to the data fields 

yes? cancel var/all
yes? use curv_map.nc
yes? let out_salt = curv_to_rect(salt[d=1,K=1,L=2], map[d=2]) 

yes? shade out_salt 


yes? let out_airt = curv_to_rect(airt[d=1], map[d=2]) 

yes? save/file=air_on_rect.nc out_airt 



Appendix A Sec12.  RECT_TO_CURV 

RECT_TO_CURV (V, lon_bounds_out, lat_bounds_out, missing_allowed)   Uses Bilinear Interpolation to regrid data on a recilinear grid to a curvilinear grid. 

Arguments: 

Variable on the source rectilinear grid 

 

lon_bounds_out 

Destination grid longitudes, in degrees (2-D field of longitudes describing the curvilinear grid) 

 

lat_bounds_out 

Destination grid latitudes, in degrees (2-D field of latitudes describing the curvilinear grid) 

 

missing_allowed 

Number of missing values allowed among the 4 surrounding source cells: 0 to 3 

Result Axes: 

Inherited from lon_bounds_out 

 

Inherited from lat_bounds_out 

 

Inherited from V 

 

Inherited from V 

Example: put a rectilinear data set on a curvilinear grid for comparison. 

yes? use my_curvilinear_data.nc
yes? use levitus_climatology

yes? show data
    currently SET data sets:
   1> /.my_curvilinear_data.nc  
name     title                         I      J      K    L
GEOLON  geographic longitude of grid  1:180  1:173   ...   ...
GEOLAT  geographic latitude of grid   1:180  1:173   ...   ...
SALT    salinity                      1:180  1:173  1:30  1:12
AIRT  air temperature                 1:180  1:173  1:30  1:12
 

    2> /home/ja9/tmap/fer_dsets/data/levitus_climatology.cdf  (default)
name     title                         I      J      K    L
TEMP     TEMPERATURE                  1:360  1:180  1:20   ...
SALT     SALINITY                     1:360  1:180  1:20   ... 


yes? ! For convenience, define variables for arguments to RECT_TO_CURV  

yes? let lonout = geolon[d=1]
yes? let latout = geolat[d=1]
 

yes? let a = rect_to_curv(temp[d=2,k=1], lonout, latout, 2)
yes? shade a, lonout, latout
 

yes? ! Compare to a variable on the curvilinear grid 

yes? shade a-airt[d=1], lonout, latout
 

yes? ! save the new variable for all depths, with the curvilinear 

yes? ! latitude and longitude variables

yes? let temp_curv = rect_to_curv(temp[d=2], lonout, latout, 2)
yes? save/file=tcurv.nc temp_curv, lonout, latout
LISTing to file tcurv.nc 



Appendix A Sec13.  DATE1900 

DATE1900(formatted date)    Scalar function: converts a formatted date into Julian days since 1-Jan-1900. 

Argument: 

formatted date 

dd-mmm-yyyy   or dd-mmm-yyyy, in quotes 

     

Result Axes: 

NORMAL (no axis) 

 

NORMAL (no axis) 

 

NORMAL (no axis) 

 

NORMAL (no axis) 

Examples: 

yes?  list date1900("23-feb-2003")
            VARIABLE : DATE1900("23-feb-2003")
         37673.
yes? list date1900("2-jan-1900")
            VARIABLE : DATE1900("2-jan-1900") 

          1.000 




Appendix A Sec14.  DAYS1900TOYMDHMS 

DAYS1900TOYMDHMS(day1900) Converts Julian days since 1-Jan-1900 to values year, month, day, hour, minute, second. 

Argument: 

day1900 

Julian day counted from 1-jan-1900 

     

Result Axes: 

Inherited from argument 

 

Inherited from argument 

 

ABSTRACT (results occupy indices 1...6) 

 

Inherited from argument 

This function applies only to time in the standard, Gregorian calendar. 

Example: 

   Create a variable based on a time axis. List the result of DAYS1900TOYMDHMS. 

yes? DEF AXIS/T=28-JAN-2003:3-FEB-2003:1/UNITS=days/T0=1-JAN-1900 timeax
yes? LET tday = T[gt=timeax]
yes? LIST days1900toymdhms(tday)
            VARIABLE : DAYS1900TOYMDHMS(TDAY)
            SUBSET   : 6 by 9 points (Z-TIME)
                       1      2      3      4      5      6    
                       1      2      3      4      5      6
28-JAN-2003 00 / 1:  2003.     1.    28.     0.     0.     0.
29-JAN-2003 00 / 2:  2003.     1.    29.     0.     0.     0.
30-JAN-2003 00 / 3:  2003.     1.    30.     0.     0.     0.
31-JAN-2003 00 / 4:  2003.     1.    31.     0.     0.     0.
01-FEB-2003 00 / 5:  2003.     2.     1.     0.     0.     0.
02-FEB-2003 00 / 6:  2003.     2.     2.     0.     0.     0.
03-FEB-2003 00 / 7:  2003.     2.     3.     0.     0.     0. 



Appendix A Sec15.  ELEMENT_INDEX 

ELEMENT_INDEX(A, B) Returns index value in B for each point in A 

Example 

yes? LIST  ELEMENT_INDEX({6,5,4,3,2,1}, {1,2,3})
            VARIABLE : ELEMENT_INDEX ({6,5,4,3,2,1}, {1,2,3})
            SUBSET   : 6 points (X)
1   / 1:   ....
2   / 2:   ....
3   / 3:   ....
4   / 4:  3.000
5   / 5:  2.000
6   / 6:  1.000 



Appendix A Sec16.  ELEMENT_INDEX_STRING 

ELEMENT_INDEX_STRING(A, B) Returns index value in B for each string in A. The string comparisons are case-sensitive. 

Arguments: 

string data to mask 

 

list of strings to match 

     

Result Axes: 

Inherited from argument A 

 

Inherited from argument A 

 

Inherited from argument A 

 

Inherited from argument A 

Example 

(See ELEMENT_INDEX) above for a simple example of the numeric case. ) 

Say we have a dataset that contains a string variable called institute for a collection of stations, and station locations  xloc, yloc. Use ELEMENT_INDEX_STR to draw a polygon plot where the ! data stations belonging to each institute is shown by a dot with a unique color for each institution. 

yes? USE obsdata.nc   ! contains a variable called institute

yes? LET inst_names = {“NOAA”, “WHOI”, “FSU”, “BOM”}
yes? LET code = IS_ELEMENT_STR(institute, inst_names)

yes? LIST institute, code
      X: 0.5 to 53.5 

    Column 1: INSTITUTE 

    Column 2: CODE is ELEMENT_INDEX_STR(institute, {“NOAA”, “FSU”, “BOM”, “WHOI”})
   INSTITUTE CODE
    1 / 1: “NOAA” 1.000
    2 / 2: “WHOI” 4.000
    3 / 3: “FSU” 2.000
    4 / 4: “BOM” 3.000
    5 / 5: “NOAA” 1.000
    6 / 6: “BOM” 3.000
    ...
yes? GO basemap X=120:250 Y=25S:65N 20
yes? GO polymark POLY/OVER/PALETTE=rainbow_by_levels/LEV=(1,5,1) \ xloc, yloc, code, square, 0.2 



Appendix A Sec17.  EOF_SPACE 

EOF_SPACE(A, FRAC_TIMESER) Returns EOF (Empirical Orthogonal Function) spacial fields(eigenfunctions) from x-y-z-time field 

Arguments: 

Variable in any spatial dimensions, and time 

 

FRAC_TIMESER 

 

Use only those time series with this fraction valid data, e.g. 0.8 to require that 80% of the data be present to use the data at a location. 

Result Axes: 

Inherited from A 

 

Inherited from A 

 

Inherited from A 

 

ABSTRACT 1 to NEOF 

The EOF functions all make the same computations, returning different portions of the results. EOF_SPACE returns the eigenfunctions, normalized so that they have the units of data, while time amplitude functions (TAF's) are dimensionless. Thus the sum of the values of a given EOF = sqrt(eigenvalue), and the mean of a given TAF = 1. EOF_STAT returns some useful statistics: the number of EOF's which were computed and normalized for the parameters given; the %variation explained for each eigenfunction, and the eigenvalues. 

Specifying the context of the input variable explicitly e.g. 

 EOF_SPACE(A[x=20:40,y=2s:40n,l=1:58],FRAC_TIMESER) 

will prevent any confusion about the region. See the note in chapter 3 (p.77 )on the context of variables passed to functions. 

The method is an implementation of Chelton's '82 method for finding EOFs of gappy time series. If there are no gaps, it reduces to ordinary EOFs. 

The EOF analysis solves a matrix problem where the matrix is dimensioned (NX*NY*NZ) by NT, which can quickly become quite large. The EOF functions use other workspace as well which demands even more memory, and often memory must be increased with the SET MEMORY command. Regridding to a coarser grid or restricting the region may be necessary. 

See the example under EOF_STAT for more on the input parameters, and see the demonstration ef_eof_demo.jnl for examples of this function. 

Note: Earlier versions of the EOF functions had one more parameter. Check the version you have by saying 

yes? SHOW FUNCTION eof* 



Appendix A Sec18.  EOF_STAT 

EOF_STAT(A,FRAC_TIMESER) Used with EOF_SPACE and/or EOF_TFUNC. Return statistics related to an EOF solution for a given set of parameters. Results are on the x-axis j = 1: # EOFscomputed and scaled, j = 2: % percentage of total variance accounted for by each eigenvector, j = 3: the eigenvalues. 

Arguments: 

Variable in any spatial dimensions, and time 

 

FRAC_TIMESER 

Use only those time series with this fraction valid data, e.g. 0.8 to require that 80% of the data be present to use the data at a location. 

Result Axes: 

ABSTRACT: 1 to NEOF 

 

ABSTRACT: 1 through 3 as outlined in the description. 

 

NORMAL (no axis) 

 

NORMAL (no axis) 

Please see the discussion under EOF_SPACE, and see the demonstration ef_eof_demo.jnl for examples of this function. 

Example results: 

For a simple sample function, eof_stat called to decompose it into eigenfunctions. We allow data to be used if the time series at the point has at least 80% valid data. 

Request the number of eigenvalues computed for this choice of parameters. 

yes? list/i=1/j=1 eofstat
            VARIABLE : EOF_STAT(SST[X=67W:1W,Y=11S:11N], 0.8)0
            DATA SET : COADS Monthly Climatology (1946-1989)
            FILENAME : coads_climatology.des
            FILEPATH : /home/ja9/tmap/fer_dsets/descr/
            X        : 1
            Y        : 1
         284.0 

Now get the percent variance explained by the eigenfunctions which were computed. 

yes? list/i=1:10/j=2 eofstat
            VARIABLE : EOF_STAT(SST[X=67W:1W,Y=11S:11N], 0.8)
            DATA SET : COADS Monthly Climatology (1946-1989)
            FILENAME : coads_climatology.des
            FILEPATH : /home/ja9/tmap/fer_dsets/descr/
            SUBSET   : 10 points (X)
            Y        : 2
              2    
              2
1    /  1:  86.95
2    /  2:   5.82
3    /  3:   3.87
4    /  4:   1.51
5    /  5:   0.56
6    /  6:   0.38
7    /  7:   0.31
8    /  8:   0.23
9    /  9:   0.15
10   / 10:   0.11 

And finally the eigenvalues associated with these eigenfunctions. 

yes? list/i=1:10/j=3 eofstat
            VARIABLE : EOF_STAT(SST[X=67W:1W,Y=11S:11N], 0.8)
            DATA SET : COADS Monthly Climatology (1946-1989)
            FILENAME : coads_climatology.des
            FILEPATH : /home/ja9/tmap/fer_dsets/descr/
            SUBSET   : 10 points (X)
            Y        : 3
              3    
              3
1    /  1:  249.4
2    /  2:   16.7
3    /  3:   11.1
4    /  4:    4.3
5    /  5:    1.6
6    /  6:    1.1
7    /  7:    0.9
8    /  8:    0.7
9    /  9:    0.4
10   / 10:    0.3 



Appendix A Sec19.  EOF_TFUNC 

EOF_TFUNC(A, FRAC_TIMESER) Compute EOF time amplitude functions from x-y-z-time field w/gaps. 

Please see the discussion under EOF_SPACE, and see the demonstration ef_eof_demo.jnl for examples of this function. 

The time amplitude functions (TAF's) are dimension less; and the mean of a given TAF = 1. They are returned as follows: For x=1, time amplitude function corresponding to the first eigenfunction is the time series with t=1:NT. 


Appendix A Sec20.  FINDHI 

FINDHI(A,XRANGE,YRANGE)  Find local maxima of a variable. 

Arguments: 

Variable in x and y, may be a function of z and/or t 

 

XRANGE 

Range in data units of the X radius in which the function looks for maxima 

 

YRANGE 

Range in data units of the Y radius in which the function looks for maxima 

Result Axes: 

ABSTRACT 

 

ABSTRACT: j=1:3 

 

Inherited from A 

 

Inherited from A 

The maxima are listed along the X axis: j=1 contains the X locations of the points, j=2 contains the Y coordinates of the points, and j=3 contains the function values at the maxima. 

This function looks for the maximumm gridded value in the neighborhood x+/- XRANGE, Y+/- YRANGE. It returns only values in the interior of the region, not on boundaries. It is an implementaion of the NCAR graphics routine "minmax" 

The GO script label_hi_lo.jnl makes it easy to call this function and label and label low's and high's with either their numerical value or the letters L and H. See the demonstration script minmax_label_demo.jnl 

Also see the script bullseye.jnl which locates and marks a "bullseye", i.e. a local minimum or maximum in a 2-D field within a user-specified region. 


Appendix A Sec21.  FINDLO 

FINDLO(A,XRANGE,YRANGE)  Find local minima of a variable. 

Arguments: 

Variable in  x and y,  may be a function of z and/or t 

 

XRANGE 

Range in data units of the X radius in which the function looks for minima 

 

YRANGE 

Range in data units of the Y radius in which the function looks for minima 

Result Axes: 

ABSTRACT 

 

ABSTRACT: j=1:3 

 

Inherited from A 

 

Inherited from A 

The minima are listed along the X axis: j=1 contains the X locations of the points, j=2 contains the Y coordinates of the points, and j=3 contains the function values at the minima. 

This function looks for the minimumm gridded value in the neighborhood x+/- XRANGE, Y+/- YRANGE. It returns only values in the interior of the region, not on boundaries. It is an implementaion of the NCAR graphics routine "minmax". 

The GO script label_hi_lo.jnl makes it easy to call this function and label and label low's and high's with either their numerical value or the letters L and H. See the demonstration script minmax_label_demo.jnl 

Also see the script bullseye.jnl  which locates and marks a "bullseye", i.e. a local minimum or maximum in a 2-D field within a user-specified region. 


Appendix A Sec22.  FFT_IM 

FFT_IM(A) computes the imaginary part of Fast Fourier Transform of time series in variable A 

Arguments: 

Variable with a regular time axis; may be a function of x, y, and/or z 

Result Axes: 

Inherited from A     

 

Inherited from A 

 

Inherited from A 

 

Generated by the function: frequency in cyc/(time units from A) 

The units of the returned time axis are "cycles/Dt"  where Dt is the time increment. 

Even and odd N's are allowed. N need not be a power of 2. FFT_RE and FFTP_IM assume f(1)=f(N+1), and the user gives the routines the first N pts. 

Specifying the context of the input variable explicitly e.g. 

LIST FFT_IM(A[l=1:58]) 

will prevent any confusion about the region. See the note in chapter 3 (p. 77)on the context of variables passed to functions. 

The code is based on the FFT  routines in  Swarztrauber's FFTPACK available at www.netlib.org. See the section on FFTA for more discussion  (p. 86). For further discussion of the FFTPACK code, please see the document, Notes on FFTPACK - A Package of Fast Fourier Transform Programs at http://ferret.pmel.noaa.gov/FERRET_17sep07/Documentation/FFTpack_notes/FFTPACK_notes.html 


Appendix A Sec23.  FFT_RE 

FFT_RE(A) computes the real part of Fast Fourier Transform of time series in variable A 


Arguments: 

Variable with a regular time axis; may be a function of x, y, and/or z 

Result Axes: 

Inherited from A     

 

Inherited from A 

 

Inherited from A 

 

Generated by the function: frequency in cyc/(time units from A) 

The  units of the returned time axis are "cycles/Dt"  where Dt is the time increment. 

Even and odd N's are allowed. N need not be a power of 2. FFT_RE and FFT_IM assume f(1)=f(N+1), and the user gives the routines the first N pts. 

Specifying the context of the input variable explicitly e.g. 

LIST FFT_RE(A[l=1:58]) 

will prevent any confusion about the region. See the note in chapter 3 (p. 77)on the context of variables passed to functions. 

The code is based on the FFT  routines in  Swarztrauber's FFTPACK available at www.netlib.org. See the section on FFTA for more discussion  (p. 86). For further discussion of the FFTPACK code, please see the document, Notes on FFTPACK - A Package of Fast Fourier Transform Programs at http://ferret.pmel.noaa.gov/FERRET_17sep07/Documentation/FFTpack_notes/FFTPACK_notes.html 


Appendix A Sec24.  FFT_INVERSE 

FFT_INVERSE(AR, AI) computes the inverse Fast Fourier Transform of the two frequency series AR and AI 

Arguments: 

AR 

Real part of an FFT transform. Variable with a frequency axis; may be a function of x, y, and/or z 

 

AI 

Imaginary part of an FFT transform. Variable with a frequency axis; may be a function of x, y, and/or z 

Result Axes: 

Inherited from AR, AI     

 

Inherited from AR, AI 

 

Inherited from AR, AI 

 

Abstract axis: 2*length of input frequency axes of AR and AI 

The returned time axis is abstract; the user will need to regrid it to the appropriate time axis. 

The code is based on the FFT  routines in  Swarztrauber's FFTPACK available at www.netlib.org. See the section on FFTA for more discussion (p. 86).  For further discussion of the FFTPACK code, please see the document, Notes on FFTPACK - A Package of Fast Fourier Transform Programs at http://ferret.pmel.noaa.gov/FERRET_17sep07/Documentation/FFTpack_notes/FFTPACK_notes.html 


Appendix A Sec25.  IS_ELEMENT_OF 

IS_ELEMENT_OF(A, B) returns 1 if any element of B matches any element of A, and 0 if there is no match 

Arguments: 

Numeric variable to search 

 

Numeric variableto match 

Result Axes: 

Abstract, 1 element long 

 

Normal 

 

Normal 

 

Normal 

Example: 

yes? list/nohead IS_ELEMENT_OF ({44,55,66}, {55}) 1.00 



Appendix A Sec26.  IS_ELEMENT_OF_STR 

IS_ELEMENT_OF_STR(A, B) returns 1 if any element of string variable B matches any element of string variable A, and 0 if there is no match. The comparisons are case-sensitive. 

Arguments: 

String variable to search 

 

String variable to match 

Result Axes: 

Abstract, 1 element long 

 

Normal 

 

Normal 

 

Normal 

Example: 

yes? list/nohead IS_ELEMENT_OF_STR ({"HELLO", "hello", "Friend"}, {"Friend", "bye"})
1.00
yes? list/nohead IS_ELEMENT_OF_STR ({"HELLO", "hello", "Friend"}, {"friend", "heLLo"})
0.00 



Appendix A Sec27.  LANCZOS 

LANCZOS(A, F1, F2, N )  Returns the argument, bandpass-filtered in time using a Lanczos filter. 

Arguments: 

Variable with a regular time axis; may be a function of x, y, and/or z 

 

F1 

Low frequency cutoff 

 

F2 

High frequency cutoff 

 

Number of weights (must be odd) 

Result Axes: 

Inherited from A 

 

Inherited from A 

 

Inherited from A 

 

Inherited from A 

For details see:  Duchon, C. E., 1979: Lanczos filtering in one and two dimensions. J. of App. Met., 18, 1016-1022. This function is based on code written by Bill Gustafson at UC Davis. 

Example: apply filter to series after removing its mean. 

yes? use monthly_navy_winds
yes? let aa = uwnd[i=50,j=20]
yes? let az = aa - aa[t=@ave]
yes? plot az
yes? plot/over lanczos(az, 0.05, 0.1, 11)
yes? plot/over lanczos(az, 0.1, 0.2, 11) 



Appendix A Sec28.  LSL_LOWPASS 

LSL_LOWPASS(A, cutoff_period, filter_span)  Returns the argument filtered with Least Squares Lanzcos filter in time. 

Arguments: 

Variable with a regular time axis; may be a function of x, y, and/or z 

 

cutoff_period 

Cutoff period (the period at which the filter attains 1/2 amplitude) 

 

filter_span 

number of input data points used in each filtered output point. 

Result Axes: 

Inherited from A 

 

Inherited from A 

 

Inherited from A 

 

Inherited from A 

This function low-pass filters an equally spaced time series using least-squares approximation to the ideal low-pass filter of Bloomfield with Lanczos convergence factors. It is very similar to subroutine LOPASS in Chapter 6, p. 149, of Bloomfield, P., 1976, Fourier Analysis of Time Series: An Introduction, John Wiley & Sons, New York, 258 pp. 

The main difference is that the present routine takes account of missing values in the input time series  Values near the ends and near gaps are filled with the missing value flag. 

The cutoff period is the period at which the filter attains ½ amplitude or 1/4 "energy",  measured in units of delta T. The cutoff_period must be less than or equal to N, the length of the time axis. 

The filter span is the number of input data points used in each filtered output point. A wide filter gives a narrow frequency response transition band, but leads to ringing near data discontinuities and loss of filtered values at the end points and surrounding missing values. A narrow  filter reduces ringing and output data loss, but gives a wider frequency transition width, i.e. it falls off less rapidly at frequencies higher than the cutoff. The filter transition region lies in the period range  between N*cutoff_period/(N + cutoff_period) and N*cutoff_period/(N - cutoff_period). The filter span should be an odd integer. It is set to the next lower odd number if the input is even. 

Note on tidal filtering:  For hourly time series containing tidal signals, some investigators use this filter with a 35-hour cutoff period and a filter span of xxx hours to remove at least 99.5 % of the energy for periods less than 25 hours. 

Adapted from Bloomfield by E. D. Cokelet, NOAA/PMEL, 3 Dec 1999 


Appendix A Sec29.  MINUTES24 

MINUTES24(formatted time)    Scalar function: converts a formatted time of day into  minutes since 00:00, with fractions of minutes. 

Argument: 

formatted time 

hours, minutes, seconds in the form
hh:mm:ss, in quotes. 

     

Result Axes: 

NORMAL (no axis) 

 

NORMAL (no axis) 

 

NORMAL (no axis) 

 

NORMAL (no axis) 

Examples: 

yes? list minutes24("12:24:13")
            VARIABLE : MINUTES24("12:24:13")
         744.2
yes? list minutes24("00:30:30")
            VARIABLE : MINUTES24("00:30:30")
         30.50 



Appendix A Sec30.  WRITEV5D 

WRITEV5D(V1,V2,V3,V4,V5,V6,V7,V8,FILENAME)    Write up to 8 variables to a Vis5D-formatted file 

Arguments: 

V1 

 
 

V2 

 
 

V3 

Up to 8 variables to write to the file 

 

V4 

 
 

V5 

 
 

V6 

 
 

V7 

 
 

V8 

 
 

FILENAME 

Name of the file to write: file type for Vis5d files is .v5d 

Result Axes: 

Inherited from variables: all variables must have the same x and y axes 

 

Inherited from variables: all variables must have the same x and y axes 

 

Inherited from variables; the result grid will contain the union of all the levels that are present in the variables. 

 

Inherited from variables: all variables must have the same time axis 

This function calls utility functions from the Vis5D distribution to write a Vis5D-formatted file containing Ferret variables. TheVis5D tool is a system for interactive visualization of large 5-D gridded data sets. It was developed by Bill Hibbard and others at the University of Wisconsin, and can be found at 

 http://www.ssec.wisc.edu/~billh/vis5d.html 

There are limits in Vis5D on the size of the grid and the number of timesteps. The function will issue an error if these limits are exceeded. 

To make it more convenient to call the writev5d function, to open Vis5D from Ferret, and to append to a Vis5D file, GO tools are available: vis5d_write.jnl, vis5d_start.jnl, and vis5d_append.jnl. These have the filename first in their argument lists, and do not require the user to specify all 9 arguments to the function. 

Example: 

Write 3 variables to a file, then append timesteps to some of the variables. There is a gap between the times first written to the file and the times written when we call vis5d_append; this will show up in the Vis5d tool as a gap in time. Last, start Vis5d and open the file. 

Yes? SET REGION/I=55:180/J=30:60
yes? GO vis5d_write myfile.v5d sst[L=20:30], airt[L=20:30], fcn_1     
yes? GO vis5d_append myfile.v5d sst[l=34,50], airt[l=34,50]
yes? GO vis5d_start myfile.v5d