2011-07-12 00:04:49 +08:00
|
|
|
/** \file
|
|
|
|
Functions to write attributes.
|
|
|
|
|
|
|
|
These functions read and write attributes.
|
|
|
|
|
2018-12-07 05:29:57 +08:00
|
|
|
Copyright 2018 University Corporation for Atmospheric
|
2011-07-12 00:04:49 +08:00
|
|
|
Research/Unidata. See \ref copyright file for more info. */
|
|
|
|
|
|
|
|
#include "ncdispatch.h"
|
|
|
|
|
|
|
|
/** \name Writing Attributes
|
|
|
|
|
|
|
|
Functions to write attributes. */
|
|
|
|
/*! \{ */
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\ingroup attributes
|
2011-12-16 05:21:38 +08:00
|
|
|
Write a string attribute.
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
The function nc_put_att_string adds or changes a variable attribute or
|
|
|
|
global attribute of an open netCDF dataset. The string type is only
|
|
|
|
available in netCDF-4/HDF5 files, when ::NC_CLASSIC_MODEL has not been
|
|
|
|
used in nc_create().
|
|
|
|
|
2011-12-16 05:21:38 +08:00
|
|
|
\param ncid NetCDF or group ID, from a previous call to nc_open(),
|
2015-12-24 09:37:42 +08:00
|
|
|
nc_create(), nc_def_grp(), or associated inquiry functions such as
|
2011-12-16 05:21:38 +08:00
|
|
|
nc_inq_ncid().
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
\param varid Variable ID of the variable to which the attribute will
|
2011-12-16 05:21:38 +08:00
|
|
|
be assigned or ::NC_GLOBAL for a global or group attribute.
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
\param name Attribute \ref object_name. \ref attribute_conventions may
|
|
|
|
apply.
|
|
|
|
|
|
|
|
\param len Number of values provided for the attribute.
|
|
|
|
|
|
|
|
\param value Pointer to one or more values.
|
|
|
|
|
|
|
|
\returns ::NC_NOERR No error.
|
2017-10-06 08:15:27 +08:00
|
|
|
\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue.
|
2011-07-12 00:04:49 +08:00
|
|
|
\returns ::NC_ENOTVAR Couldn't find varid.
|
|
|
|
\returns ::NC_EBADTYPE Fill value and var must be same type.
|
|
|
|
\returns ::NC_ENOMEM Out of memory
|
|
|
|
\returns ::NC_ELATEFILL Fill values must be written while the file
|
|
|
|
is still in initial define mode.
|
|
|
|
*/
|
2016-01-05 05:49:47 +08:00
|
|
|
|
2016-01-05 05:59:51 +08:00
|
|
|
|
2016-01-05 05:49:47 +08:00
|
|
|
int
|
|
|
|
nc_put_att_string(int ncid, int varid, const char *name,
|
|
|
|
size_t len, const char** value)
|
2011-07-12 00:04:49 +08:00
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
2015-12-24 09:37:42 +08:00
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, NC_STRING,
|
2011-07-12 00:04:49 +08:00
|
|
|
len, (void*)value, NC_STRING);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\ingroup attributes
|
|
|
|
Write a text attribute.
|
|
|
|
|
2018-08-25 04:14:15 +08:00
|
|
|
Add or change a text attribute. 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 for classic formats (or
|
|
|
|
netCDF-4/HDF5 with NC_CLASSIC_MODEL).
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
Although it's possible to create attributes of all types, text and
|
|
|
|
double attributes are adequate for most purposes.
|
|
|
|
|
|
|
|
Use the nc_put_att function to create attributes of any type,
|
|
|
|
including user-defined types. We recommend using the type safe
|
|
|
|
versions of this function whenever possible.
|
|
|
|
|
2011-12-16 05:21:38 +08:00
|
|
|
\param ncid NetCDF or group ID, from a previous call to nc_open(),
|
2015-12-24 09:37:42 +08:00
|
|
|
nc_create(), nc_def_grp(), or associated inquiry functions such as
|
2011-12-16 05:21:38 +08:00
|
|
|
nc_inq_ncid().
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
\param varid Variable ID of the variable to which the attribute will
|
|
|
|
be assigned or ::NC_GLOBAL for a global attribute.
|
|
|
|
|
|
|
|
\param name Attribute \ref object_name. \ref attribute_conventions may
|
|
|
|
apply.
|
|
|
|
|
|
|
|
\param len Number of values provided for the attribute.
|
|
|
|
|
|
|
|
\param value Pointer to one or more values.
|
|
|
|
|
|
|
|
\returns ::NC_NOERR No error.
|
2017-10-06 08:15:27 +08:00
|
|
|
\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue.
|
2011-07-12 00:04:49 +08:00
|
|
|
\returns ::NC_ENOTVAR Couldn't find varid.
|
|
|
|
\returns ::NC_EBADTYPE Fill value and var must be same type.
|
|
|
|
\returns ::NC_ENOMEM Out of memory
|
|
|
|
\returns ::NC_ELATEFILL Fill values must be written while the file
|
|
|
|
is still in initial define mode.
|
|
|
|
|
|
|
|
\note With netCDF-4 files, nc_put_att will notice if you are writing a
|
|
|
|
_Fill_Value_ attribute, and will tell the HDF5 layer to use the
|
|
|
|
specified fill value for that variable.
|
|
|
|
|
2014-03-09 08:39:09 +08:00
|
|
|
\section nc_put_att_text_example Example
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
Here is an example using nc_put_att_double() to add a variable
|
|
|
|
attribute named valid_range for a netCDF variable named rh and
|
|
|
|
nc_put_att_text() to add a global attribute named title to an existing
|
|
|
|
netCDF dataset named foo.nc:
|
|
|
|
|
|
|
|
\code
|
|
|
|
#include <netcdf.h>
|
|
|
|
...
|
2015-12-24 09:37:42 +08:00
|
|
|
int status;
|
|
|
|
int ncid;
|
|
|
|
int rh_id;
|
2011-07-12 00:04:49 +08:00
|
|
|
static double rh_range[] = {0.0, 100.0};
|
|
|
|
static char title[] = "example netCDF dataset";
|
|
|
|
...
|
|
|
|
status = nc_open("foo.nc", NC_WRITE, &ncid);
|
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
...
|
2015-12-24 09:37:42 +08:00
|
|
|
status = nc_redef(ncid);
|
2011-07-12 00:04:49 +08:00
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
status = nc_inq_varid (ncid, "rh", &rh_id);
|
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
...
|
|
|
|
status = nc_put_att_double (ncid, rh_id, "valid_range",
|
|
|
|
NC_DOUBLE, 2, rh_range);
|
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
status = nc_put_att_text (ncid, NC_GLOBAL, "title",
|
|
|
|
strlen(title), title)
|
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
...
|
2015-12-24 09:37:42 +08:00
|
|
|
status = nc_enddef(ncid);
|
2011-07-12 00:04:49 +08:00
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
\endcode
|
|
|
|
*/
|
2016-01-05 05:49:47 +08:00
|
|
|
|
2016-01-05 05:59:51 +08:00
|
|
|
|
2016-01-05 05:49:47 +08:00
|
|
|
int nc_put_att_text(int ncid, int varid, const char *name,
|
|
|
|
size_t len, const char *value)
|
2011-07-12 00:04:49 +08:00
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
2015-12-24 09:37:42 +08:00
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, NC_CHAR, len,
|
2011-07-12 00:04:49 +08:00
|
|
|
(void *)value, NC_CHAR);
|
|
|
|
}
|
|
|
|
|
2015-12-24 09:37:42 +08:00
|
|
|
/*! \} */
|
2011-07-12 00:04:49 +08:00
|
|
|
/*!
|
|
|
|
\ingroup attributes
|
|
|
|
Write an attribute.
|
|
|
|
|
|
|
|
The function nc_put_att_ type adds 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
|
2018-08-25 04:15:59 +08:00
|
|
|
before, the netCDF dataset must be in define mode for classic formats
|
|
|
|
(or netCDF-4/HDF5 with NC_CLASSIC_MODEL).
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
With netCDF-4 files, nc_put_att will notice if you are writing a
|
2012-08-17 02:31:48 +08:00
|
|
|
_FillValue attribute, and will tell the HDF5 layer to use the
|
|
|
|
specified fill value for that variable. With either classic or
|
|
|
|
netCDF-4 files, a _FillValue attribute will be checked for validity,
|
|
|
|
to make sure it has only one value and that its type matches the type
|
|
|
|
of the associated variable.
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
Although it's possible to create attributes of all types, text and
|
|
|
|
double attributes are adequate for most purposes.
|
|
|
|
|
2011-12-16 05:21:38 +08:00
|
|
|
\param ncid NetCDF or group ID, from a previous call to nc_open(),
|
2015-12-24 09:37:42 +08:00
|
|
|
nc_create(), nc_def_grp(), or associated inquiry functions such as
|
2011-12-16 05:21:38 +08:00
|
|
|
nc_inq_ncid().
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
\param varid Variable ID of the variable to which the attribute will
|
2011-12-16 05:21:38 +08:00
|
|
|
be assigned or ::NC_GLOBAL for a global or group attribute.
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
\param name Attribute \ref object_name. \ref attribute_conventions may
|
|
|
|
apply.
|
|
|
|
|
|
|
|
\param xtype \ref data_type of the attribute.
|
|
|
|
|
|
|
|
\param len Number of values provided for the attribute.
|
|
|
|
|
|
|
|
\param value Pointer to one or more values.
|
|
|
|
|
|
|
|
\returns ::NC_NOERR No error.
|
2017-10-06 08:15:27 +08:00
|
|
|
\returns ::NC_EINVAL More than one value for _FillValue or trying to set global _FillValue.
|
2011-07-12 00:04:49 +08:00
|
|
|
\returns ::NC_ENOTVAR Couldn't find varid.
|
|
|
|
\returns ::NC_EBADTYPE Fill value and var must be same type.
|
|
|
|
\returns ::NC_ENOMEM Out of memory
|
|
|
|
\returns ::NC_ELATEFILL Fill values must be written while the file
|
|
|
|
is still in initial define mode.
|
|
|
|
|
2014-03-09 08:39:09 +08:00
|
|
|
\section nc_put_att_double_example Example
|
2011-07-12 00:04:49 +08:00
|
|
|
|
|
|
|
Here is an example using nc_put_att_double() to add a variable
|
|
|
|
attribute named valid_range for a netCDF variable named rh and
|
|
|
|
nc_put_att_text() to add a global attribute named title to an existing
|
|
|
|
netCDF dataset named foo.nc:
|
|
|
|
|
|
|
|
\code
|
|
|
|
#include <netcdf.h>
|
|
|
|
...
|
2015-12-24 09:37:42 +08:00
|
|
|
int status;
|
|
|
|
int ncid;
|
|
|
|
int rh_id;
|
2011-07-12 00:04:49 +08:00
|
|
|
static double rh_range[] = {0.0, 100.0};
|
|
|
|
static char title[] = "example netCDF dataset";
|
|
|
|
...
|
|
|
|
status = nc_open("foo.nc", NC_WRITE, &ncid);
|
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
...
|
2015-12-24 09:37:42 +08:00
|
|
|
status = nc_redef(ncid);
|
2011-07-12 00:04:49 +08:00
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
status = nc_inq_varid (ncid, "rh", &rh_id);
|
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
...
|
|
|
|
status = nc_put_att_double (ncid, rh_id, "valid_range",
|
|
|
|
NC_DOUBLE, 2, rh_range);
|
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
status = nc_put_att_text (ncid, NC_GLOBAL, "title",
|
|
|
|
strlen(title), title)
|
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
...
|
2015-12-24 09:37:42 +08:00
|
|
|
status = nc_enddef(ncid);
|
2011-07-12 00:04:49 +08:00
|
|
|
if (status != NC_NOERR) handle_error(status);
|
|
|
|
\endcode
|
|
|
|
*/
|
|
|
|
/*! \{*/
|
|
|
|
int
|
|
|
|
nc_put_att(int ncid, int varid, const char *name, nc_type xtype,
|
|
|
|
size_t len, const void *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
2015-12-24 09:37:42 +08:00
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
2011-07-12 00:04:49 +08:00
|
|
|
value, xtype);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_schar(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const signed char *value)
|
|
|
|
{
|
|
|
|
NC *ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
2015-12-24 09:37:42 +08:00
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
2011-07-12 00:04:49 +08:00
|
|
|
(void *)value, NC_BYTE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_uchar(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const unsigned char *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_UBYTE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_short(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const short *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
2015-12-24 09:37:42 +08:00
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
2011-07-12 00:04:49 +08:00
|
|
|
(void *)value, NC_SHORT);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_int(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const int *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_INT);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_long(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const long *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, longtype);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_float(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const float *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_FLOAT);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_double(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const double *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_DOUBLE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_ubyte(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const unsigned char *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_UBYTE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_ushort(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const unsigned short *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_USHORT);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_uint(int ncid, int varid, const char *name,
|
|
|
|
nc_type xtype, size_t len, const unsigned int *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_UINT);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_longlong(int ncid, int varid, const char *name,
|
2015-12-24 09:37:42 +08:00
|
|
|
nc_type xtype, size_t len,
|
2011-07-12 00:04:49 +08:00
|
|
|
const long long *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_INT64);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
nc_put_att_ulonglong(int ncid, int varid, const char *name,
|
2015-12-24 09:37:42 +08:00
|
|
|
nc_type xtype, size_t len,
|
2011-07-12 00:04:49 +08:00
|
|
|
const unsigned long long *value)
|
|
|
|
{
|
|
|
|
NC* ncp;
|
|
|
|
int stat = NC_check_id(ncid, &ncp);
|
|
|
|
if(stat != NC_NOERR) return stat;
|
|
|
|
return ncp->dispatch->put_att(ncid, varid, name, xtype, len,
|
|
|
|
(void *)value, NC_UINT64);
|
|
|
|
}
|