Basics |
For example, if x is an NCL variable, then the lines:
x@min = -50 x@max = 50. x@units = "meters" x@long_name = "A variable for temporary storage" x@eigenvalues = (/ 0.75, 0.40, 0.01 /)would create the attributes min, max, units, long_name, and eigenvalues. In the above, notice that NCL arrays are initialized by bracketing the data with the array designator characters "(/" and "/)".
Attributes have types, so, using the attributes created above, the lines:
xmini = x@min xmaxr = x@max info = x@long_name eigval = x@eigenvalueswould create an NCL variable xmini of type integer, an NCL variable xmaxr of type float, an NCL variable info of type string, and a singly-dimensioned float array eigval.
The attribute "_FillValue" is special in NCL and, if defined, denotes the value that, when stored in a variable, will be considered as a missing value. An array may have several occurrences of the missing value in it. These missing values are subsequently ignored by the plotting functions and by many of the computational functions.
The NCL function isatt can be used to query whether a given string is an attribute name for a variable.
An array dimension can be assigned a name. This can be done by entering an array name followed by the "!" character followed by an integer dimension number and setting that equal to a name (string value). For example, if the variable pressure has three dimensions, then the statements:
pressure!0 = "time" pressure!1 = "latitude" pressure!2 = "longitude"would assign the name "time" to the first dimension of pressure, "latitude" to the second dimension, and "longitude" to the third. These dimension names can be used in "named subscripting," discussed in the "Array subscripting" section below. Named dimensions are also used to define coordinate variables as discussed immediately below.
The NCL function isdim can be used to query if a given string is the name of a named dimension of a variable.
You can define a coordinate variable for any named dimension of an array, and only for a named dimension. Suppose, for example, that pressure is a 9x7 array and consider the statements:
pressure!0 = "lat" pressure!1 = "lon" lat_points = (/-80, -60, -40, -20, 0, 20, 40, 60, 80/) lon_points = (/-180, -120, -60, 0, 60, 120, 180/) pressure&lat = lat_points pressure&lon = lon_pointsThe first two statements name the first two dimensions of pressure, the next two statements define coordinate arrays, and the final two statements define the coordinate variables lat and lon and associate them with the coordinate arrays lat_points and lon_points respectively.
The coordinate array associated with a coordinate variable must have the same size as the named dimension with which the coordinate variable is associated. Also, a coordinate variable must have the same name as its corresponding named dimension. The elements in a coordinate array must be monotonically increasing or decreasing. Any of the numeric data types may be used for values in the coordinate arrays associated with a coordinate variable.
The use of coordinate variables for subscripting of arrays is described below in the "Array subscripting" section.
The NCL function iscoord can be used to query if a specified string is a coordinate variable of a variable.
NCL's array subscripting syntax contributes significantly to NCL's data processing power and versatility. There are three types of subscripting:
The most general form of a standard subscript is m:n:i which indicates the range m to n in strides of i.
Consider the array v defined by
v = (/0,1,2,3,4,5,6,7,8,9/)then the following NCL statements illustrate the many possibilities for standard subscripts (semi-colons on an NCL statement initiate comments that are ignored by the NCL interpreter):
v1 = v(1:7) ; v1 contains 1,2,3,4,5,6,7 . v2 = v(1:7:3) ; v2 is an array containing the ; elements 1,4,7 . v3 = v(:4) ; v3 contains 0,1,2,3,4 (a missing ; initial integer indicates ; the beginning of the indices). v4 = v(8:) ; v4 contains 8,9 (a missing second ; index indicates the largest ; of the indices). v5 = v(:) ; v5 equals v (this is the same as ; setting v5 = v). v6 = v(2:4:-1) ; v6 contains 4,3,2 (in that order). ; The algorithm is to find all ; numbers within the range of ; the first colon-separated ; pair, then step in reverse ; when the stride is negative. v7 = v(6) ; v7 is a scalar with value 6 . v8 = v(5:3) ; v8 contains 5,4,3 in that order ; (when the starting index is ; greater than the ending index, ; a reverse selection is done). v9 = v(::-1) ; v9 contains 9,8,...,0 in that order.
The 1-dimensional case carries over to arrays with multiple dimensions, so that if w were a 5x7x11 array, the statement
w1 = w(0:4:2, :3, :)would define w1 as a 3x4x11 array constructed in each dimension as in the linear array example above.
pressure_rev = pressure (lon | :, lat | 4:5)would define pressure_rev as an array with first dimension named lon of size 37 and second dimension named lat of size 2. The syntax requires the vertical bars be present as well as a specified subscript range.
For example, where
w = (/0,1,2,3,4,5,6/) ; create data array w!0 = "w_dim0" ; name the dimension w&w_dim0 = (/.0, .1, .2, .3, .4, .5, .6/) ; associate array ws = w( {.1 : .5 : 2} ) ; use coord. subscriptingws would be a 1-dimensional integer array of size 3 with values 1,3,5. Note that the stride must always be an integer and should be thought of as a skip indicator rather than an additive increment value, since coordinate subscripts may not always be integers, as illustrated here. A stride of 2 means to take every second value after the first, a stride of 3 means take every third value, and so forth.
NCL provides a default color map that contains 32 different colors. If you want to define your own color map, then you can do it one of several ways:
To use one of the other eight predefined color maps, select one from the "Color tables" section of the NCAR Graphics Reference Manual, and set the resource wkColorMap to this name. For example, if you want to use the "temp1" color map, you can make this color map active by including the following setvalues statement:
setvalues wks "wkColorMap" : "temp1" end setvaluesafter a workstation is opened (either from a call to gsn_open_wks or by using create to create a workstation).
wks = gsn_open_wks("x11","example") cmap = (/(/1.00, 1.00, 1.00/), (/0.00, 0.00, 0.00/), \ (/.560, .500, .700/), (/.300, .300, .700/), \ (/.100, .100, .700/), (/.000, .100, .700/), \ (/.000, .300, .700/), (/.000, .500, .500/), \ (/.000, .700, .100/), (/.060, .680, .000/), \ (/.550, .550, .000/), (/.570, .420, .000/), \ (/.700, .285, .000/), (/.700, .180, .000/), \ (/.870, .050, .000/), (/1.00, .000, .000/)/)then you can make this new color map active with either of these segments of code:
gsn_define_colormap(wks,cmap)or
setvalues wks "wkColorMap" : cmap end setvaluesTo help determine what RGB values to use to get the colors you want, below are five color tables with sample RGB values. Each table has a fixed intensity value for red, and shows the colors for varying intensity values of blue and green:
Table 1 | Table 2 | Table 3 | Table 4 | Table 5 |
---|---|---|---|---|
(Click on any table to see it enlarged.) |
Note: To create a grayscale color map, use RGB values that are equal in intensity. For example, (0.11, 0.11, 0.11), (0.5, 0.5, 0.5), and (0.968, 0.968, 0.968) are all RGB values that produce varying shades of gray.
(Note that some of the colors are duplicates, like "grey1" and "gray1".)
For example, if you want to use the same color map in the example above, but you also want to add the named colors "CadetBlue", "Ivory", "LimeGreen", and "DarkSalmon", then your code would look something like the following:
wks = gsn_open_wks("x11","example") cmap = (/"(/1.00, 1.00, 1.00/)", "(/0.00, 0.00, 0.00/)", \ "(/.560, .500, .700/)", "(/.300, .300, .700/)", \ "(/.100, .100, .700/)", "(/.000, .100, .700/)", \ "(/.000, .300, .700/)", "(/.000, .500, .500/)", \ "(/.000, .700, .100/)", "(/.060, .680, .000/)", \ "(/.550, .550, .000/)", "(/.570, .420, .000/)", \ "(/.700, .285, .000/)", "(/.700, .180, .000/)", \ "(/.870, .050, .000/)", "(/1.00, .000, .000/)", \ "CadetBlue", "Ivory", "LimeGreen", "DarkSalmon"/)You can then make this new color map active with either of these segments of code:
gsn_define_colormap(wks,cmap)or
setvalues wks "wkColorMap" : cmap end setvalues
The hsv2rgb function takes three 1-dimensional arrays (H, S, and V) of the same size (n) and returns an n x 3 array of RGB values that can be passed directly to gsn_define_colormap or assigned to the wkColorMap resource. The variable H represents the hue and must be in the range [0.,360.]. S represents the saturation (percentage of white) and must be in the range [0.,1.0]. V represents the value (brightness or intensity) and must be in the range [0.,1.].
Below are three sample color wheels (with HSV values included) to help you select values to use in the hsv2rgb function. Each wheel has a fixed value for V, and shows the colors at varying degrees of H for three different fixed values for S:
Wheel 1 | Wheel 2 | Wheel 3 |
---|---|---|
(Click on any "wheel" to see it enlarged.) |
For example, let's assume you want a color map with 18 entries: a white background, a black foreground, and the rest of the 16 colors ranging from blue to red (no green). Let's further assume you want to use a fixed intensity value of 1.0 and a fixed saturation of 0.67. Then your NCL code might look like the following:
load "gsn_code.ncl" load "hsv2rgb.ncl" begin wks = gsn_open_wks("x11","example") hue = fspan(225.,360.,16) ; Set hue to range from 225 to 360. sat = fspan(0.67,0.67,16) ; Fix saturation at 0.67. val = fspan(1.,1.,16) ; Fix value at 1.0. cmap = new((/18,3/),float) ; Define an 18 x 3 float array. cmap(0,:) = (/1.,1.,1./) ; Set the background to white. cmap(1,:) = (/0.,0.,0./) ; Set the foreground to black. cmap(2:17,:) = hsv2rgb(hue,sat,val) ; Generate smooth range of RGB values. gsn_define_colormap(wks,cmap) . . . endThe above code snippet produces a color table that looks like this:
(Click on image to see it enlarged.)
To see the full code that generated the above labelbar, see "lblbar.ncl".
. . . wks = gsn_open_wks("x11","example") . . . cmap = gsn_retrieve_color_map(wks) . . .or the getvalues statement:
. . . wks = gsn_open_wks("x11","example") . . . getvalues wks "wkColorMap" : cmap end getvalues . . .where wks is the id of the workstation. In either case, cmap will be an n x 3 float array of RGB values, where n is the number of colors in the color map.
Do loops in NCL are costly, so if possible, use NCL's Fortran 90 array syntax to avoid them. For example, if you have the following do loop:
x = new(100001,float) do i = 0,100000 x(i) = i*0.1 end doit would be more efficient to rewrite it as:
x = ispan(0,100000,1)*0.1
If it is impossible for you to rewrite your do loop, then you may want to consider writing a wrapper function (see the section "Incorporating your own Fortran or C code" in the "Going beyond the basics" chapter of this document).
If you open a file with addfile and plan to access a particular variable in it several times, then it is a good idea to save this file variable to a local NCL variable and use the local variable instead. This is because every time you reference a file variable, the file is reopened and then closed again.
As noted above, if you plan to use a file variable repeatedly, you should save it to a local NCL variable. This is especially true if you are reordering the dimensions every time you access the file variable. Saving a file variable to a local NCL variable will require more memory, but this is often preferable to the repeated opening and closing of a file.
If you are setting lots of resources, then it may be better to put them all in a separate resource file rather than setting them directly in the NCL script. This is especially true if you are setting a particular resource to the same value for multiple plots, because a resource file only gets loaded once, whereas if you set the resource multiple times in an NCL script, it will get loaded every time.
If you are writing large netCDF files (e.g. GRiB to netCDF), you can get the code to run faster by using filedimdef, fileattdef, filevarattdef, and filevardef to define your variables, dimensions, and attributes ahead of time.
If you are assigning one variable to another, and it contains lots of metadata (attributes, dimension names, and coordinate variables), then your code may run faster if you enclose the variable on the right side of the assignment statement with "(/" and "/)" so that the metadata isn't copied. You should only do this if you don't need the metadata!
For example, if you have the assignment statement:
sst2 = sst(0,:,:)your script may run faster if you rewrite this as:
sst2 = (/sst(0,:,:)/)
If you are reading Fortran records with fbinrecread, it may be slow if you have a lot of records. A better thing to do is to write your own wrapper for reading in files (see the section "Incorporating your own Fortran or C code" in the "Going beyond the basics" chapter of this document).
If you are creating a series of images to form an animation sequence, and the only thing you are changing from plot to plot is the data, then it is more efficient to call the GSUN plotting function only once for the initial plot, and then use setvalues and draw to change the data for the subsequent plots and redraw them. See example 9 for more information on how to do this.