|
|
|||
|
||||
8 Attributes
Attributes may be associated with each netCDF variable to specify such properties as units, special values, maximum and minimum valid values, scaling factors, and offsets. Attributes for a netCDF dataset are defined when the dataset is first created, while the netCDF dataset is in define mode. Additional attributes may be added later by reentering define mode. A netCDF attribute has a netCDF variable to which it is assigned, a name, a type, a length, and a sequence of one or more values. An attribute is designated by its variable ID and name. When an attribute name is not known, it may be designated by its variable ID and number in order to determine its name, using the function NF90_INQ_ATTNAME.
The attributes associated with a variable are typically defined immediately after the variable is created, while still in define mode. The data type, length, and value of an attribute may be changed even when in data mode, as long as the changed attribute requires no more space than the attribute as originally defined.
It is also possible to have attributes that are not associated with any variable. These are called global attributes and are identified by using NF90_GLOBAL as a variable pseudo-ID. Global attributes are usually related to the netCDF dataset as a whole and may be used for purposes such as providing a title or processing history for a netCDF dataset.
Operations supported on attributes are:
- Create an attribute, given its variable ID, name, data type, length, and value.
- Get attribute's data type and length from its variable ID and name.
- Get attribute's value from its variable ID and name.
- Copy attribute from one netCDF variable to another.
- Get name of attribute from its number.
- Rename an attribute.
- Delete an attribute.
8.1 Attribute Conventions
Names commencing with underscore (`_') are reserved for use by the netCDF library. Most generic applications that process netCDF datasets assume standard attribute conventions and it is strongly recommended that these be followed unless there are good reasons for not doing so. Below we list the names and meanings of recommended standard attributes that have proven useful. Note that some of these (e.g. units, valid_range, scale_factor) assume numeric data and should not be used with character data.
units A character string that specifies the units used for the variable's data. Unidata has developed a freely-available library of routines to convert between character string and binary forms of unit specifications and to perform various useful operations on the binary forms. This library is used in some netCDF applications. Using the recommended units syntax permits data represented in conformable units to be automatically converted to common units for arithmetic operations. See Appendix A "Units," page 103, for more information. long_name A long descriptive name. This could be used for labeling plots, for example. If a variable has no long_name attribute assigned, the variable name should be used as a default. valid_min A scalar specifying the minimum valid value for this variable. valid_max A scalar specifying the maximum valid value for this variable. valid_rangeA vector of two numbers specifying the minimum and maximum valid values for this variable, equivalent to specifying values for both valid_min and valid_max attributes. Any of these attributes define the valid range. The attribute valid_range must not be defined if either valid_min or valid_max is defined.
Generic applications should treat values outside the valid range as missing. The type of each valid_range, valid_min and valid_max attribute should match the type of its variable (except that for byte data, these can be of a signed integral type to specify the intended range).
If neither valid_min, valid_max nor valid_range is defined then generic applications should define a valid range as follows. If the data type is byte and _FillValue is not explicitly defined, then the valid range should include all possible values. Otherwise, the valid range should exclude the _FillValue (whether defined explicitly or by default) as follows. If the _FillValue is positive then it defines a valid maximum, otherwise it defines a valid minimum. For integer types, there should be a difference of 1 between the _FillValue and this valid minimum or maximum. For floating point types, the difference should be twice the minimum possible (1 in the least significant bit) to allow for rounding error.
scale_factor If present for a variable, the data are to be multiplied by this factor after the data are read by the application that accesses the data. add_offsetIf present for a variable, this number is to be added to the data after it is read by the application that accesses the data. If both scale_factor and add_offset attributes are present, the data are first scaled before the offset is added. The attributes scale_factor and add_offset can be used together to provide simple data compression to store low-resolution floating-point data as small integers in a netCDF dataset. When scaled data are written, the application should first subtract the offset and then divide by the scale factor.
When scale_factor and add_offset are used for packing, the associated variable (containing the packed data) is typically of type byte or short, whereas the unpacked values are intended to be of type float or double. The attributes scale_factor and add_offset should both be of the type intended for the unpacked data, e.g. float or double.
_FillValueThe _FillValue attribute specifies the fill value used to pre-fill disk space allocated to the variable. Such pre-fill occurs unless nofill mode is set using NF90_SET_FILL. See Section 5.12 "Set Fill Mode for Writes: NF90_SET_FILL," page 41, for details. The fill value is returned when reading values that were never written. If _FillValue is defined then it should be scalar and of the same type as the variable. It is not necessary to define your own _FillValue attribute for a variable if the default fill value for the type of the variable is adequate. However, use of the default fill value for data type byte is not recommended. Note that if you change the value of this attribute, the changed value applies only to subsequent writes; previously written data are not changed.
Generic applications often need to write a value to represent undefined or missing values. The fill value provides an appropriate value for this purpose because it is normally outside the valid range and therefore treated as missing when read by generic applications. It is legal (but not recommended) for the fill value to be within the valid range.
See Section 7.8 "Fill Values," page 67, for more information.
missing_value This attribute is not treated in any special way by the library or conforming generic applications, but is often useful documentation and may be used by specific applications. The missing_value attribute can be a scalar or vector containing values indicating missing data. These values should all be outside the valid range so that generic applications will treat them as missing. signedness Deprecated attribute, originally designed to indicate whether byte values should be treated as signed or unsigned. The attributes valid_min and valid_max may be used for this purpose. For example, if you intend that a byte variable store only nonnegative values, you can use valid_min = 0 and valid_max = 255. This attribute is ignored by the netCDF library. FORTRAN_format A character array providing the format that should be used by FORTRAN or Fortran 90 applications to print values for this variable. For example, if you know a variable is only accurate to three significant digits, it would be appropriate to define the FORTRAN_format attribute as "(G10.3)". title A global attribute that is a character array providing a succinct description of what is in the dataset. history A global attribute for an audit trail. This is a character array with a line for each invocation of a program that has modified the dataset. Well-behaved generic netCDF applications should append a line containing: date, time of day, user name, program name and command arguments. ConventionsIf present, `Conventions' is a global attribute that is a character array for the name of the conventions followed by the dataset, in the form of a string that is interpreted as a directory name relative to a directory that is a repository of documents describing sets of discipline-specific conventions. This permits a hierarchical structure for conventions and provides a place where descriptions and examples of the conventions may be maintained by the defining institutions and groups. The conventions directory name is currently interpreted relative to the directory pub/netcdf/Conventions/ on the host machine ftp.unidata.ucar.edu. Alternatively, a full URL specification may be used to name a WWW site where documents that describe the conventions are maintained.
For example, if a group named NUWG agrees upon a set of conventions for dimension names, variable names, required attributes, and netCDF representations for certain discipline-specific data structures, they may store a document describing the agreed-upon conventions in a dataset in the NUWG/ subdirectory of the Conventions directory. Datasets that followed these conventions would contain a global Conventions attribute with value "NUWG".
Later, if the group agrees upon some additional conventions for a specific subset of NUWG data, for example time series data, the description of the additional conventions might be stored in the NUWG/Time_series/ subdirectory, and datasets that adhered to these additional conventions would use the global Conventions attribute with value "NUWG/Time_series", implying that this dataset adheres to the NUWG conventions and also to the additional NUWG time-series conventions.
8.2 Create an Attribute: NF90_PUT_ATT
The function NF90_PUT_ATTadds or changes a variable attribute or global attribute of an open netCDF dataset. If this attribute is new, or if the space required to store the attribute is greater than before, the netCDF dataset must be in define mode.
Usage
Although it's possible to create attributes of all types, text and double attributes are adequate for most purposes.
function nf90_put_att(ncid, varid, name, values) integer, intent( in) :: ncid, varid character(len = *), intent( in) :: name any valid type, scalar or array of rank 1, & intent( in) :: values integer :: nf90_put_attErrors
NF90_PUT_ATT returns the value NF90_NOERR if no errors occurred. Otherwise, the returned status indicates an error. Possible causes of errors include:
- The variable ID is invalid for the specified netCDF dataset.
- The specified netCDF type is invalid.
- The specified length is negative.
- The specified open netCDF dataset is in data mode and the specified attribute would expand.
- The specified open netCDF dataset is in data mode and the specified attribute does not already exist.
- The specified netCDF ID does not refer to an open netCDF dataset.
- The number of attributes for this variable exceeds NF90_MAX_ATTRS
Example
Here is an example using NF90_PUT_ATT to add a variable attribute named valid_range for a netCDF variable named rh and a global attribute named title to an existing netCDF dataset named foo.nc:
use netcdf implicit none integer :: ncid, status, RHVarID ... status = nf90_open("foo.nc", nf90_write, ncid) if (status /= nf90_noerr) call handle_err(status) ... ! Enter define mode so we can add the attribute status = nf90_redef(ncid) if (status /= nf90_noerr) call handle_err(status) ! Get the variable ID for "rh"... status = nf90_inq_varid(ncid, "rh", RHVarID) if (status /= nf90_noerr) call handle_err(status) ! ... put the range attribute, setting it to eight byte reals... status = nf90_put_att(ncid, RHVarID, "valid_range", real((/ 0, 100 /)) ! ... and the title attribute. if (status /= nf90_noerr) call handle_err(status) status = nf90_put_att(ncid, RHVarID, "title", "example netCDF dataset") ) if (status /= nf90_noerr) call handle_err(status) ! Leave define mode status = nf90_enddef(ncid) if (status /= nf90_noerr) call handle_err(status)8.3 Get Information about an Attribute: NF90_Inquire_Att and NF90_INQ_ATTNAME
The function NF90_Inquire_att returns information about a netCDF attribute given the variable ID and attribute name. Information about an attribute includes its type, length, name, and number. See NF90_GET_ATT for getting attribute values.
The function NF90_INQ_ATTNAME gets the name of an attribute, given its variable ID and number. This function is useful in generic applications that need to get the names of all the attributes associated with a variable, since attributes are accessed by name rather than number in all other attribute functions. The number of an attribute is more volatile than the name, since it can change when other attributes of the same variable are deleted. This is why an attribute number is not called an attribute ID.
Usage
function nf90_Inquire_Attribute(ncid, varid, name, xtype, len, attnum) integer, intent( in) :: ncid, varid character (len = *), intent( in) :: name integer, intent(out), optional :: xtype, len, attnum integer :: nf90_Inquire_Attribute function nf90_inq_attname(ncid, varid, attnum, name) integer, intent( in) :: ncid, varid, attnum character (len = *), intent(out) :: name integer :: nf90_inq_attnameErrors
Each function returns the value NF90_NOERR if no errors occurred. Otherwise, the returned status indicates an error. Possible causes of errors include:
- The variable ID is invalid for the specified netCDF dataset.
- The specified attribute does not exist.
- The specified netCDF ID does not refer to an open netCDF dataset.
- For NF90_INQ_ATTNAME, the specified attribute number is negative or more than the number of attributes defined for the specified variable.
Example
Here is an example using NF90_Inquire_Att to inquire about the lengths of an attribute named valid_range for a netCDF variable named rh and a global attribute named title in an existing netCDF dataset named foo.nc:
use netcdf implicit none integer :: ncid, status integer :: RHVarID ! Variable ID integer :: validRangeLength, titleLength ! Attribute lengths ... status = nf90_open("foo.nc", nf90_nowrite, ncid) if (status /= nf90_noerr) call handle_err(status) ... ! Get the variable ID for "rh"... status = nf90_inq_varid(ncid, "rh", RHVarID) if (status /= nf90_noerr) call handle_err(status) ! ... get the length of the "valid_range" attribute... status = nf90_Inquire_Att(ncid, RHVarID, "valid_range", & len = validRangeLength) if (status /= nf90_noerr) call handle_err(status) ! ... and the global title attribute. status = nf90_Inquire_Att(ncid, nf90_global, "title", len = titleLength) if (status /= nf90_noerr) call handle_err(status)8.4 Get Attribute's Values: NF90_GET_ATT
Function nf90_get_att gets the value(s) of a netCDF attribute, given its variable ID and name.
Usage
function nf90_get_att(ncid, varid, name, values) integer, intent( in) :: ncid, varid character(len = *), intent( in) :: name any valid type, scalar or array of rank 1, & intent(out) :: values integer :: nf90_get_attErrors
NF90_GET_ATT returns the value NF90_NOERR if no errors occurred. Otherwise, the returned status indicates an error. Possible causes of errors include:
- The variable ID is invalid for the specified netCDF dataset.
- The specified attribute does not exist.
- The specified netCDF ID does not refer to an open netCDF dataset.
- One or more of the attribute values are out of the range of values representable by the desired type.
Example
Here is an example using NF90_GET_ATT to determine the values of an attribute named valid_range for a netCDF variable named rh and a global attribute named title in an existing netCDF dataset named foo.nc. In this example, it is assumed that we don't know how many values will be returned, so we first inquire about the length of the attributes to make sure we have enough space to store them:
use netcdf implicit none integer :: ncid, status integer :: RHVarID ! Variable ID integer :: validRangeLength, titleLength ! Attribute lengths real, dimension(:), allocatable, & :: validRange character (len = 80) :: title ... status = nf90_open("foo.nc", nf90_nowrite, ncid) if (status /= nf90_noerr) call handle_err(status) ... ! Find the lengths of the attributes status = nf90_inq_varid(ncid, "rh", RHVarID) if (status /= nf90_noerr) call handle_err(status) status = nf90_Inquire_Att(ncid, RHVarID, "valid_range", & len = validRangeLength) if (status /= nf90_noerr) call handle_err(status) status = nf90_Inquire_Att(ncid, nf90_global, "title", len = titleLength) if (status /= nf90_noerr) call handle_err(status) ... !Allocate space to hold attribute values, check string lengths allocate(validRange(validRangeLength), stat = status) if(status /= 0 .or. len(title) < titleLength) print *, "Not enough space to put attribute values." exit end if ! Read the attributes. status = nf90_get_att(ncid, RHVarID, "valid_range", validRange) if (status /= nf90_noerr) call handle_err(status) status = nf90_get_att(ncid, nf90_global, "title", title) if (status /= nf90_noerr) call handle_err(status)8.5 Copy Attribute from One NetCDF to Another: NF90_COPY_ATT
The function NF90_COPY_ATT copies an attribute from one open netCDF dataset to another. It can also be used to copy an attribute from one variable to another within the same netCDF.
Usage
function nf90_copy_att(ncid_in, varid_in, name, ncid_out, varid_out) integer, intent( in) :: ncid_in, varid_in character (len = *), intent( in) :: name integer, intent( in) :: ncid_out, varid_out integer :: nf90_copy_attErrors
NF90_COPY_ATT returns the value NF90_NOERR if no errors occurred. Otherwise, the returned status indicates an error. Possible causes of errors include:
- The input or output variable ID is invalid for the specified netCDF dataset.
- The specified attribute does not exist.
- The output netCDF is not in define mode and the attribute is new for the output dataset is larger than the existing attribute.
- The input or output netCDF ID does not refer to an open netCDF dataset.
Example
Here is an example using NF90_COPY_ATT to copy the variable attribute units from the variable rh in an existing netCDF dataset named foo.nc to the variable avgrh in another existing netCDF dataset named bar.nc, assuming that the variable avgrh already exists, but does not yet have a units attribute:
use netcdf implicit none integer :: ncid1, ncid2, status integer :: RHVarID, avgRHVarID ! Variable ID ... status = nf90_open("foo.nc", nf90_nowrite, ncid1) if (status /= nf90_noerr) call handle_err(status) status = nf90_open("bar.nc", nf90_write, ncid2) if (status /= nf90_noerr) call handle_err(status) ... ! Find the IDs of the variables status = nf90_inq_varid(ncid1, "rh", RHVarID) if (status /= nf90_noerr) call handle_err(status) status = nf90_inq_varid(ncid1, "avgrh", avgRHVarID) if (status /= nf90_noerr) call handle_err(status) ... status = nf90_redef(ncid2) ! Enter define mode if (status /= nf90_noerr) call handle_err(status) ! Copy variable attribute from "rh" in file 1 to "avgrh" in file 1 status = nf90_copy_att(ncid1, RHVarID, "units", ncid2, avgRHVarID) if (status /= nf90_noerr) call handle_err(status) status = nf90_enddef(ncid2) if (status /= nf90_noerr) call handle_err(status)8.6 Rename an Attribute: NF90_RENAME_ATT
The function NF90_RENAME_ATT changes the name of an attribute. If the new name is longer than the original name, the netCDF dataset must be in define mode. You cannot rename an attribute to have the same name as another attribute of the same variable.
function nf90_rename_att(ncid, varid, curname, newname) integer, intent( in) :: ncid, varid character (len = *), intent( in) :: curname, newname integer :: nf90_rename_attErrors
NF90_RENAME_ATT returns the value NF90_NOERR if no errors occurred. Otherwise, the returned status indicates an error. Possible causes of errors include:
- The specified variable ID is not valid.
- The new attribute name is already in use for another attribute of the specified variable.
- The specified netCDF dataset is in data mode and the new name is longer than the old name.
- The specified attribute does not exist.
- The specified netCDF ID does not refer to an open netCDF dataset.
Example
Here is an example using NF90_RENAME_ATT to rename the variable attribute units to Units for a variable rh in an existing netCDF dataset named foo.nc:
use netcdf implicit none integer :: ncid1, status integer :: RHVarID ! Variable ID ... status = nf90_open("foo.nc", nf90_nowrite, ncid) if (status /= nf90_noerr) call handle_err(status) ... ! Find the IDs of the variables status = nf90_inq_varid(ncid, "rh", RHVarID) if (status /= nf90_noerr) call handle_err(status) ... status = nf90_rename_att(ncid, RHVarID, "units", "Units") if (status /= nf90_noerr) call handle_err(status)8.7 Delete an Attribute: NF90_DEL_ATT
The function NF90_DEL_ATT deletes a netCDF attribute from an open netCDF dataset. The netCDF dataset must be in define mode.
Usage
function nf90_del_att(ncid, varid, name) integer, intent( in) :: ncid, varid character (len = *), intent( in) :: name integer :: nf90_del_att
ncid NetCDF ID, from a previous call to NF90_OPEN or NF90_CREATE. varid ID of the attribute's variable, or NF90_GLOBAL for a global attribute. name The original attribute name.Errors
NF90_DEL_ATT returns the value NF90_NOERR if no errors occurred. Otherwise, the returned status indicates an error. Possible causes of errors include:
- The specified variable ID is not valid.
- The specified netCDF dataset is in data mode.
- The specified attribute does not exist.
- The specified netCDF ID does not refer to an open netCDF dataset.
Example
Here is an example using NF90_DEL_ATT to delete the variable attribute Units for a variable rh in an existing netCDF dataset named foo.nc:
use netcdf implicit none integer :: ncid1, status integer :: RHVarID ! Variable ID ... status = nf90_open("foo.nc", nf90_nowrite, ncid) if (status /= nf90_noerr) call handle_err(status) ... ! Find the IDs of the variables status = nf90_inq_varid(ncid, "rh", RHVarID) if (status /= nf90_noerr) call handle_err(status) ... status = nf90_redef(ncid) ! Enter define mode if (status /= nf90_noerr) call handle_err(status) status = nf90_del_att(ncid, RHVarID, "Units") if (status /= nf90_noerr) call handle_err(status) status = nf90_enddef(ncid) if (status /= nf90_noerr) call handle_err(status)
| Contact Us Site Map Search Terms and Conditions Privacy Policy Participation Policy | ||||||
|
||||||