Subclassing¶
Version 1.7.8 for version 1.7 of the CF conventions.
Creating a new implementation of the CF data model by subclassing cfdm classes is straight forward. For example:
Create a new implementation with a new field construct
class.¶
import cfdm
class my_Field(cfdm.Field):
def info(self):
return 'I am a {!r} instance'.format(self.__class__.__name__)
f = my_Field()
f.set_property('standard_name', 'air_pressure')
It is also possible use cfdm.read
to read a dataset into field
constructs defined by the new implementation, and cfdm.write
to
write to disk field constructs defined by the new implementation. For
example:
Encapsulate the new implementation in a
CFDMImplementation class instance and define new read and
write functions that pass the new implementation to the the
appropriate cfdm function.¶
import functools
# Define an implementation that is the same as cfdm, but with the
# my_Field class to represent field constructs
my_implementation = cfdm.implementation()
my_implementation.set_class('Field', my_Field)
# Define a new function that reads a dataset and returns field
# constructs in my_Field instances
my_read = functools.partial(cfdm.read,
_implementation=my_implementation)
# Define a new function that writes my_Field instances to disk
my_write = functools.partial(cfdm.write,
_implementation=my_implementation)
# Read the dataset file.nc, as used in the tutorial
q, t = my_read('file.nc')
# Write the new field constructs to disk
my_write([q, t], 'new_file.nc')
Inspect a field construct read from the dataset,
demonstrating that it is a my_Field instance from the
new implementation that has the inherited functionality
of a cfdm.Field instance.¶
>>> print(type(t))
<class '__main__.my_Field'>
>>> print(t.info())
I am a 'my_Field' instance
>>> print(t)
Field: air_temperature (ncvar%ta)
---------------------------------
Data : air_temperature(atmosphere_hybrid_height_coordinate(1), grid_latitude(10), grid_longitude(9)) K
Cell methods : grid_latitude(10): grid_longitude(9): mean where land (interval: 0.1 degrees) time(1): maximum
Field ancils : air_temperature standard_error(grid_latitude(10), grid_longitude(9)) = [[0.76, ..., 0.32]] K
Dimension coords: atmosphere_hybrid_height_coordinate(1) = [1.5]
: grid_latitude(10) = [2.2, ..., -1.76] degrees
: grid_longitude(9) = [-4.7, ..., -1.18] degrees
: time(1) = [2019-01-01 00:00:00]
Auxiliary coords: latitude(grid_latitude(10), grid_longitude(9)) = [[53.941, ..., 50.225]] degrees_N
: longitude(grid_longitude(9), grid_latitude(10)) = [[2.004, ..., 8.156]] degrees_E
: long_name:Grid latitude name(grid_latitude(10)) = [--, ..., kappa]
Cell measures : measure%area(grid_longitude(9), grid_latitude(10)) = [[2391.9657, ..., 2392.6009]] km2
Coord references: atmosphere_hybrid_height_coordinate
: rotated_latitude_longitude
Domain ancils : ncvar%a(atmosphere_hybrid_height_coordinate(1)) = [10.0] m
: ncvar%b(atmosphere_hybrid_height_coordinate(1)) = [20.0]
: surface_altitude(grid_latitude(10), grid_longitude(9)) = [[0.0, ..., 270.0]] m
>>> print(t.data.array)
[[[262.8 270.5 279.8 269.5 260.9 265.0 263.5 278.9 269.2]
[272.7 268.4 279.5 278.9 263.8 263.3 274.2 265.7 279.5]
[269.7 279.1 273.4 274.2 279.6 270.2 280.0 272.5 263.7]
[261.7 260.6 270.8 260.3 265.6 279.4 276.9 267.6 260.6]
[264.2 275.9 262.5 264.9 264.7 270.2 270.4 268.6 275.3]
[263.9 263.8 272.1 263.7 272.2 264.2 260.0 263.5 270.2]
[273.8 273.1 268.5 272.3 264.3 278.7 270.6 273.0 270.6]
[267.9 273.5 279.8 260.3 261.2 275.3 271.2 260.8 268.9]
[270.9 278.7 273.2 261.7 271.6 265.8 273.0 278.5 266.4]
[276.4 264.2 276.3 266.1 276.1 268.1 277.0 273.4 269.7]]]
Customisation of the actual functionality used by cfdm.read
and
cfdm.write
is possible by subclassing the CFDMImplementation
,
NetCDFRead
and NetCDFWrite
classes.