.. Currentmodule:: cfdm .. default-role:: obj .. _Tutorial: **cfdm tutorial** ================= ---- Version |release| for version |version| of the CF conventions. .. _Import: **Import** ---------- ---- The cfdm package is imported as follows: .. code-block:: python3 :caption: *Import the cfdm package.* >>> import cfdm .. _CF-version: **CF version** ^^^^^^^^^^^^^^ The version of the `CF conventions `_ and the :ref:`CF data model ` being used may be found with the `cfdm.CF` function: .. code-block:: python3 :caption: *Retrieve the version of the CF conventions.* >>> cfdm.CF() '1.7' This indicates which version of the CF conventions are represented by this release of the cfdm package, and therefore the version can not be changed. Note, however, that datasets of different versions may be :ref:`read ` from, or :ref:`written ` to, disk. .. _Reading-datasets: **Reading datasets** -------------------- ---- The `cfdm.read` function reads a `netCDF `_ file from disk, or from an `OPeNDAP `_ URL [#dap]_, and returns the contents as a list of zero or more `Field` class instances, each of which represents a field construct. (Henceforth, the phrase "field construct" will be assumed to mean "`Field` instance".) The list contains a field construct to represent each of the CF-netCDF data variables in the file. Datasets of any version of CF up to and including CF-|version| can be read. All formats of netCDF3 and netCDF4 files can be read. For example, to read the file ``file.nc`` (:download:`download `, 9kB) [#files]_, which contains two field constructs: .. code-block:: python3 :caption: *Read file.nc and show that the result is a two-element list.* >>> x = cfdm.read('file.nc') >>> print(type(x)) >>> len(x) 2 Descriptive properties are always read into memory, but `lazy loading `_ is employed for all data arrays, which means that no data is read into memory until the data is required for inspection or to modify the array contents. This maximises the number of field constructs that may be read within a session, and makes the read operation fast. The `cfdm.read` function has optional parameters to * allow the user to provide files that contain :ref:`external variables `; * request :ref:`extra field constructs to be created from "metadata" netCDF variables `, i.e. those that are referenced from CF-netCDF data variables, but which are not regarded by default as data variables in their own right; and * display information and warnings about the mapping of the netCDF file contents to CF data model constructs. .. _CF-compliance: **CF-compliance** ^^^^^^^^^^^^^^^^^ If the dataset is partially CF-compliant to the extent that it is not possible to unambiguously map an element of the netCDF dataset to an element of the CF data model, then a field construct is still returned, but may be incomplete. This is so that datasets which are partially conformant may nonetheless be modified in memory and written to new datasets. Such "structural" non-compliance would occur, for example, if the "coordinates" attribute of a CF-netCDF data variable refers to another variable that does not exist, or refers to a variable that spans a netCDF dimension that does not apply to the data variable. Other types of non-compliance are not checked, such whether or not controlled vocabularies have been adhered to. The structural compliance of the dataset may be checked with the `~cfdm.Field.dataset_compliance` method of the field construct, as well as optionally displayed when the dataset is read. .. _Inspection: **Inspection** -------------- ---- The contents of a field construct may be inspected at three different levels of detail. .. _Minimal-detail: **Minimal detail** ^^^^^^^^^^^^^^^^^^ The built-in `repr` function returns a short, one-line description: .. code-block:: python3 :caption: *Inspect the contents of the two field constructs from the dataset and create a Python variable for each of them.* >>> x [, ] >>> q = x[0] >>> t = x[1] >>> q This gives the identity of the field construct (e.g. "specific_humidity"), the identities and sizes of the dimensions spanned by the data array ("latitude" and "longitude" with sizes 5 and 8 respectively) and the units of the data ("1"). .. _Medium-detail: **Medium detail** ^^^^^^^^^^^^^^^^^ The built-in `str` function returns similar information as the one-line output, along with short descriptions of the metadata constructs, which include the first and last values of their data arrays: .. code-block:: python3 :caption: *Inspect the contents of the two field constructs with medium detail.* >>> print(q) Field: specific_humidity (ncvar%q) ---------------------------------- Data : specific_humidity(latitude(5), longitude(8)) 1 Cell methods : area: mean Dimension coords: time(1) = [2019-01-01 00:00:00] : latitude(5) = [-75.0, ..., 75.0] degrees_north : longitude(8) = [22.5, ..., 337.5] degrees_east >>> 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.81, ..., 0.78]] K Dimension coords: time(1) = [2019-01-01 00:00:00] : atmosphere_hybrid_height_coordinate(1) = [1.5] : grid_latitude(10) = [2.2, ..., -1.76] degrees : grid_longitude(9) = [-4.7, ..., -1.18] degrees 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 Note that :ref:`time values