Incompatible differences between versions 1.x and 2.x¶
For those familiar with the cf-python API at version 1.x, some important, backwards incompatible changes were introduced at version 2.0.
Some of these changes could break code written at version 1.x, causing an exception to be raised. For others, those marked with a warning, version 1.x may work but could produce scientifically different results.
All of the changes have been designed to make the interface more consistent and intuitive to use and were introduced at version 2.0 to coincide with the updated CF data model structure.
attributes¶
Note
At version 2.x cf.Field.attributes
is callable and allows
the attributes to be updated inplace.
>>> cf.__version__
2.0
>>> f.attributes()
{'ncvar': 'tas'}
At version 1.x it wasn’t callable and returned a dict
copy of the
attributes.
axes¶
Note
At version 2.x cf.Field.axes
returns, by default, a
dict
. If the ordered
parameter is True
then
it returns an OrderedDict
.
>>> cf.__version__
2.0
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> f.axes()
{'dim0': <CF DomainAxis: 12>,
'dim1': <CF DomainAxis: 64>,
'dim2': <CF DomainAxis: 128>,
'dim3': <CF DomainAxis: 1>}
>>> f.axes(ordered=True)
OrderedDict([('dim3', <CF DomainAxis: 1>),
('dim0', <CF DomainAxis: 12>),
('dim1', <CF DomainAxis: 64>),
('dim2', <CF DomainAxis: 128>)])
At version 1.x it returned a set
by default or, if the ordered
parameter was True
, it returned a list
.
axis¶
Note
At version 2.x cf.Field.axis
returns, by default, a
cf.DomainAxis
object. A domain axis identifier (such as
“dim2”) may be returned by setting the key
parameter to
True
.
>>> cf.__version__
2.0
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> f.axis('X')
<CF DomainAxis: 128>
>>> f.axis('X', key=True)
'dim2'
At version 1.x it always returned a domain axis identifier.
bounds¶
Warning
Running code written at version 1.x with the version 2.x library could produce scientifically different results.
Note
At version 2.x performing arithmetic on coordinates also modifies the coordinate bounds, if present.
>>> cf.__version__
2.0
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> t = f.coord('T')
>>> print t.array[0], t.bounds.array[0]
164569.0 [ 164554. 164584.]
>>> t -= 1000000
>>> print t.array[0], t.bounds.array[0]
-835431.0 [-835446. -835416.]
If the bounds are not to be changed, just the coordinate values, then the arithmetic may be applied to the coordinate object’s data array.
>>> t.data += 1000000
>>> print t.array[0], t.bounds.array[0]
164569.0 [-835446. -835416.]
At version 1.x performing arithmetic on coordinates did not modify the coordinate bounds - they had to be modified seperately.
collapse¶
Warning
Running code written at version 1.x with the version 2.x library could produce scientifically different results.
Note
At version 2.x cf.Field.collapse
does not, by default,
weight the calculations, i.e. the weights
parameter
defaults to None
.
>>> cf.__version__
2.0
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> g = f.collapse('mean')
>>> g.datum()
279.1922
>>> g = f.collapse('mean', weights=None)
>>> g.datum()
279.1922
Non-equal weighting has to be specifically requested with
the weights
parameter.
>>> h = f.collapse('mean', axes=['X', 'Y', 'T'], weights=['T', 'area'])
>>> h.datum()
288.6733
At version 1.x the weights
parameter defaulted to 'auto'
,
meaning that calculations were were weighted according to metadata
present in the field.
dump¶
Note
At version 2.x the output of cf.Field.dump
has been
reformatted.
FieldList¶
Warning
Running code written at version 1.x with the version 2.x library could produce scientifically different results.
Note
At version 2.x cf.FieldList
is not a subclass of
cf.Field
, therefore cf.FieldList
does not inherit any
methods from cf.Field
.
>>> cf.__version__
2.0
>>> fl
[<CF Field: specific_humidity(latitude(73), longitude(96)) K>,
<CF Field: air_pressure(height(17), latitude(145), longitude(196)) K>]
>>> isinstance(fl, cf.Field)
False
>>> gl = fl.collapse('mean')
DeprecationError: collapse method has been removed from a field list. Use on individual fields.
>>> gl = cf.FieldList([f.collapse('mean') for f in fl])
At version 1.x cf.FieldList
was a subclass of cf.Field
and
inherited all of the methods that returned a cf.Field
when used on a
field (such as collapse
and squeeze
).
read¶
Note
At version 2.x cf.read
always returns a cf.FieldList
.
>>> cf.__version__
2.0
>>> fl = cf.read('file[12].nc')
>>> fl
[<CF Field: specific_humidity(latitude(73), longitude(96)) K>,
<CF Field: air_pressure(height(17), latitude(145), longitude(196)) K>]
>>> fl = cf.read('file3.nc')
>>> fl
[<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>]
The new function cf.read_field
will always return a cf.Field
if there is only one identified in the input file(s).
>>> f = cf.read_field('file3.nc')
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
At version 1.x cf.read
returned a cf.Field
if only one field was
found in the input files(s), otherwise it returned a cf.FieldList
.
regridc¶
Note
At version 2.x cf.Field.regridc
the regridding method must
be specified. The method
parameter does not have an
'auto'
option.
>>> cf.__version__
2.0
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> g
<CF Field: specific_humidity(time(360), latitude(73), longitude(96)) K>
>>> h = f.regridc(g, 'time', 'nearest_stod')
>>> h
<CF Field: air_temperature(time(360), latitude(64), longitude(128)) K>
At version 1.x the regridding method defaulted to 'auto'
, meaning
that the method was inferred according to metadata present in the
field.
regrids¶
Note
At version 2.x cf.Field.regrids
the regridding method must
be specified. The method
parameter does not have an
'auto'
option.
>>> cf.__version__
2.0
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> g
<CF Field: specific_humidity(time(360), latitude(73), longitude(96)) K>
>>> h = f.regrids(g, 'conservative')
>>> h
<CF Field: air_temperature(time(12), latitude(73), longitude(96)) K>
At version 1.x the regridding method defaulted to 'auto'
, meaning
that the method was inferred according to metadata present in the
field.
properties¶
Note
At version 2.x cf.Field.properties
is callable and allows
the CF properties to be updated inplace.
>>> cf.__version__
2.0
>>> f.properties()
{'Conventions': 'CF-1.6',
'experiment_id': 'pre-industrial control experiment',
'project_id': 'IPCC Fourth Assessment',
'realization': 1,
'standard_name': 'air_temperature',
'title': 'model output prepared for IPCC AR4'}
At version 1.x it wasn’t callable and returned a dict
copy of the
CF properties.
select¶
Note
At version 2.x cf.Field.select
has been removed. Use
cf.Field.match
to see if an individual field meets given
criteria.
>>> cf.__version__
2.0
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> f.match('air_temperature')
True
cf.FieldList.select
always returns another field list.
>>> fl
[<CF Field: specific_humidity(latitude(73), longitude(96)) K>,
<CF Field: air_pressure(height(17), latitude(145), longitude(196)) K>]
>>> fl.select('specific_humidity|air_pressure')
[<CF Field: specific_humidity(latitude(73), longitude(96)) K>,
<CF Field: air_pressure(height(17), latitude(145), longitude(196)) K>]
>>> fl.select('specific_humidity')
[<CF Field: specific_humidity(latitude(73), longitude(96)) K>]
>>> fl.select('ocean_meridional_overturning_streamfunction')
[]
The new method cf.FieldList.select_field
will always return a
cf.Field
if there is only one identified in the field
list.
>>> fl.select_field('specific_humidity')
<CF Field: specific_humidity(latitude(73), longitude(96)) K>
At version 1.x cf.FieldList.select
returned a cf.Field
if only one
field element was found in the field list, otherwise it returned a
cf.FieldList
. cf.Field.select
either returned the field itself or
an empty cf.FieldList
.
Indexing a field¶
Warning
Running code written at version 1.x with the version 2.x library could produce scientifically different results.
Note
At version 2.x indexing on a field object returns a subspace
of the field, in exactly the way that indexing the
cf.Field.subspace
attribute does.
>>> cf.__version__
2.0
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> g = f[::-2, 0, 28:]
>>> g
<CF Field: air_temperature(time(6), latitude(1), longitude(100)) K>
>>> h = f.subspace[::-2, 0, 28:]
>>> h
<CF Field: air_temperature(time(6), latitude(1), longitude(100)) K>
>>> g.equals(h)
True
>>> f.equals(f[0])
False
Assignment to a subspace of the data array may either be
done to a subspace defined by direct indexing or to one
defined by indexing the cf.Field.subspace
attribute.
>>> g = f.copy()
>>> g[0] = -99
>>> h = f.copy()
>>> h.subspace[0] = -99
>>> g.equals(h)
True
At version 1.x direct indexing on a field returned the field itself, with no subspacing.
>>> cf.__version__
1.5
>>> f
<CF Field: air_temperature(time(12), latitude(64), longitude(128)) K>
>>> f.equals(f[0])
True