1. cf-python

Table of contents

See the cf-python home page for more documentation on the CF data model, downloads and source code.

2. Field structure

Table of contents

A field is composed as follows (refer to the data model description and accompanying UML diagram for more details):

Field:

All components of a field are optional.

3. Data storage, access and manipulation

Table of contents

The Variable class and all objects which inherit it (namely Field, Coordinate, CoordinateBounds and CellMeasures) contain data arrays. The data storage, access and manipulation model is very similar for all of them and it will be noted when certain objects exhibit different behaviour. In this section, the word “variable” refers a Variable object or any object which inherits from the Variable class.

3.1. Resizing

Table of contents

A variable’s data may be sliced by indexing its slice attribute. Indexing is similar to that of a numpy array. The differences to numpy array indexing are:

  1. An integer index i takes the i-th element but does not reduce the rank of the output array by one.
  2. More than one dimension’s slice may be a 1-d boolean array or 1-d sequence of integers, and these indices work independently along each dimension (similar to the way vector subscripts work in Fortran).

The result of a slice is a new variable instance and if the variable’s the new variable’s data will be a deep copy of the slice of the original array.

>>> isinstance(v, Variable)
True
>>> v.shape
(10, 20, 30)
>>> v.slice[0].shape
(1, 20, 30)
>>> v.slice[0, -1, 3].shape
(1, 1, 1)
>>> v.slice[0:5,...,slice(11,0,-2)].shape
(5, 20, 6)
>>> v.shape
(10, 20, 30)
>>> v.slice[:,:,numpy.arange(30) < 4].shape
(10, 20, 4)
>>> v.slice([1,2], [3,4], [5,6]).shape
(2, 2, 2)

For variables which contain other variable types, the contained variables are also sliced. So slicing a coordinate also slices its bounds, if there are any; and slicing a field also slices its space by applying each dimension’s slice to the appropriate space elements.

3.1.1. Size 1 dimensions

Table of contents

Size 1 dimensions resulting from a slice are always retained. However, a size 1 dimension may optionally be dropped from the field’s data and its dimension coordinate reduced to a scalar if no auxiliary coordinates or cell measures span that dimension. Therefore, fields and dimension coordinates may contain scalar data, but auxiliary coordinates and cell measures may not. A field’s squash method will carry out this reduction.

3.1.2. Resizing by coordinate values

Table of contents

A field may be resized by specifying conditions on its coordinate’s values. These conditions are specified as arguments to a call to the field’s slice attribute (as opposed to indexing it). Note that only a field’s slice attribute may be called in this manner.

>>> s
<CF Field: air_temperature(7070, 64, 128)>
>>> print s
Data            : air_temperature(time, latitude, longitude)
Cell methods    : time: mean (interval: 1.0 month)
Dimensions      : time(7070) -> 450-11-16 00:00:00 to 1049-12-16 12:00:00
                : latitude(64) -> -87.8638 to 87.8638 degrees_north
                : longitude(128) -> 0 to 357.1875 degrees_east
                : height(1) -> 2 m
Auxiliary coords:
>>> s.slice[:,32, 64]
<CF Field: air_temperature(7070, 1, 1)
>>> s.slice(longitude=0.0, latitude=0.0)
<CF Field: air_temperature(7070, 1, 1)

3.2. Assignment to the data array

Table of contents

Assignment to the data array is done with the same indexing of the slice attribute as for data access. Assignment can not change the shape of the data:

>>> v.shape
(10, 20, 30)
>>> v.slice[0, 0, 0] = 273.15
>>> v.varray[0,0,0]
273.15
>>> v.slice[0] = 273.15
>>> v.shape
(10, 20, 30)
>>> v.slice[1,2,:] = range(30)
>>> v.slice[...] = numpy.arange(6000).reshape(10, 20, 30)

3.3. Data storage

Table of contents

The data may be stored as numpy arrays or as file pointers. A file pointer may be any kind of object which has attributes shape, size, ndim and dtype; and is indexable all in the same manner as a numpy array. A netCDF4.Variable instance is an example of a valid file pointer object. Accessing the data makes no distinction between the two storage methods, but there are I/O, memory and speed performance issues to consider. If data are stored as a file pointer then accessing any part of the array will (at present) cause the entire array to be read from disk into memory and stored as a numpy array, replacing the original file pointer. Refer to read and write.

A variable stores a list of numpy arrays and file pointers which is treated by the variable as if it were a single numpy array created by realizing any file pointers in memory and concatenating all arrays in the list along their common dimension. Such a list is usually created when fields are aggregated, thereby not requiring data to be read from disk during the aggregation process. Units, missing data values, packing scale factors, packing offsets and array dimension orders may all differ between list elements, with any required conversions being made at the time of data access.

The list of numpy arrays and file pointers is held inside a Data instance and a variable’s data may be completely replaced by assigning a Data object to its _data attribute:

>>> v._data = cf.Data(numpy.arange(10))
>>> type(ncvariable)
<type 'netCDF4.Variable'>
>>> v._data = cf.Data(ncvariable)

Note that this assignment makes does not check on consistency with the variable’s metadata.

3.4. Copying

Table of contents

A deep copy of a variable may be created using its copy method or, equivalently, using the copy module.

>>> w = v.copy()
>>> w = copy.deepcopy(v)

This type of copy does not read any data from disk, i.e. it will not convert a file pointer to a numpy array. A third type of copy, however, will do such a conversion, namely slicing the variable with an ellipsis (or equivalent):

>>> v.type
<type 'netCDF4.Variable'>
>>> w = v.copy()
>>> w.type, v.type
(<type 'netCDF4.Variable'>, <type 'netCDF4.Variable'>)
>>> w = v.slice[...]
>>> w.type, v.type
(<type 'numpy.ndarray'>, <type 'numpy.ndarray'>)

4. Units

Table of contents

A variable always contains a Units object which gives the physical units of the values contained in its data array, if it has one. The Units object is stored in the Units attribute but is typically accessed through the variable’s units and calendar attributes, which may take any value allowed by the CF conventions. In particular, the value of the units attribute is a string that can be recognized by UNIDATA’s Udunits package, with the few exceptions given in the CF conventions.

>>> v.units = 'm s-1'
>>> v.Units
<Cf Units: 'm s-1'>
>>> v.units = 'days since 2004-3-1'
>>> v.calendar = 'noleap'
>>> v.Units
<CF Units: days since 2004-3-1 calendar=noleap>

4.1. Equality and equivalence of units

Table of contents

The Units object has methods for assessing whether two units are equivalent or equal. Two units are equivalent if numeric values in one unit are convertible to numeric values in the other unit (such as kilometres and metres). Two units are equal if they are equivalent and their conversion is a scale factor of 1 (such as kilometres and 1000 metres). Note that equivalence and equality are based on internally stored binary representations of the units, rather than their string representations.

>>> u.units = 'm/s'
>>> v.units = 'm s-1'
>>> u.Units.equals(v.Units)
True
>>> v.units = 'days since 1987-12-3'
>>> u.Units.equals(v.Units)
False
>>> v.units = 'km s-1'
>>> u.Units.equals(v.Units)
False
>>> u.Units.equivalent(v.Units)
True
>>> v.units = '0.001 kilometer.second-1'
>>> u.Units.equals(v.Units)
True
>>> u.Units.equivalent(v.Units)
True

4.2. Time units

Table of contents

Time units may be given as durations of time or as an amount of time since a reference time:

>>> v.units = 's'
>>> v.units = 'day'
>>> v.units = 'days since 1970-01-01'
>>> v.units = 'seconds since 1992-10-8 15:15:42.5 -6:00'

Note

It is recommended that the units year and month be used with caution, as explained in the following excerpt from the CF conventions: “The Udunits package defines a year to be exactly 365.242198781 days (the interval between 2 successive passages of the sun through vernal equinox). It is not a calendar year. Udunits includes the following definitions for years: a common_year is 365 days, a leap_year is 366 days, a Julian_year is 365.25 days, and a Gregorian_year is 365.2425 days. For similar reasons the unit month, which is defined to be exactly year/12, should also be used with caution.”

4.2.1. Calendar

Table of contents

The date given in reference time units must be associated with one of the calendars recognized by the CF conventions and may be set with the variable’s calendar attribute. However, as in the CF conventions, if the calendar is not set then, for the purposes of calculation and comparison, it defaults to the mixed Gregorian/Julian calendar as defined by Udunits:

>>> v.units = 'days since 2000-1-1'
>>> v.calendar
AttributeError: Can't get 'Variable' attribute 'calendar'
>>> w.units = 'days since 2000-1-1'
>>> w.calendar = 'gregorian'
>>> w.Units.equals(v.Units)
True

4.3. Changing units

Table of contents

Changing units to equivalent units causes the variable’s data array values to be modified in place (if required) when they are next accessed, and not before:

>>> v.units
'metre'
>>> v.varray
array([    0.,  1000.,  2000.,  3000.,  4000.])
>>> v.units = 'kilometre'
>>> v.units
'kilometre'
>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])
>>> v.units
'hours since 2000-1-1'
>>> v.varray
array([-1227192., -1227168., -1227144.])
>>> v.units = 'days since 1860-1-1'
>>> v.varray
array([ 1.,  2.,  3.])

Equivalently to assigning new units as a string to the units attribute, the Units object stored in the Units attribute may be operated on with overloaded augmented arithmetic assignments and binary arithmetic operations:

>>> v.units
'kelvin'
>>> v.varray
array([ 273.15,  274.15,  275.15,  276.15,  277.15])
>>> v.Units -= 273.15
>>> v.units
'K @ 273.15'
>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])
>>> v.Units = v.Units + 273.15
>>> v.units
'K'
>>> v.varray
array([ 273.15,  274.15,  275.15,  276.15,  277.15])
>>> v.units = 'K @ 237.15'
'K @ 273.15'
>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])

If the variable has a data array and its units are changed to non-equivalent units then a TypeError will be raised when the data are next accessed:

>>> v.units
'm s-1'
>>> v.units = 'K'
>>> v.varray
TypeError: Units are not convertible: <CF Units: m s-1>, <CF Units: K>

It is possible to change a variable’s units without modifying the data by using the variable’s override_Units method.

Any numpy array may be modified in place for equivalent units using the Units object’s conform method.

4.3.1. Changing units without modifying the data

Table of contents

It is possible to change a variable’s units without modifying the data by using the variable’s override_Units method. This is useful for correcting erroneously set units and setting units where there were none:

>>> v.Units
<CF Units: metre>
>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])
>>> v.override_Units(cf.Units('km'))
>>> v.Units
<CF Units: km>
>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])
>>> v.units
AttributeError: 'Variable' object has no attribute 'units'
>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])
>>> w.Units
<CF Units: days since 2000-1-1 calendar='noleap'>
>>> v.override_Units(w.Units)
>>> v.Units
<CF Units: days since 2000-1-1 calendar='noleap'>
>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])

4.3.2. Changing the calendar

Table of contents

Warning

Do not change the calendar of reference time units. Whilst this is possible, it will almost certainly result in an incorrect interpretation of the data array or an error. Allowing the calendar to be changed is under development and will be available soon.

4.4. Coordinate units

Table of contents

Although deprecated in the CF conventions, the units level, layer, and sigma_level are still allowed for dimensionless vertical coordinates and are equivalent to setting dimensionless units of 1.

>>> c.units
'level'
>>> d.units
'1'
>>> c.Units.equals(d.Units)
True

The units of a coordinate’s bounds are always the same as the coordinate itself, and the units of the bounds automatically change when a coordinate’s units are changed:

>>> c.units
'degrees'
>>> c.bounds.units
'degrees'
>>> c.units = 'radians'
>>> c.bounds.units
'radians'

5. Arithmetic and comparison with variables

Table of contents

5.1. Operator overloading

Table of contents

The following operators, operations and assignments are overloaded in a variable to apply element-wise to the variable’s data as a numpy array.

Comparison operators:

==, !=, >, <, >=, <=

Binary arithmetic operations:

+, -, *, /, //, __truediv__, %, pow(), **, &, ^, |

Unary arithmetic operations:

-, +, abs(), ~

Augmented arithmetic assignments:

+=, -=, *=, /=, //=, %=, **=, &=, ^=, |=

5.2. Valid operations

Table of contents

Since a variable’s data as a numpy array are used in these comparisons and operations, the variable may be combined with any object which its data as a numpy array may be combined with or another variable (via its data as a numpy array). The result of the comparison operations will a numpy boolean array, the result of the binary and unary arithmetic operations will be a new variable and the augmented arithmetic operations will modify the variable in place:

>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])
>>> w.varray
array([ 0.,  2.,  4.,  6.,  8.])
>>> array = numpy.array([1, 2, 3, 4, 5])
>>> x = v + w
>>> x.varray
array([ 0.,  3.,  6.,  9.,  12.])
>>> x = v + 2
>>> x.varray
array([ 2.,  3.,  4.,  5.,  6.])
>>> x = v + array
>>> x.varray
array([ 1.,  3.,  5.,  7,  9.])
>>> x = 2 + v
>>> x.varray
array([ 2.,  3.,  4.,  5.,  6.])
>>> x = array + v
>>> x.varray
array([ 1.,  3.,  5.,  7,  9.])
>>> v > w
array([False, False, False, False, False], dtype=bool)
>>> v == 2
array([False, False,  True, False, False], dtype=bool)
>>> v <= array
array([ True,  True,  True,  True,  True], dtype=bool)
>>> id(v)
18085504
>>> v = v + 2
>>> id(v)
18097176
>>> v += 2
>>> id(v)
18097176

5.3. Units in variable arithmetic

Table of contents

When variables with defined units are combined arithmetically, their units are also combined to reflect the physical nature of the new values. The following examples give various units to variables v and w whilst their data arrays remain the same:

>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])
>>> w.varray
array([ 0.,  2.,  4.,  6.,  8.])
>>> v.units
'm'
>>> x = v ** 3
>>> x.units
'm3'
>>> x.array
array([  0.,   1.,   8.,  27.,  64.])
>>> w.units
's'
>>> x = v / w
>>> x.units
'm s-1'
>>> x.varray
array([ NaN,  0.5,  0.5,  0.5,  0.5])

When combining two variables with equivalent but non-equal units, the value of the operand on the right hand side is automatically converted to the units of the operand on the left side prior to the operation being carried out. This conversion is done in a temporary copy of the array and does not affect the variable in place:

>>> v.units
'm'
>>> w.units
'km'
>>> x = v + w
>>> x.units
'm'
>>> x.varray
array([    0.,  2001.,  4002.,  6003.,  8004.])
>>> w.varray
array([ 0.,  2.,  4.,  6.,  8.])
>>> v.units
'days since 2000-12-1'
>>> w.units
'seconds'
>>> x = v + (w * 5400)
>>> x.units
'days since 2000-12-1'
>>> x.varray
array([ 0.   ,  1.125,  2.25 ,  3.375,  4.5  ])
>>> v.units
'days since 2000-12-1'
>>> w.units
'days since 2000-11-30'
>>> x = v - w
>>> x.units
'days'
>>> x.varray
array([ 1.,  0.,  -1.,  -2.,  -3.])

5.4. Associating units with non-variable objects

Table of contents

The ValueUnits object allows units to be associated with a number or a numpy array, so that units may be taken into account when it is combined with a variable, another ValueUnits object or a number:

>>> v.varray
array([ 0.,  1.,  2.,  3.,  4.])
>>> s = cf.ValueUnits(2.0, units='s')
>>> m = cf.ValueUnits(2000.0, units='metres')
>>> a = cf.ValueUnits(numpy.array([1, 2, 3, 2, 1]), units='km')
>>> b = a / s
>>> b
<CF ValueUnits: array([ 0.5,  1. ,  1.5,  1. ,  0.5]), units='km s-1'>
>>> b = a - 1
>>> b
<CF ValueUnits: array([0, 1, 2, 1, 0]), units='km'>
>>> b = a ** 2
>>> b
<CF ValueUnits: array([ 1, 4, 9, 4, 1]), units='km2'>
>>> a < m
array([ True, False, False, False,  True], dtype=bool)
>>> v.units
'm'
>>> x = v / s
>>> x.units
'm s-1'
>>> x.varray
array([ 0., 0.5.,  1., 1.5,  2.])
>>> v.units
'm'
>>> x = v * a
>>> x.units
'm2'
>>> x.varray
array([    0.,  2000.,  6000.,  6000.,  4000.])

When combining two ValueUnits objects, or a ValueUnits object and a variable, with equivalent but non-equal units, the value of the operand on the right hand side is automatically converted to the units of the operand on the left side prior to the operation being carried out. This conversion is done in a temporary copy of the array and does not affect the object in place:

>>> x = t - a
>>> x
<CF ValueUnits: array([ 1000.,     0., -1000.,     0.,  1000.]), units='metres'>
>>> a
<CF ValueUnits: array([1, 2, 3, 2, 1]), units='km'>

6. Tolerance of numeric equality

Table of contents

Most objects defined in the cf package have an equals method which determines the congruence of two instances. The aspects of this equality vary between objects, but for all objects numeric equalities are tested to within a tolerance defined by parameters ‘rtol’ (relative tolerance) and ‘atol’ (absolute tolerance), where two numbers a and b (from the left and right sides respectively of the comparison) are considered equal if

|a-b|<=atol+rtol*|b|

Default tolerances may be found and set with the functions RTOL and ATOL. Numerically tolerant equality of two objects is also tested by the equals function.

7. Space structure

Table of contents

A space contains any number of dimensions and space components, the latter comprising dimension coordinates, auxiliary coordinates, cell measures and transforms. A field’s space is stored in its attr:`~.cf.Field.space attribute, the value of which is a Space object.

7.1. Dimensionality

Table of contents

The dimensions of the space, and of its associated field, are given by the space’s dimension_sizes and dimensions attributes.

The dimension_sizes attribute is a dictionary whose keys are dimension identifiers and values are positive integer dimension sizes. A dimension identifier is the string dim suffixed by an arbitrary, but unique, integer. For example:

>>> s
<CF Space: (30, 24, 1, 17)>
>>> s.dimension_sizes
{'dim0': 1, 'dim1': 17, 'dim2': 30, 'dim3': 24}

The dimensions attribute specifies which dimensions relate to each space component (coordinates and cell measures) and to the field which holds the space. For example:

>>> s.dimensions
{'data': ['dim1', 'dim2', 'dim3'],
 'aux0': ['dim2', 'dim3'],
 'aux1': ['dim2', 'dim3'],
 'cm0' : ['dim2', 'dim3'],
 'dim0': ['dim0'],
 'dim1': ['dim1'],
 'dim2': ['dim2'],
 'dim3': ['dim3']}

A key of this dictionary identifies a space component or the field’s data as follows:

Key prefix Description
aux Auxiliary coordinate
cm Cell measures
data The field containing the space
dim Dimension coordinate

Each key’s value is an ordered list which corresponds to the shape of that component’s data, with two exceptions:

  1. If the field’s data is a scalar then its value is an empty list
  2. If a dimension coordinate is a scalar it retains its dimension as a single element list.

An arbitrary non-negative integer after the prefix discerns between space components of the same type.

It is possible for a space dimension to have no space components.

7.2. Storage of coordinates and cell measures variables

Table of contents

The space object is a kind of dictionary which support the built-in dictionary’s methods. Its keys are the identifiers of the space components dimension coordinates, auxiliary coordinates and cell measures. Each key’s value stores the variable it identifies. For example, a space’s key and value pairs may be:

>>> s.keys()
['dim0', 'dim1', 'dim2', 'dim3', 'aux0', 'aux1']
>>> for key, value in s.iteritems():
...     print key, ':', repr(value)
...
dim0: <CF Coordinate: sigma(20)>
dim1: <CF Coordinate: time(12)>
dim2: <CF Coordinate: latitude(111)>
dim3: <CF Coordinate: longitude(106)>
aux0: <CF Coordinate: grid_latitude(111, 106)>
aux1: <CF Coordinate: grid_longitude(111, 106)>

7.3. Transforms

Table of contents

The space may have any number of transforms describing projection parameters (CF grid mappings) or potential auxiliary coordinates (coordinates defined by CF formula_terms equations). These are stored in the space’s transform attribute, which is a dictionary of Transform objects. For example:

>>> s.transform
{'trans0': <CF Transform: atmosphere_sigma_coordinate>,
 'trans1': <CF Transform: rotated_latitude_longitude>}
>>> cf.dump(s.transform['trans0'])
atmosphere_sigma_coordinate transform
-------------------------------------
Transform['ps'] = <CF Field: surface_air_pressure(106, 111)>
Transform['ptop'] = <CF Field: ptop>
Transform['sigma'] = 'dim0'
>>> cf.dump(s.transform['trans1'])
rotated_latitude_longitude transform
------------------------------------
Transform['grid_mapping_name'] = 'rotated_latitude_longitude'
Transform['grid_north_pole_latitude'] = 70.0
Transform['grid_north_pole_longitude'] = 100.0
Transform['north_pole_grid_longitude'] = -80.0

A transform may also be linked with any number of the space’s coordinates via their transform attributes:

>>> s['dim0'].transform
'trans0'
>>> s['dim2'].transform
'trans1'
>>> s['dim3'].transform
'trans1'
>>> s['aux0'].transform
'trans1'
>>> s['aux1'].transform
'trans1'

8. Attributes

Table of contents

8.1. Instance attributes

Table of contents

Attributes may be set on a variable in the usual way, but these will not be recognized as CF attributes. Some attributes, such as existing methods, are reserved and may not be set:

>>> v.property = 999
>>> v.property
999
>>> v.match = 'test'
AttributeError

Refer to Variable for details on reserved attributes and methods.

8.2. Public attributes

Table of contents

Public variable attributes are those which you would expect to read from or be written to a CF variable on disk. They are set, retrieved and deleted with the methods setpub, getpub and delpub respectively, thereby allowing public attributes to share names with reserved attribute names, instance attributes and private attributes:

>>> v.getpub('standard_name')
AttributeError: 'Variable' object doesn't have public attribute 'standard_name'
>>> v.setpub('standard_name', 'air_temperature')
>>> v.getpub('standard_name')
'air_temperature'
>>> v.delpub('standard_name')
>>> v.getpub('standard_name')
AttributeError: 'Variable' object doesn't have public attribute 'standard_name'
>>> v.getpub('standard_name', 'default_value')
'default_value'

For convenience, the variable’s pub method provides a shorter way of setting and retrieving public attributes which is exactly equivalent to either the setpub or getpub methods:

>>> v.pub(standard_name='air_temperature')
>>> v.pub('standard_name')
'air_temperature'
>>> v.delpub('standard_name')
>>> v.pub('standard_name', 'default_value')
'default_value'

For further convenience, attributes with a special CF meaning for a particular type of CF variable may be set, retrieved and deleted directly on the variable itself, equivalently to using the setpub, getpub or delpub methods:

>>> v.standard_name = 'air_pressure'
>>> v.standard_name
'air_pressure'
>>> del v.standard_name
>>> v.pub(standard_name='air_pressure')
>>> v.standard_name
'air_pressure'

In general, these attributes match those given in appendix A of the CF conventions, with any deviations given in the documentation of the relevant classes (Variable, Field or Coordinate).

8.3. Private attributes

Table of contents

Private attributes are those which are solely for convienience within the API and are not to be written to a CF variable on disk. Similarly to public attributes, they may be set, retrieved and deleted with the methods setpriv, getpriv and delpriv respectively, thereby allowing private attributes to share names with reserved attribute names, instance attributes and public attributes:

>>> v.setpriv('file', '../file.nc')
>>> v.getpriv('file')
'../file.nc'
>>> v.delpriv('file')
>>> v.getpriv('file')
AttributeError: 'Variable' object doesn't have private attribute 'file'
>>> v.getpriv('file', 'default_value')
'default_value'

For convenience, the variable’s priv method provides a shorter way of setting and retrieving private attributes which is exactly equivalent to either the setpriv or getpriv methods:

>>> v.priv(ncvar='data1')
>>> v.priv('ncvar')
'data1'
>>> v.delpriv('ncvar')
>>> v.priv('ncvar', 'default_value')
'default_value'

9. Variable lists

Table of contents

The Variable, Coordinate and Field objects have associated list objects which allow an ordered sequence of instances to be stored as a single, list-like object:

Class Associated list class
Variable VariableList
Coordinate CoordinateList
Field FieldList

These list-like objects behave in much the same way as built-in lists:

>>> type(sl)
<class 'cf.field.FieldList'>
>>> sl
[<CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>,
 <CF Field: precipitation_flux(2400, 96, 192)>,
 <CF Field: air_temperature(2400, 96, 192)>]
>>> len(sl)
3

They are indexable in same way as built-in lists returning either list or non-list types depending on the nature of the index:

>>> type(sl[0])
<class 'cf.field.Field'>
>>> sl[0]
<CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>
>>> type(sl[2::-2])
<class 'cf.field.FieldList'>
>>> sl[2::-2]
[<CF Field: air_temperature(2400, 96, 192)>,
 <CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>]
>>> type(sl[slice(1,2)])
<class 'cf.field.FieldList'>
>>> sl[slice(1,2)]
[<CF Field: precipitation_flux(2400, 96, 192)>]

The usual built-in list methods work as expected. For example:

>>> print repr(sl.reverse()
[<CF Field: air_temperature(2400, 96, 192)>,
 <CF Field: precipitation_flux(2400, 96, 192)>,
 <CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>]
>>> sl.append(sl[0])
>>> sl
[<CF Field: air_temperature(2400, 96, 192)>,
 <CF Field: precipitation_flux(2400, 96, 192)>,
 <CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>,
 <CF Field: air_temperature(2400, 96, 192)>]
>>> len(sl)
4
>>> sl.insert(1, sl[2])
>>> sl
[<CF Field: air_temperature(2400, 96, 192)>,
 <CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>,
 <CF Field: precipitation_flux(2400, 96, 192)>,
 <CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>,
 <CF Field: air_temperature(2400, 96, 192)>]
>>> len(sl)
5
>>> sl.index(sl[2])
2
>>> sl[3] in sl
True
>>> sl.extend(sl[0:2])
>>> sl
[<CF Field: air_temperature(2400, 96, 192)>,
 <CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>,
 <CF Field: precipitation_flux(2400, 96, 192)>,
 <CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>,
 <CF Field: air_temperature(2400, 96, 192)>,
 <CF Field: air_temperature(2400, 96, 192)>,
 <CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>]
>>> len(sl)
7
>>> sl.pop()
<CF Field: toa_outgoing_longwave_flux_assuming_clear_sky(2400, 96, 192)>
>>> len(sl)
6
>>> sl.remove(sl[0])
>>> len(sl)
5

Non-list instances are also indexable as if they were single element lists. Indexing them is essentially a null operation, but allows them to be used interchangeably with their list counterparts. This is particularly useful in iterative situations when it is not known if an instance is a variable or its list counterpart:

>>> type(x)
<class 'cf.field.Field'>
>>> type(x[0])
<class 'cf.field.Field'>
>>> type(y)
<class 'cf.field.FieldList'>
>>> len(x), len(y)
(1, 3)
>>> for i in x:
...     print type(i), repr(i)
...
<class 'cf.field.Field'> <CF Field: air_density(2400, 96, 192)>
>>> for i in y:
...     print type(i), repr(i)
...
<class 'cf.field.Field'> <CF Field: air_pressure(2400, 96, 192)>
<class 'cf.field.Field'> <CF Field: air_temperature(2400, 96, 192)>
<class 'cf.field.Field'> <CF Field: precipitation_flux(2400, 96, 192)>

Attributes and methods of a variable are all available on its list counterpart by broadcasting to each element of the list:

>>> sl.units
['Pa', 'K', 'kg m-2 s-1']
>>> sl[1].units
'K'
>>> sl.units[1]
'K'
>>> sl[1:2].units
['K']
>>> sl.new_attribute = 'test'
>>> sl.new_attribute
['test', 'test', 'test']
>>> s = sl[2]
>>> s.new_attribute
'test'
>>> sl.name()
['air_pressure',
 'air_temperature',
 'precipitation_flux'] 
>>> sl.__repr__()
[<CF Field: air_pressure(2400, 96, 192)>,
 <CF Field: air_temperature(2400, 96, 192)>,
 <CF Field: precipitation_flux(2400, 96, 192)>]
>>> sl.match(units='K')
[False, True, False]

Use the pub and priv (or getpub and getpriv) methods to return defaults values for missing attributes:

>>> sl._FillValue
AttributeError: Can't get 'Field' attribute '_FillValue'
>>> sl.pub('_FillValue')
AttributeError: Can't get 'Field' attribute '_FillValue'
>>> sl.pub('_FillValue', None)
[None, None, None, -1.0e+30]

10. Aggregation

Table of contents

Fields read from disk with the read function are, by default, aggregated in to as few fields as possible according to the CF aggregation rules. Fields in memory may also be aggregated with the aggregate function.

11. Classes

Table of contents

Class Description Parent class
Variable Abstract base class object
CfList Abstract base class MutableSequence
CfDict Abstract base class MutableMapping
Field Field Variable
Coordinate Dimension or auxiliary coordinate Variable
CoordinateBounds Coordinate bounds Variable
CellMeasures Cell measures Variable
Space Space CfDict
Transform Coordinate transforms CfDict
CellMethods Cell methods CfList
Units Comparison expression object
Data Comparison expression object
VariableList List of variables CfList
CoordinateList List of coordinates VariableList
FieldList List of fields VariableList
Comparison Comparison expression object

12. Functions

Table of contents

Function Description
aggregate Aggregate fields into as few fields as possible.
dump Print the string returned from an object’s dump method.
eq Create a Comparison object.
equals Determine whether two objects are congruent.
ATOL Absolute tolerance for numerical equality.
RTOL Relative tolerance for numerical equality.
ge Create a Comparison object.
gt Create a Comparison object.
inside Create a Comparison object.
le Create a Comparison object.
lt Create a Comparison object.
ne Create a Comparison object.
outside Create a Comparison object.
read Read fields from netCDF files.
write Write fields to a netCDF file.