NCL Website header
NCL Home > Documentation > Manuals > Reference

NCL Language Reference Guide: Variables

Properties of variables

Variable names must begin with an alphabetic character, but they can contain any mix of numeric and alphabetic characters. The one exception to this rule is that the underscore ('_') is also allowed. Variable names are case sensitive. The maximum variable name length is currently 256 characters. Variables can reference arrays of multi-dimensional data. These data can be described by variable attributes, named dimensions, and coordinate variables. Variables can also reference files and graphical objects.

The following are examples of unique variable names:

    a
    A
    forecast_time
    s092389
    __t__
    
Variables, like in other programming languages, are textual names that reference data. In NCL, somewhat like Fortran, variables can be created without previously defining them. This is call-implicit instantiation. Unlike Fortran though, the type of a variable is based on what type of value is assigned to it, not the name. Unlike other languages, variables in NCL can be deleted, or changed from defined to undefined.

NCL has been designed with special features that allow ancillary information to be "attached" to a variable programmatically. NCL provides a unique syntax for storing and retrieving these ancillary data values. These ancillary data are divided up into three categories: variable attributes, dimensions, and coordinates. Variables can have an unlimited number of attributes assigned to them. Each dimension of a variable can have a name associated with it and optionally a coordinate variable. Variables become defined when an undefined name appears on the left side of an assignment statement.

There are three types of variables referenced in this document. The first and most obvious is the term variable which is defined as a textual reference to a multi-dimensional or scalar value. Second, there is the term variable that references a file, which is defined as a variable that is assigned the return value of the addfile function. These variables provide references to open files. Finally, the term file variable is defined to be a variable in a file that references a multi-dimensional data value. These terms will be used throughout this section of the reference guide to distinguish between different kinds of variables.

Attributes

Attributes are descriptive pieces of information that can be associated with an already existing variable, or file variable. They are very useful for communicating information to the user about specific data. Attributes can be assigned single-dimensioned arrays, but not files. Variable attributes are referenced by entering the variable name, followed by '@', followed by the name to be used to reference the attribute. If the attribute is not defined, then an error message is displayed. An attribute is created by referencing it on the left side of an assignment statement and assigning a value to it. The following are examples of creating the attributes units, long_name, and _FillValue in the variable named temperature:
    temperature@units = "Degrees C"
    temperature@long_name = "Temperature at Tropopause"
    temperature@_FillValue = -9999.0
    

Attributes can be used in expressions and subscripted in the same fashion as variables. Common uses of attributes are to store the units that data are stored in, and to store names and text that could be useful.

Missing values

The attribute _FillValue is a special reserved attribute name that denotes what values stored in a variable should be considered missing values. Whenever the _FillValue attribute is assigned a new value, every occurrence of the previous value in the variable temperature, in the above example, is replaced with the new _FillValue. The _FillValue attribute must be the same type as the data type referenced by the variable. The procedure delete is used to remove the missing value attribute. Once removed, all of the previous elements of the variable that were treated as missing values are treated as normal values.

The _FillValue attribute has many important uses in NCL. First and most important is how missing values are handled in expressions. When missing values appear in terms of an NCL expression, they are ignored for the specific element that contains the missing value. Consider the following example:

    a = (/27.2, -10.0/)
    a@_FillValue = -10.0
    b = a * 9.0/5.0 + 32.0
    print(b)
    
    Variable: b
    Type: float
    Total Size: 8 bytes
                2 values
    Number of Dimensions: 1
    Dimensions and sizes:   [2]
    Coordinates: 
    Number Of Attributes: 1
      _FillValue :  -10
    (0)     80.96
    (1)     -10
    
In this example, the constant array (/ 27.2, -10.0/) is assigned to the variable a. Next the value of -10.0 is assigned as the _FillValue attribute. When the expression is evaluated, the element equal to -10.0 in the array is ignored, and the result is the array referenced by b which has -10.0 as its _FillValue. See Expressions and missing values for more discussion.

The default missing values have changed in version 6.0.0. The older missing values too often fell into the range of normal calculations and led occasionally to occurrences of accidental equivalences of data or the results of calculations with the missing value. The resulting errors can be mysterious and hard to debug. Here is a table with the new default missing values along with the former values for comparison.

TypeDefault _FillValuePre-6.0.0 default _FillValue
double9.969209968386869e+36-9999.0
int64-9223372036854775806-999999
uint64184467440737095516140
float9.96921e+36-999.0
long-2147483647-9999
ulong42949672950
integer-2147483647-999
uint42949672950
short-32767-99
ushort655350
byte (*)-1270xff
ubyte2550
logicalMissing (assigned as _Missing)Missing (assigned as _Missing)
string"missing""missing"
character0x000x00
graphic-1-1
file-1-1
list-1-1

For users who are unable to adapt to the version 6.0.0 _FillValue defaults immediately, there is a new NCL command line option, '-o', that sets the defaults to their previous values. Alternatively, you can use the function set_default_fillvalue to set the default fill value for individual types, to set all fill values to the pre-6.0.0 values, or to restore the current default values. The function default_fillvalue returns the current default fill value for any specific type.

When a variable is converted from one type to another, either through automatic coercion or through the use of a conversion function, the _FillValue attribute value is converted as well. If the "from" type fill value is within the range of the "to" type, it is converted the same way as the rest of the data. If it is not within the "to" type range, it will be changed to the default fill value of the "to" type. In this case, all data elements that have the value of the old fill value will also be changed. See Coercion of types for futher details.

Dimensions

Dimensions define the shape and size of the data referenced by variables. In NCL, dimensions are ordered using row x column ordering, which is identical to the C programming language. By convention, dimensions are numbered from 0 to n-1 where n is the number of dimensions of the data referenced. The dimension numbers are significant because NCL allows names to be associated with dimensions. This in turn facilitates coordinate subscripting and named subscripting. A variable dimension is referenced by entering the variable name, followed by the '!' character, followed by the dimension number being referenced. If the dimension has been assigned a name, then this reference returns the name. To assign or change a name to a dimension, simply assign a string to the dimension number in the following fashion:
    temperature!0 = "frtime"
    temperature!1 = "lat"
    temperature!2 = "lon"
    
The previous example is valid only if temperature has three or more dimensions.

Coordinate variables

Coordinate variables are single-dimension arrays that have the same name and size as the dimension they are assigned to. These arrays represent the data coordinates for each index in the named dimension. When the values in these arrays are monotonically increasing or decreasing, they can be used in coordinate subscripting. If they are not monotonic or contain missing values, then coordinate subscripting will not work. The '&' operator is used to reference and assign coordinate variables. In order to assign a coordinate variable to a dimension, the dimension must have a name. These examples show assignment of variables to coordinate variables:
    temperature&frtime = forecast_times
    temperature&lat = lat_points
    temperature&lon = lon_points
    

String references

Sometimes it is impossible to know the names of the attributes and coordinates before writing a script, or these names may vary from variable to variable. To solve this problem, string variables can be used to reference attributes and coordinates by enclosing the variable reference within dollar signs '$'. The following are examples of this:
    	dimnames = (/"frtime","lat","lon"/)
    	attnames = (/"_FillValue", "long_name"/)
    
    ;
    ; access to attribute
    ;	
    	att0 = temperature@$attnames(0)$
    
    ;
    ; Example of referencing a coordinate variable 
    ; without knowing the dimension name
    ;
    	if(iscoord(dimnames(0)) 
    		coord0 = temperature&$temperature!0$
    	end if
    
    

Variables used as parameters to functions and procedures

When functions and procedures are called, in NCL, the parameter passing mechanism is called pass-by-reference. This means, just like FORTRAN, that changes made within a function or procedure to a parameter are also applied to the variable in the calling environment. With NCL, however, there are some differences which must be considered when passing variables as parameters. In NCL changes to named dimensions, coordinate variables and attributes also affect the variable in the calling environment. Furthermore, if the variable is subscripted prior to calling a function or procedure the values are remapped back into the original variable once the function or procedure is terminated.

In the following example the variable a is subscripted note how the assignments in the procedure set are propagated back to the calling environment:

	procedure set(x)
	begin
		x = 1
		x!0 = "dim1"
		x@_FillValue = 1
	end

	a = (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/)

	set(a(1,:))

	print(a)
It is important to consider this functionality whenever writing an NCL function or procedure that makes any kind of assignments to the input parameters.

Subscripts

There are three types of subscripting in NCL. Standard is similar to the array subscripting available in Fortran 90. One very important item to note is that NCL dimension indexes start at 0 and end at n-1. Second, coordinate subscripting uses the data in the coordinate variables for determining subsections of the array to select. Third, named subscripting uses the names of the dimensions to allow for array reordering operations. All three types of subscripting can be used in a single variable selection.

Standard subscripts

Standard subscripting provides the capability of selecting ranges and strides in addition to the ability to select data using a vector of integer indexes. All of this functionality is more or less duplicated from Fortran 90. The following is a simple example of a set of single subscripts for a three-dimensional variable with dimensions 5x6x7. Unlike Fortran, the array indexes begin at 0. Standard subscript indexes must always be integer; floating point numbers and strings are not accepted.

Note: Individual subscripts are separated by commas ',' and the entire subscript list is enclosed in parentheses.

    temperature(0,5,6)
    
A range subscript selection accepts a beginning and ending index separated by a colon ':'. Both the beginning index and the ending index are included in the selection, therefore the range is inclusive. Furthermore, if the start is greater than the end, then the selection reverses the ordering of the array. Some examples are:
    temperature(1:3,5,6)
    temperature(1:3,4:5,5:6)
    
The first selection selects a 3x1x1 subsection of the array temperature, and the second selection selects a 3x2x2 subsection. In addition to the above style of selection, a stride can also be specified that causes the selection to skip over a given number of elements. For example, a value of 1 means that every element from the beginning of the range and the end of the range will be selected. With values greater than 1, the first index of the subscript is followed by the stride plus the current index. Therefore a value of 3 selects the first, fourth, seventh, and so on.
    temperature(0:4:2,0:5:3,0:6:4)
    
The above selection uses strides to produce a 3x2x2 array.

There is no restriction on having the start of a subscript range be less than the end of the subscript range. When the start is greater than the end, a reverse selection is done, meaning the order output selection is reversed from the original variable. For example:

    temperature(3:1,5,6)
    temperature(3:1,4:5,5:6)
    

Another option for selection is to leave out the start, end, or both. This means that the start or end will default to the beginning or end respectively.

    temperature(:2,:1,5:)
    temperature(:,:,:)
    
The first selection selects from the beginning to index 2 for the first dimension, the beginning to index 1 for the second dimension, and the final subscript selects from index 5 to the end for the 3rd dimension. The second example shows how the entire array can be selected.

The following uses the default range to reverse the ordering of each dimension using a negative stride:

    temperature(:2:-1,:1:-1,5::-1)
    temperature(::-1,::-1,::-1)
    

Finally, a vector of integer indexes can be used as a subscript. As long as all of the entries in the vector are within the bounds of the given dimension, the vector could be any size. Vector subscripting allows a single index to be selected more than once. For example, consider the following array and its use of vector subscripting on the variable temperature:

    (/1,1,1,2,2,2/)
    temperature((/1,1,1,2,2,2,/),:,:)
    
This selection creates an array 6x6x7 which is actually bigger than the original. The first, second, and third indexes of the first dimension contain identical arrays. The vector must always be a single-dimensioned array of integers.

Coordinate subscripts

Coordinate subscripts use the coordinate variables associated with a variable to determine which indexes are used in the selection. When specifying a coordinate subscript, braces '{' and '}' indicate the start and end values of the coordinate variable that will be used to select the indexes. Essentially, the start and end values are "looked" up in the coordinate variable, and the indexes are used to make the subselection. The following are examples of coordinate subscripts. Note that coordinate and standard subscripting can be mixed in the same variable subscript. Also, stride is still specified as an integer stride. If the coordinate values used in the subscript do not exactly match values in the coordinate variable, all coordinate values that fall within the coordinate subscript range are selected. If the values do match, then they are selected in an inclusive fashion.
    temperature(0,{20:60},{-95:-120})
    temperature(0,{20},{-95})
    temperature(0,{:20:2},{:-95:2})
    

Coordinate subscripting only works when the coordinate variables assigned to the variables are monotonically increasing or decreasing. If an attempt is made to subscript a coordinate variable that is not monotonic, an error message is generated.

Named subscripting

Named subscripting is a means by which arrays can be reordered. Named subscripting requires that each dimension of the variable being subscripted is named. If one or more are not named, an error messages is printed. The following are examples of named subscripting. The dimension names of the variable temperature are "time", "lat", and "lon" for dimensions 0 through 2 respectively.
    temperature( time | 0, lon | :, lat | :)
    temperature( time | :, {lon | 20 : 60}, {lat | -95 : -120})
    

The first example "swaps" the lat and lon dimensions. The second example shows a similar dimension reordering but utilizes coordinate subscripting.

Using string reference with named subscripting

It is not necessary to "hard-code" the names of dimensions when using named subscripting. Alternatively, dollar signs '$' can be placed around a string variable. This causes NCL to use the variable's string value as the dimension name. The following shows how an array can be reordered without knowing the names of the dimensions:
    dims = getfilevardims(file1,"T")
    T = file1->T( $dims(1)$ | :,  $dims(0)$ | :, $dims(2)$ | :)
    
Note: it can be time-consuming to reorder dimensions when reading a variable off a file. If you can spare the extra memory, it is better to read the variable into memory, and then reorder the dimensions:
    dims = getfilevardims(file1,"T")
    T    = file1->T
    Tnew = T( $dims(1)$ | :,  $dims(0)$ | :, $dims(2)$ | :)
    

Variable assignment

It is important to understand what happens when a variable is used in an assignment statement in NCL. The assignment statement functions differently depending on whether the variable being assigned to is currently undefined or defined. The assignment statement also functions differently depending on whether a variable or a value occupies the right side of the assignment.

When a variable appearing on the left side of an assignment has not be defined or was previously deleted, the assignment statement causes the variable to become defined and the data type and dimensionality of the variable is determined by the right side.

When a variable appearing on the left side is already defined, then the right side must have the same type, or be coercible to the type on the left, and the right side must have the same dimensionality.

Value-only assignment

Value-only assignments to variables are fairly straightforward. In essence, value-only assignments mean that the right side of the assignment is not a variable, it is the result of an expression, a value. In this case, if the left side variable reference was not defined prior to the assignment statement, the variable on the left side becomes defined and references the value of the right side. No dimension names, coordinate variables or attributes other than _FillValue are assigned. If the right side of the expression does not contain any missing values, then _FillValue is not assigned either.

If the left side variable was defined prior to the assignment statement, then the value on the left side is assigned the value of the right side. If the left side is a subscripted reference to a variable, then the right side elements are mapped to the appropriate location in the left side variable. If the left side has any attributes, dimension names, or coordinate variables, they are left unchanged since only a value is being assigned to the left side variable. When the left side is defined, then the type of the right side and the dimensionality must match. However, there is one exception to the requirement that the dimension sizes of the left side and the right side match, a single scalar value can be assigned to more than one location. Consider the following example:

    a = (/1,2,3,4,5,6,7,8,9,10/)
    a(0:3) = -1
    print(a)
    
    Variable: a
    Type: integer
    Total Size: 40 bytes
                10 values
    Number of Dimensions: 1
    Dimensions and sizes:   [10]
    Coordinates: 
    (0)     -1
    (1)     -1
    (2)     -1
    (3)     -1
    (4)     5
    (5)     6
    (6)     7
    (7)     8
    (8)     9
    (9)     10
    
This example demonstrates the value of -1 being assigned to the first four elements of the variable a.

Variable-to-variable assignments

During variable-to-variable assignment attributes, coordinate variables and dimension names, in addition to actual multi-dimensional values, are assigned. Before discussing this type of assignment, it is important to note that the array designator characters '(/' and '/)' can be used when assigning one variable to another to force only the right side's value to be assigned to the left side and the right side's attributes, dimensions, and coordinates are ignored. Essentially using the array designator characters forces value-to-variables assignment. The following shows how the array designator characters can be used to do this:
    ;
    ; Example of array designator use to force "Value Only" assignment
    ;
    	variable1 = (/ variable2 /)
    

Variable-to-variable assignment occurs when both the left side and the right side are variables. In this situation, the assignment statement also tries to assign attributes, dimension names, and coordinates of the right side to the left side.

The two simplest cases are:

  • The left side is undefined prior to the assignment
  • The variable on the left side is not subscripted, meaning the entire variable is being referenced

In both these situations, all of the right side's attributes, coordinates, and dimension names are assigned to the left side. If the left side has the same dimension and coordinate names, then only the coordinate variable is overwritten with the value and attributes of the right side's coordinate variables. However, if the names of the dimension names do not match, a warning message is generated and the names and coordinate variables of the left side are overwritten. As far as attributes go, if the left side has attributes, then the left side's attribute list is merged with that of the right side. If the same attribute name appears on both the left and right sides, the right side's attribute overwrites the left side's. If the types of the attribute values do not match, you could have a type mismatch error.

The following are examples of some variable-to-variable assignment situations:

This first example shows assignment to an undefined variable and then shows the use of the array designator characters '(/' and '/)' to perform a value-only assignment.

    ;
    ; Create variable be with values, dimension names, coordinate variables 
    ; and attributes
    ;
    	b = (/ (/1.0,2.0,3.0/), (/4.0,5.0,6.0/), (/7.0,8.0,9.0/) /)
    	b!0 = "dim0"
    	b!1 = "dim1"
    	b@units = "none"
    	b&dim0 = (/.1,.2,.3/)
    	b&dim1 = (/10,100,1000/)
    
    ;
    ; Variable-to-variable assignment with left side undefined
    ;
    	a = b
    
    ;
    ; Use of array designator characters to assign "Value Only" to undefined 
    ; left side
    ;
    	c = (/b/)
    
    ;
    ; This print shows that all of the dimension names, attributes, and coordinate 
    ; variables have been assigned to a.
    ;
    	print(a)
    
    	Variable: a
    	Type: float
    	Total Size: 36 bytes
    		     9 values
    	Number of Dimensions: 2
    	Dimensions and sizes:   [dim0 | 3] x [dim1 | 3]
    	Coordinates: 
    		    dim0: [0.1..0.3]
    		    dim1: [10..1000]
    	Number Of Attributes: 1
    	  units :       none
    	(0,0)   1
    	(0,1)   2
    	(0,2)   3
    	(1,0)   4
    	(1,1)   5
    	(1,2)   6
    	(2,0)   7
    	(2,1)   8
    	(2,2)   9
    
    ;
    ; This print shows that only the values of b were assigned to c.
    ;
    	print(c)
    
    	Variable: c
    	Type: float
    	Total Size: 36 bytes
                         9 values
    	Number of Dimensions: 2
    	Dimensions and sizes:   [3] x [3]
    	Coordinates: 
    	(0,0)   1
    	(0,1)   2
    	(0,2)   3
    	(1,0)   4
    	(1,1)   5
    	(1,2)   6
    	(2,0)   7
    	(2,1)   8
    	(2,2)   9
    
    

This second example demonstrates a defined variable being assigned to a defined variable. Note the changes resulting from assignment to the dimension names, attribute values, and coordinate variables in variable a. These assignments that change the left side's coordinates and dimension names generate errors. When left and right dimension names are different, NCL considers this an error that the user should be warned about. To avoid these errors you can either make sure before assignment that the left and right sides have the same dimension names, or if you only want to assign a value and don't care about attributes, dimensions, and coordinate variables, you can enclose the right side using '(/' and '/)', which forces NCL to use only the value of the right side.

    ;
    ; Define variable a with value, dimension names and attributes.
    ; No coordinate variables assigned.
    ;
    	a = (/ (/1.1,1.2,1.3/), (/2.1,2.2,2.3/), (/3.1,3.2,3.3/) /)
    	a!0 = "test0"
    	a!1 = "test1"
    	a@units = "Degrees"
    	a@long_name = "A"
    
    ;
    ; Define variable b with value, dimension names, attributes, and
    : coordinate variables.
    ;
    	b = (/ (/1.0,2.0,3.0/), (/4.0,5.0,6.0/), (/7.0,8.0,9.0/) /)
    	b!0 = "dim0"
    	b!1 = "dim1"
    	b@units = "none"
    	b&dim0 = (/.1,.2,.3/)
    	b&dim1 = (/10,100,1000/)
    
    ;
    ; Here is the "Variable-to-variable" assignment. The dimension names of a
    ; change, and the coordinate variables of b are assigned to a. In addition,
    ; the attribute lists are merged.
    ;
    	a = b
    	print(a)
    
    	Variable: a
    	Type: float
    	Total Size: 36 bytes
                         9 values
    	Number of Dimensions: 2
    	Dimensions and sizes:   [dim0 | 3] x [dim1 | 3]
    	Coordinates: 
    		    dim0: [0.1..0.3]
    		    dim1: [10..1000]
    	Number Of Attributes: 2
    	  units :       none
    	  long_name :   A
    	(0,0)    1
    	(0,1)    2
    	(0,2)    3
    	(1,0)    4
    	(1,1)    5
    	(1,2)    6
    	(2,0)    7
    	(2,1)    8
    	(2,2)    9
    

The remaining case is that when the left side is subscripted, only a portion of the target variable is being assigned to. The simplest case here is when the left-side dimension names are the same and both the left side and right side have coordinate variables for the same dimensions. In this case, assignment occurs for each coordinate variable. The subscripted left-side coordinate variable is assigned the subscripted right side coordinate. The attributes lists for the right side is merged with that of the left side and assigned to the left side variable. The following demonstrates this kind of variable-to-variable assignment.

    ;
    ; Define variable a with values, dimension names, attributes and
    ; coordinate variables.
    ;
    	a = (/ (/1.1,1.2,1.3/), (/2.1,2.2,2.3/), (/3.1,3.2,3.3/) /)
    	a!0 = "dim0"
    	a!1 = "dim1"
    	a&dim0 = (/.1,.2,.3/)
    	a&dim1 = (/.1,.01,.001/)
    	a@units = "Degrees"
    	a@long_name = "A"
    
    ;
    ; Define b with same dimension names, and assign different coordinate
    ; variables for dim1.
    ;
    	b = (/ (/1.0,2.0,3.0/), (/4.0,5.0,6.0/), (/7.0,8.0,9.0/) /)
    	b!0 = "dim0"
    	b!1 = "dim1"
    	b@units = "none"
    	b&dim0 = (/.1,.2,.3/)
    	b&dim1 = (/10.0,100.0,1000.0/)
    
    ;
    ; Here is the example of "Variable to Variable" assignment where the left
    ; side is already defined. The coordinate variable for "dim1" is overwritten.
    ;
    	b(0,:) = a(0,:)
    	print(b)
    
    	Variable: b
    	Type: float
    	Total Size: 36 bytes
                         9 values
    	Number of Dimensions: 2
    	Dimensions and sizes:   [dim0 | 3] x [dim1 | 3]
    	Coordinates: 
    		    dim0: [0.1..0.3]
    	 	    dim1: [0.1..0.001]
    	Number Of Attributes: 2
    	  units :       Degrees
    	  long_name :   A
    	(0,0)   1.1
    	(0,1)   1.2
    	(0,2)   1.3
    	(1,0)   4
    	(1,1)   5
    	(1,2)   6
    	(2,0)   7
    	(2,1)   8
    	(2,2)   9
    
If the left side variable does not have a coordinate variable and the right side does, a coordinate variable is created and assigned. If the left side is subscripted, then the created coordinate variable only has values assigned for the subscripted range, and the rest of the coordinate variable is filled with missing values. The following example illustrates this feature:
    ;
    ; Define b with no coordinate variables.
    ;
    	b = (/ 1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0/)
    	b!0 = "dim0"
    
    ;
    ; Define a with coordinate variables.
    ;
    	a = (/ 1.1,1.2,1.3,2.1,2.2/)
    	a!0 = "dim0"
    	a&dim0 = (/.1,.2,.3,.4,.5/)
    
    ;
    ; Assignment of a to b. Selection of dim0 selects only every other element.
    ;
    	b(::2) = a(:)
    
    ;
    ; Print of the coordinate variable "dim0" demonstrates filling of missing 
    ; value for non-selected element.
    ;
    	print(b&dim0)
    
    
    	Variable: dim0 (coordinate)
    	Type: float
    	Total Size: 36 bytes
                         9 values
    	Number of Dimensions: 1
    	Dimensions and sizes:   [dim0 | 9]
    	Coordinates: 
    	Number Of Attributes: 1
    	  _FillValue :  -999
    	(0)     0.1
    	(1)     -999
    	(2)     0.2
    	(3)     -999
    	(4)     0.3
    	(5)     -999
    	(6)     0.4
    	(7)     -999
    	(8)     0.5
    
The final situation that must be considered when assigning one variable to another is when the dimension names of the left side and the right side do not match. In this case, the assignment overrides the left side's dimension names and coordinate variables, and a warning message is generated. If this is not the desired effect, then the array designator characters '(/' and '/)' can be used to make the assignment a "value-only" assignment.

Variable reassignment

Reassignment is trying to use a variable which has been previously defined (if it is not defined, the the reassignement will be simple assignment). With reassignment, a variable appearing on the left side of a reassignment can be defined or not defined, the reassignment statement causes the variable to become defined (or redefined) and the data type and dimensionality of the variable is determined by the right side.

The reassignment is available in version 6.1.1 or later.

When a variable appearing on the left side is already defined, then it is actually deleted first, and then redefined to the data type and dimensionality of the variable is determined by the right side.

Value-only reassignment

Value-only reassignments to variables are similar to value-only assignment, except that the left hand side variable could have been in different type and shape.

Consider the following example:

     a = (/1,2,3,4,5,6,7,8,9,10/)
    ;use a for something
     a := (/(/"I", "am"/), (/"string", "now"/)/)
     print(a)
    
    Variable: a
    Type: string
    Total Size: 32 bytes
                4 values
    Number of Dimensions: 2
    Dimensions and sizes:   [2] x [2]
    Coordinates: 
    (0,0)   I
    (0,1)   am
    (1,0)   string
    (1,1)   now
    
This example demonstrates the type of a changed from integer to string, and the dimensionality changed as well.

Variable-to-variable reassignments

During variable-to-variable reassignment the left hand side variable is deleted (if it is defined) and then variable-to-variable assignment is performed. The following shows how it works in NCl:
    ;
     a = new((/20, 20/), string)
    ;
    ; Create variable be with values, dimension names, coordinate variables 
    ; and attributes
    ;
    	b = (/ (/1.0,2.0,3.0/), (/4.0,5.0,6.0/), (/7.0,8.0,9.0/) /)
    	b!0 = "dim0"
    	b!1 = "dim1"
    	b@units = "none"
    	b&dim0 = (/.1,.2,.3/)
    	b&dim1 = (/10,100,1000/)
    
    
    ;Variable-to-variable reassignment with left side defined
    
    
     a := b
    
    ;Variable-to-variable reassignment with left side undefined
    
     c := b
    
     print(a)
     print(c)
    
    Variable: a
    Type: float
    Total Size: 36 bytes
                9 values
    Number of Dimensions: 2
    Dimensions and sizes:   [dim0 | 3] x [dim1 | 3]
    Coordinates: 
                dim0: [0.1..0.3]
                dim1: [10..1000]
    Number Of Attributes: 1
      units :       none
    (0,0)    1
    (0,1)    2
    (0,2)    3
    (1,0)    4
    (1,1)    5
    (1,2)    6
    (2,0)    7
    (2,1)    8
    (2,2)    9
    
    
    Variable: c
    Type: float
    Total Size: 36 bytes
                9 values
    Number of Dimensions: 2
    Dimensions and sizes:   [dim0 | 3] x [dim1 | 3]
    Coordinates: 
                dim0: [0.1..0.3]
                dim1: [10..1000]
    Number Of Attributes: 1
      units :       none
    (0,0)    1
    (0,1)    2
    (0,2)    3
    (1,0)    4
    (1,1)    5
    (1,2)    6
    (2,0)    7
    (2,1)    8
    (2,2)    9
    

List variables

Variables of type list may be used to contain a heterogeneous suite of NCL variables. Specifically, the variables within a list may be different types, sizes and shapes. An additional feature is that list variables can treated like stacks or queues.

Create list variables

There are two ways to create a list variables. The first is use the '[/.../]' syntax as shown in the following example:
    
     i = (/ (/1,2,3/), (/4,5,6/), (/7,8,9/) /)   ; 2-dimensioal integer array
     x = 5.0                                     ; scalar of type float
     d = (/100000.d, 283457.23d/)                ; 1-dimensional double array
     s = "abcde"                                 ; string
     c = stringtochar("abcde")                   ; character
     vl = [/i, x, d, c, s/]                      ; construct list via [/.../]
    

The second is to treat the list variable as a stack. This feature allows variables to be dynamically added to an existing list variable. The following example illustrates the basic approach. The NewList function creates a list and ListPush can be used to dynamically add variables to the list.

     x = (/1,2,3,4/)
     x@attr = "integer array"
     y = (/6.,7.,8.,9./)
     y@attr = "float array"
     s = (/"one","two","three"/)
     s@attr = "string array"
    
     my_list = NewList("lifo")
    
     ListPush(my_list,x)
     ListPush(my_list,y)
     ListPush(my_list,s)
    

Note: When using ListPush to add elements to the list, the newly added elements are always at the the head (top) of the list.

Check list variables

The ListCount counts the total elements in a list, and a function named ListIndex can be used to check if an element is in the list.

     cnt = ListCount(my_list)
    ;print(cnt)
    
     idx = ListIndex(my_list, x)
    ;print(idx)
    

Access list elements

There are two ways to access elements in a list. The first way is to access an element at a certain position via numeric indexing using square brackets. This does not change the element (number) in the list.

One can use ListIndex to get the index of of a variable, and then use this index to access the desired element.

     e = my_list[1]
    
     print(e)
    
     idx = ListIndex(my_list, x)
     print(idx)
    
     nx = my_list[idx]
    
     print("ori x = " + x)
     print("new x = " + nx)
    

The second is to access the element with the ListPop function. For those familiar with stacks and queues, there is an alias ListDequeue).

     a = ListPop(my_list)
    

Note: When using ListPop to access an element in the list, the element itself is removed from the list. Also, there is a choice to Pop/Dequeue from head/tail of the list depending on the type of the list. There are two types of list: 1. FIFO (First-In, First-Out, which functions like a queue in computer science); and, 2. LIFO (Last-In, First-Out, which is like a stack).

The list type can be checked using ListGetType, and changed with ListSetType.

     lt = ListGetType(my_list)
     ListSetType(my_list, "lifo")
     ListSetType(my_list, "fifo")
    

HLU object variables

HLU object variables are variables of type graphic. HLU object variables reference HLU objects that were either created with the create statement or were retrieved from an object with the getvalues statement. Arrays of HLU objects are supported by NCL. The same HLU functions that are available through C and Fortran are available from NCL to operate on HLU objects. See NCL versions of HLU functions and procedures for more information. The interfaces to many of the functions have been modified to support operations on one or more HLU object.

HLU object variables support assignment and all of the other properties of NCL variables. Also, HLU object variables can be compared with the .ne. and .eq. operators.

Files and file variables

Once again it is very important to understand the distinction between a variable that references a file (from now on simply called a file) and a file variable. When a file is opened with the addfile function, a reference to the file is assigned to a variable. The variable's data type is file. This variable is a variable that references a file. On the other hand, a file variable is a variable that is contained within a file. There are many ways to get information about file variables. Calling the procedure print with a variable that references a file as a parameter will produce a listing of all of the file's attributes, dimensions, variables, and coordinate variables. The procedure list_filevars produces a similar listing. The function getfilevarnames returns an array of strings that contains the string name of all the file variables in the file. filevardimsizes should always be used to determine the dimension sizes of a file variable. It is very important to use filevardimsizes since calling dimsizes may inadvertently force the entire file variable to be read into memory. getfilevaratts and getfilevardims are also useful functions.

Opening data files

Opening files is done with the addfile function. Addfile takes two parameters. The first is a UNIX pathname string, either relative or absolute, to the file; the second parameter is a string option. Currently there are three options for the second parameter, "w", "r", and "c". "w" means open the file with read/write permissions, "r" means open the file with read-only permissions, and "c" means create the file. "c" will return an error message if the file already exists. "w" will return an error message if the permissions of the file and/or directory are not correct.

The addfile function uses the file extension (i.e. ".nc" or ".cdf" for netCDF, ".hdf" for HDF, ".ccm" for CCM history files, and ".grb" for GRIB) to determine what type of file to open. Once open, all files and file variables regardless of type are referenced using the same NCL file reference syntax. For more information on what types of file formats are currently supported and special conventions of a specific file format, see the Supported data format information section of the reference guide.

Referencing file variables

The '->' operator is used to reference specific variables in a file. The following examples demonstrate referencing a file variable, a file variable attribute, and a file variable coordinate variable:
    a = file1->temperature(0,:,:,:)
    att = file1->temperature@units
    lon = file1->temperature&lon
    
Using the '->' operator requires the variable name to appear immediately after the '->'; parentheses and expressions are not allowed immediately after the '->'. A different kind of file variable access is available to reference variables by a string expression. This is covered elsewhere.

File variables function just like regular NCL variables with respect to what is outlined in the NCL properties of variables section. It is important to understand that only the section defined by the variable reference is read or written. This means that NCL allows direct access to file variables; the entire variable does not have to be read in to NCL at one time. For instance, if file1 contains a variable "elev" that is dimensioned [lat | 2159] x [lon | 4320], the selection file1->elev({20:60},{-135:-65}) will read in only the [lat | 480] x [lon | 840] subsection defined by the referencem leaving the remaining 8923680 data points in the file.

Note: for efficiency reasons, it is better to not reorder the dimensions when reading a variable off a file. Instead, if you can spare the extra memory, it is better to read the variable into memory, and then reorder the dimensions:

    T    = file1->T        ; Assume it is lon x lat x lev
                           ; and that we want lev x lat x lon.
    
    Tnew = T(  lev | :,  lat | :, lon | :)
    

File variable string references (Using '$' to reference file variables)

Sometimes it is convenient to write generic scripts that do depend on specific variable, attribute, or dimension names. This can be accomplished by using string variables containing the name of a variable rather than by hard-coding the names. Basically, string references work by putting a dollar sign '$' before and after the string variable. When NCL encounters this syntax, it uses the string value of the variable for the variable, attribute, or dimension name. There are several functions that are convenient to use with this feature. They are getfilevarnames, getfilevaratts, and getfilevardims.

The following is an example of how to copy a file from one format to another without knowing the names of the variables in the file.

    gribfile = addfile(ncargpath("data") + "/grb/ced1.lf00.t00z.eta.grb","r")
    ncfile = addfile("./ced1.lf00.t00z.eta.nc","c")
    names = getfilevarnames( gribfile )
    do i = 0, dimsizes( names ) - 1
    	ncfile->$names(i)$ = gribfile->$names(i)$
    end do
    
The following are examples of referencing attributes and dimensions using string references:
    ncl < fileinfo.ncl > file.output
    
	begin
;
; Open a file.
;
	gribfile = addfile(ncargpath("data") + "/grb/ced1.lf00.t00z.eta.grb","r")
;
; Get the names of the variables.
;
	names = getfilevarnames( gribfile )

;
; Loop on all the variables.
;
	do i = 0, dimsizes( names ) - 1
		print("Variable Name: " + names(i))
;
; Retrieve variable information.
;
		dims = getfilevardims(gribfile,names(i))
		sizes = filevardimsizes(gribfile,names(i))
;
; Print variable information.
;
		print(dimsizes(sizes) + " Dimensions:")
		if(.not.any(ismissing(dims))) then
			do j = 0, dimsizes(dims) -1
				print( j + ") " + dims(j) + ": " + sizes(j))
			end do	
		end if
		atts = getfilevaratts(gribfile,names(i))
		if(.not.any(ismissing(atts))) then
			do k = 0, dimsizes(atts) -1
;
; Example of accessing attributes and variable using the string
; reference technique.
;
				print(atts(k) + ": " +gribfile->$names(i)$@$atts(k)$)
			end do
		end if
		delete(atts)
		delete(dims)
		delete(sizes)
		print("")
	end do
end

Assignment to file variables

The rules for assignment of variables to files are the same as those for assigning variables to variables with a couple of exceptions. The first and most important is that when assigning a variable to a file, you must define the dimension names. If you don't, NCL will pick ones for you. The second exception is that dimensions, coordinate variables and variables cannot be deleted from a file. This means that a warning message will be generated when the assignment tries to delete a dimension name or coordinate variable. To avoid these errors, make sure your dimension names are defined before assignment, and when you do assign a variable to a file variable that is already defined, make sure your right side has the same dimension names and coordinate variables. One way to do this is to use the following four procedures to pre-define your variables, attributes, dimensions, and coordinate variables: filedimdef, filevardef, filevarattdef, and fileattdef.

Groups and group variables

Group is a structure under a file or group. It is only available to HDF5 file in NCL for now. A group is just like a directory on a disk (where disk is a file here).

Create groups

HDF5 file can be opened with the addfile function. Addfile takes two parameters. The first is a UNIX pathname string, either relative or absolute, to the HDF5 file; the second parameter is a string option. Currently there are three options for the second parameter, "w", "r", and "c", which has described above for file.

See the Supported data format information section of the reference guide for more info. The '=>' operator is used to reference specific group in a file. The following examples demonstrate referencing a group from a file, and a group from another group, and then then referencing variable from a group.

     f = addfile("data/NISESSMI.h5", "r")
    
     gn = "/Northern Hemisphere"
    
     g1 = f=>$gn$
    
    ;print(typeof(g1))
    ;print(g1)
    
     g2n = "/Northern Hemisphere/Data Fields"
     g2 = g1=>$g2n$
    ;print(g2)
    

Referencing variables in groups

The '->' operator is used to reference specific variable in a group, similar to reference a variable in a file. Using the '->' operator requires the variable name to appear immediately after the '->'; parentheses and expressions are not allowed immediately after the '->'. A different kind of file variable access is available to reference variables by a string expression, as in the example to be quotaed with '$' (dollar sign), this is exactly same as from a file.

The following example continues from the above to access a variable from a group.

     vn = "/Northern Hemisphere/Data Fields/Age"
     v1 = g1->$vn$
    
     v2 = g2->$vn$
    
Group variables function just like regular NCL files with respect to what is outlined in the NCL properties of files section.