The cf package allows a data array and its associated metadata to be contained and manipulated as a single entity called a field, which is stored in a Field object.
Much of the basic field manipulation syntax can be seen in this simple read-modify-write example which:
- Reads a field from a file on disk and find out information about it.
- Modifies a CF property and the units of its data.
- Modifies the data values.
- Modifies a subspace of the data values.
- Writes it out to another file on disk.
The example may be reproduced by downloading the sample netCDF file (file.nc) (taking care not to overwrite an existing file with that name).
1. Import the cf package.
>>> import cf
2. Read a field from disk and find a summary of its contents.
>>> f = cf.read('file.nc')[0]
>>> type(f)
<class 'cf.field.Field'>
>>> f
<CF Field: air_temperature(4, 5)>
>>> print f
Data : air_temperature(latitude, longitude)
Cell methods : time: mean
Dimensions : time(1) = [15] days since 2000-1-1
: latitude(4) = [-2.5, ..., 5] degrees_north
: longitude(5) = [0, ..., 15] degrees_east
: height(1) = [2] m
Auxiliary coords:
3. Find all of the field’s CF properties and its data array as a masked numpy array.
>>> f.properties
{'Conventions': 'CF-1.0',
'_FillValue': 1e+20,
'cell_methods': <CF CellMethods: time: mean>,
'experiment_id': 'stabilization experiment (SRES A1B)',
'long_name': 'Air Temperature',
'standard_name': 'air_temperature',
'title': 'SRES A1B',
'units': 'K'}
>>> f.array
masked_array(data =
[[ 274.15, 276.15, 275.15, 277.15, 278.15],
[ 274.15, 275.15, 276.15, 277.15, 276.15],
[ 277.15, 275.15, 278.15, 274.15, 278.15],
[ 276.15, 274.15, 275.15, 277.15, 274.15]],
mask = False,
fill_value = 1e+20)
4.. Modify the field’s long name CF property and change the field’s data from units of Kelvin to Celsius.
Note
Changing the units automatically changes the data when it is next accessed.
>>> f.long_name
'Air Temperature'
>>> f.long_name = 'Surface Air Temperature'
>>> f.long_name
'Surface Air Temperature'
>>> f.Units -= 273.15
>>> f.units
'K @ 273.15'
>>> f.array
masked_array(data =
[[ 1. 3. 2. 4. 5.]
[ 1. 2. 3. 4. 3.]
[ 4. 2. 5. 1. 5.]
[ 3. 1. 2. 4. 1.]],
mask = False,
fill_value = 1e+20)
5. Check that the field has ‘temperature’ in its standard name and that at least one of its longitude coordinate values is greater than 0.0.
>>> f.match(prop ={'standard_name': '.*temperature.*'},
coord={'longitude' : cf.gt(0)})
True
6. Modify the data values.
>>> g = f + 100
>>> g.array
masked_array(data =
[[ 101. 103. 102. 104. 105.]
[ 101. 102. 103. 104. 103.]
[ 104. 102. 105. 101. 105.]
[ 103. 101. 102. 104. 101.]],
mask = False,
fill_value = 1e+20)
>>> g = f + f
>>> g.array
masked_array(data =
[[ 2. 6. 4. 8. 10.]
[ 2. 4. 6. 8. 6.]
[ 8. 4. 10. 2. 10.]
[ 6. 2. 4. 8. 2.]],
mask = False,
fill_value = 1e+20)
>>> g = f / cf.Data(2, 'seconds')
>>> g.array
masked_array(data =
[[0.5 1.5 1.0 2.0 2.5]
[0.5 1.0 1.5 2.0 1.5]
[2.0 1.0 2.5 0.5 2.5]
[1.5 0.5 1.0 2.0 0.5]],
mask = False,
fill_value = 1e+20)
>>> g.Units
<CF Units: s-1.K>
7. Access and modify a subspace of the data values.
>>> g = f.subspace[0::2, 2:4]
>>> g.array
masked_array(data =
[[ 2. 4.]
[ 5. 1.]],
mask = False,
fill_value = 1e+20)
>>> f.subspace[0::2, ...] = -10
>>> f.array
masked_array(data =
[[-10. -10. -10. -10. -10.]
[ 1. 2. 3. 4. 3.]
[-10. -10. -10. -10. -10.]
[ 3. 1. 2. 4. 1.]],
mask = False,
fill_value = 1e+20)
8. Write the modified field to disk.
>>> cf.write(f, 'newfile.nc')