Creating cf.Field objects

Note

For versions 3.x (Python 3) documentation, see https://ncas-cms.github.io/cf-python

A new field may be created by initializing a new cf.Field instance with properties and a data array:

Keyword Description
attributes Provide the new field with non-CF attributes in a dictionary
data Provide the new field with a data array in a cf.Data object
flags Provide the new field with self-describing flag values in a cf.Flags object
properties Provide the new field with CF properties in a dictionary

Other metadata items (coordinate, cell methods, etc.) are then provided with bespoke methods:

cf.Field.insert_aux Insert an auxiliary coordinate object into the field.
cf.Field.insert_axis Insert a domain axis into the field.
cf.Field.insert_cell_methods Insert one or more cell method objects into the field.
cf.Field.insert_domain_anc Insert a domain ancillary object into the field.
cf.Field.insert_data Insert a data array into the field.
cf.Field.insert_dim Insert a dimension coordinate object into the field.
cf.Field.insert_field_anc Insert a field ancillary object into the field.
cf.Field.insert_measure Insert a cell measure object into the field.
cf.Field.insert_ref Insert a coordinate reference object into the field.

For example:

>>> coord
<CF DimensionCoordinate: time(12) days since 2003-12-1>
>>> f.insert_dim(coord)

Removing field components is done with the following methods:

cf.Field.remove_axis Remove and return a unique axis from the field.
cf.Field.remove_axes Remove and return axes from the field.
cf.Field.remove_data Remove and return the data array.
cf.Field.remove_item Remove and return an item from the field.
cf.Field.remove_items Remove and return items from the field.

For example:

>>> f.remove_item('forecast_reference_time')

Examples

To improve readability, it is recommended that the construction of a field is done by first creating the components separately (data, coordinates, properties, etc.), and then combining them to make the field (as in example 3 and example 4), although this may not be necessary for very simple fields (as in example 1 and example 2).

Example 1

An empty field:

>>> f = cf.Field()
>>> print f
Field:
-------

Example 2

A field with just CF properties:

>>> f = cf.Field(properties={'standard_name': 'air_temperature',
...                          'long_name': 'temperature of air'})
...
>>> print f
Field: air_temperature
----------------------

Example 3

A field with a simple domain. Note that in this example the data and coordinates are generated using range and numpy.arange simply for the sake of having some numbers to play with. In practice it is likely the values would have been read from a file in some arbitrary format:

>>> import numpy
>>> data = cf.Data(numpy.arange(90.).reshape(10, 9), 'm s-1')
>>> properties = {'standard_name': 'eastward_wind'}
>>> dim0 = cf.DimensionCoordinate(data=cf.Data(range(10), 'degrees_north'),
...                               properties={'standard_name': 'latitude'})
>>> dim1 = cf.DimensionCoordinate(data=cf.Data(range(9), 'degrees_east'))
>>> dim1.standard_name = 'longitude'
>>> f = cf.Field(properties=properties)
>>> f.insert_dim(dim0)
>>> f.insert_dim(dim1)
>>> f.insert_data(data)
>>> print f
Field: eastward_wind
--------------------
Data           : eastward_wind(latitude(10), longitude(9)) m s-1
Axes           : latitude(10) = [0, ..., 9] degrees_north
               : longitude(9) = [0, ..., 8] degrees_east

Adding an auxiliary coordinate to the “latitude” axis and a cell method may be done with the relevant methods (note that these coordinate values are just for illustration):

>>> aux = cf.AuxiliaryCoordinate(data=cf.Data(['alpha','beta','gamma','delta','epsilon',
...                                            'zeta','eta','theta','iota','kappa']))
>>> aux.long_name = 'extra'
>>> f.insert_aux(aux, axes=['dim0'])
>>> f.insert_cell_methods('latitude: point')
>>> f.long_name = 'wind'
>>> print f
Field: eastward_wind
--------------------
Data           : eastward_wind(latitude(10), longitude(9)) m s-1
Cell methods   : latitude: point
Axes           : latitude(10) = [0, ..., 9] degrees_north
               : longitude(9) = [0, ..., 8] degrees_east
Aux coords     : long_name:extra(latitude(10)) = [alpha, ..., kappa]

Removing the auxiliary coordinate and the cell method that were just added is also done with a method and by simple deletion:

>>> f.remove_item({'long_name': 'extra'})
>>> del f.cell_methods
>>> print f
Field: eastward_wind
--------------------
Data           : eastward_wind(latitude(10), longitude(9)) m s-1
Axes           : latitude(10) = [0, ..., 9] degrees_north
               : longitude(9) = [0, ..., 8] degrees_east

Example 4

A more complicated field is created by the following script. Note that in this example the data and coordinates are generated using numpy.arange simply for the sake of having some numbers to play with. In practice it is likely the values would have been read from a file in some arbitrary format:

 import numpy
 import cf

#---------------------------------------------------------------------
 # 1. CREATE the field's domain items
 #---------------------------------------------------------------------
 # Create a grid_latitude dimension coordinate
 Y = cf.DimensionCoordinate(properties={'standard_name': 'grid_latitude'},
                            data=cf.Data(numpy.arange(10.), 'degrees'))

 # Create a grid_longitude dimension coordinate
 X = cf.DimensionCoordinate(data=cf.Data(numpy.arange(9.), 'degrees'))
 X.standard_name = 'grid_longitude'

 # Create a time dimension coordinate (with bounds)
 bounds = cf.Bounds(data=cf.Data([0.5, 1.5],
                                 cf.Units('days since 2000-1-1', calendar='noleap')))
 T = cf.DimensionCoordinate(properties=dict(standard_name='time'),
                            data=cf.Data(1, cf.Units('days since 2000-1-1',
                                                     calendar='noleap')),
                            bounds=bounds)

 # Create a longitude auxiliary coordinate
 lat = cf.AuxiliaryCoordinate(data=cf.Data(numpy.arange(90).reshape(10, 9),
                                           'degrees_north'))
 lat.standard_name = 'latitude'

 # Create a latitude auxiliary coordinate
 lon = cf.AuxiliaryCoordinate(properties=dict(standard_name='longitude'),
                              data=cf.Data(numpy.arange(1, 91).reshape(9, 10),
                                           'degrees_east'))

 # Create a rotated_latitude_longitude grid mapping coordinate reference
 grid_mapping = cf.CoordinateReference('rotated_latitude_longitude',
                                       parameters={
                                           'grid_north_pole_latitude': 38.0,
                                           'grid_north_pole_longitude': 190.0})

 #---------------------------------------------------------------------
 # 3. Create the field
 #---------------------------------------------------------------------
 # Create CF properties
 properties = {'standard_name': 'eastward_wind',
               'long_name'    : 'East Wind'}

 # Create the field's data array
 data = cf.Data(numpy.arange(90.).reshape(9, 10), 'm s-1')

 # Finally, create the field
 f = cf.Field(properties=properties)

 f.insert_cell_methods('latitude: point')

 f.insert_dim(T)
 f.insert_dim(X)
 f.insert_dim(Y)

 f.insert_aux(lat)
 f.insert_aux(lon)

 f.insert_ref(grid_mapping)

 f.insert_data(data)

 print_f = str(f)

 self.assertTrue(

 print f

Running this script produces the following output:

The new field:

Field: eastward_wind
--------------------
Data           : eastward_wind(grid_longitude(9), grid_latitude(10)) m s-1
Cell methods   : latitude: point
Axes           : time(1) = [2000-01-02T00:00:00Z] noleap
               : grid_longitude(9) = [0.0, ..., 8.0] degrees
               : grid_latitude(10) = [0.0, ..., 9.0] degrees
Aux coords     : latitude(grid_latitude(10), grid_longitude(9)) = [[0, ..., 89]] degrees_north
               : longitude(grid_longitude(9), grid_latitude(10)) = [[1, ..., 90]] degrees_east
Coord refs     : rotated_latitude_longitude

Example 5

Example 4 would be slightly more complicated if the grid_longitude and grid_latitude axes were to have the same size. In this case the field needs be told which axes, and in which order, are spanned by the two dimensional auxiliary coordinates (latitude and longitude) and the field needs to know which axes span the data array:

import numpy
import cf

import cf
import numpy

#---------------------------------------------------------------------
# 1. CREATE the field's domain items
#---------------------------------------------------------------------
# Create a grid_latitude dimension coordinate
Y = cf.DimensionCoordinate(properties={'standard_name': 'grid_latitude'},
                           data=cf.Data(numpy.arange(10.), 'degrees'))

# Create a grid_longitude dimension coordinate
X = cf.DimensionCoordinate(data=cf.Data(numpy.arange(10.), 'degrees'))
X.standard_name = 'grid_longitude'

# Create a time dimension coordinate (with bounds)
bounds = cf.Bounds(data=cf.Data([0.5, 1.5],
                                cf.Units('days since 2000-1-1', calendar='noleap')))
T = cf.DimensionCoordinate(properties=dict(standard_name='time'),
                           data=cf.Data(1, cf.Units('days since 2000-1-1',
                                                    calendar='noleap')),
                           bounds=bounds)

# Create a longitude auxiliary coordinate
lat = cf.AuxiliaryCoordinate(data=cf.Data(numpy.arange(100).reshape(10, 10),
                                          'degrees_north'))
lat.standard_name = 'latitude'

# Create a latitude auxiliary coordinate
lon = cf.AuxiliaryCoordinate(properties=dict(standard_name='longitude'),
                             data=cf.Data(numpy.arange(1, 101).reshape(10, 10),
                                          'degrees_east'))

# Create a rotated_latitude_longitude grid mapping coordinate reference
grid_mapping = cf.CoordinateReference('rotated_latitude_longitude',
                                      parameters={
                                          'grid_north_pole_latitude': 38.0,
                                          'grid_north_pole_longitude': 190.0})

#---------------------------------------------------------------------
# 3. Create the field
#---------------------------------------------------------------------
# Create CF properties
properties = {'standard_name': 'eastward_wind',
              'long_name'    : 'Eastward Wind'}

# Create the field's data array
data = cf.Data(numpy.arange(100.).reshape(10, 10), 'm s-1')

# Finally, create the field
f = cf.Field(properties=properties)

f.insert_cell_methods('latitude: point')

f.insert_dim(T)
f.insert_dim(X)
f.insert_dim(Y)

f.insert_aux(lat, axes=['Y', 'X'])
f.insert_aux(lon, axes=['X', 'Y'])

f.insert_ref(grid_mapping)

f.insert_data(data, axes=['Y', 'X'])

print f

Running this script produces the following output:

field: eastward_wind
--------------------
Data           : eastward_wind(grid_latitude(10), grid_longitude(10)) m s-1
Cell methods   : latitude: point
Axes           : time(1) = [2000-01-02T00:00:00Z] noleap
               : grid_latitude(10) = [0.0, ..., 9.0] degrees
               : grid_longitude(10) = [0.0, ..., 9.0] degrees
Aux coords     : latitude(grid_latitude(10), grid_longitude(10)) = [[0, ..., 99]] degrees_north
               : longitude(grid_longitude(10), grid_latitude(10)) = [[1, ..., 100]] degrees_east
Coord refs     : rotated_latitude_longitude