netCDF4 file access via h5py with hierarchical and legacy APIs for scientific computing
69
Attributes provide metadata for files, groups, and variables in netCDF4 files. They store descriptive information such as units, descriptions, valid ranges, and processing history, enabling self-documenting data files.
Dictionary-like interface for managing attributes on netCDF objects.
class Attributes(MutableMapping):
def __getitem__(self, key: str):
"""
Get attribute value by name.
Args:
key (str): Attribute name
Returns:
Attribute value (type depends on stored data)
"""
...
def __setitem__(self, key: str, value) -> None:
"""
Set attribute value.
Args:
key (str): Attribute name
value: Attribute value (scalar, string, or array)
"""
...
def __delitem__(self, key: str) -> None:
"""
Delete attribute.
Args:
key (str): Attribute name to delete
"""
...
def __contains__(self, key: str) -> bool:
"""Check if attribute exists."""
...
def __iter__(self):
"""Iterate over attribute names."""
...
def __len__(self) -> int:
"""Number of attributes."""
...
def keys(self):
"""Attribute names."""
...
def values(self):
"""Attribute values."""
...
def items(self):
"""(name, value) pairs."""
...All netCDF objects (File, Group, Variable) have an attrs property.
# Available on File, Group, and Variable classes
@property
def attrs(self) -> Attributes:
"""Dictionary-like access to attributes."""
...import h5netcdf
import numpy as np
with h5netcdf.File('attributes.nc', 'w') as f:
# Create dimensions and variable
f.dimensions['time'] = 100
f.dimensions['lat'] = 180
f.dimensions['lon'] = 360
temp = f.create_variable('temperature', ('time', 'lat', 'lon'), dtype='f4')
# Set common variable attributes
temp.attrs['units'] = 'K'
temp.attrs['long_name'] = 'Air Temperature'
temp.attrs['standard_name'] = 'air_temperature'
temp.attrs['valid_range'] = [200.0, 350.0]
temp.attrs['missing_value'] = -999.0
temp.attrs['_FillValue'] = -999.0
# Set processing attributes
temp.attrs['source'] = 'ERA5 Reanalysis'
temp.attrs['processing_level'] = 'Level 3'
temp.attrs['creation_date'] = '2023-11-15'
# Numeric attributes
temp.attrs['scale_factor'] = 1.0
temp.attrs['add_offset'] = 0.0
temp.attrs['calibration_factor'] = 0.98
# Array attributes
temp.attrs['flag_values'] = np.array([0, 1, 2, 3], dtype='i1')
temp.attrs['flag_meanings'] = 'good questionable bad missing'with h5netcdf.File('global_attrs.nc', 'w') as f:
# Set global (file-level) attributes
f.attrs['title'] = 'Global Temperature Analysis'
f.attrs['institution'] = 'Climate Research Center'
f.attrs['contact'] = 'data@climate.org'
f.attrs['Conventions'] = 'CF-1.8'
f.attrs['history'] = 'Created on 2023-11-15 using h5netcdf'
f.attrs['source'] = 'Satellite observations and model data'
f.attrs['references'] = 'Smith et al. (2023), Journal of Climate'
# Geospatial attributes
f.attrs['geospatial_lat_min'] = -90.0
f.attrs['geospatial_lat_max'] = 90.0
f.attrs['geospatial_lon_min'] = -180.0
f.attrs['geospatial_lon_max'] = 180.0
f.attrs['geospatial_lat_units'] = 'degrees_north'
f.attrs['geospatial_lon_units'] = 'degrees_east'
# Temporal attributes
f.attrs['time_coverage_start'] = '2023-01-01T00:00:00Z'
f.attrs['time_coverage_end'] = '2023-12-31T23:59:59Z'
# Technical attributes
f.attrs['processing_software'] = 'h5netcdf v1.6.4'
f.attrs['format_version'] = 'netCDF-4'
f.attrs['compression'] = 'gzip level 6'with h5netcdf.File('group_attrs.nc', 'w') as f:
# Create groups with attributes
observations = f.create_group('observations')
observations.attrs['description'] = 'Raw observational data'
observations.attrs['quality_control'] = 'Level 1'
observations.attrs['instrument'] = 'AVHRR'
model = f.create_group('model')
model.attrs['description'] = 'Model simulation results'
model.attrs['model_name'] = 'WRF v4.3'
model.attrs['grid_resolution'] = '25km'
model.attrs['physics_scheme'] = 'YSU PBL, WSM6 microphysics'with h5netcdf.File('coordinates.nc', 'w') as f:
f.dimensions['time'] = 12
f.dimensions['lat'] = 180
f.dimensions['lon'] = 360
# Time coordinate
time = f.create_variable('time', ('time',), dtype='f8')
time.attrs['units'] = 'days since 2023-01-01 00:00:00'
time.attrs['calendar'] = 'standard'
time.attrs['long_name'] = 'Time'
time.attrs['standard_name'] = 'time'
time.attrs['axis'] = 'T'
# Latitude coordinate
lat = f.create_variable('lat', ('lat',), dtype='f4')
lat.attrs['units'] = 'degrees_north'
lat.attrs['long_name'] = 'Latitude'
lat.attrs['standard_name'] = 'latitude'
lat.attrs['axis'] = 'Y'
lat.attrs['valid_range'] = [-90.0, 90.0]
# Longitude coordinate
lon = f.create_variable('lon', ('lon',), dtype='f4')
lon.attrs['units'] = 'degrees_east'
lon.attrs['long_name'] = 'Longitude'
lon.attrs['standard_name'] = 'longitude'
lon.attrs['axis'] = 'X'
lon.attrs['valid_range'] = [-180.0, 180.0]with h5netcdf.File('inspect_attrs.nc', 'r') as f:
# Inspect global attributes
print("Global attributes:")
for name, value in f.attrs.items():
print(f" {name}: {value}")
# Inspect variable attributes
for var_name, variable in f.variables.items():
print(f"\nVariable '{var_name}' attributes:")
for attr_name, attr_value in variable.attrs.items():
print(f" {attr_name}: {attr_value}")
# Check for specific attributes
if 'temperature' in f.variables:
temp = f.variables['temperature']
if 'units' in temp.attrs:
print(f"Temperature units: {temp.attrs['units']}")
if 'valid_range' in temp.attrs:
vmin, vmax = temp.attrs['valid_range']
print(f"Valid range: {vmin} to {vmax}")
# Check for fill value
fill_value = temp.attrs.get('_FillValue', None)
if fill_value is not None:
print(f"Fill value: {fill_value}")with h5netcdf.File('attr_types.nc', 'w') as f:
f.dimensions['x'] = 10
var = f.create_variable('data', ('x',), dtype='f4')
# String attributes
var.attrs['string_attr'] = 'This is a string'
var.attrs['unicode_attr'] = 'Unicode: αβγ'
# Numeric attributes
var.attrs['int_attr'] = 42
var.attrs['float_attr'] = 3.14159
var.attrs['double_attr'] = np.float64(2.718281828)
# Array attributes
var.attrs['int_array'] = np.array([1, 2, 3, 4, 5])
var.attrs['float_array'] = np.array([1.1, 2.2, 3.3])
var.attrs['string_array'] = ['option1', 'option2', 'option3']
# Boolean-like (stored as integers)
var.attrs['flag'] = np.int8(1) # True
var.attrs['enabled'] = np.int8(0) # False
# Special values
var.attrs['nan_value'] = np.nan
var.attrs['inf_value'] = np.inf# Following Climate and Forecast (CF) conventions
with h5netcdf.File('cf_compliant.nc', 'w') as f:
# Global CF attributes
f.attrs['Conventions'] = 'CF-1.8'
f.attrs['title'] = 'Monthly Global Temperature Anomalies'
f.attrs['institution'] = 'Climate Data Center'
f.attrs['source'] = 'Reanalysis'
f.attrs['history'] = 'Created 2023-11-15'
f.attrs['comment'] = 'Temperature anomalies relative to 1981-2010 base period'
# Create dimensions
f.dimensions['time'] = None
f.dimensions['lat'] = 180
f.dimensions['lon'] = 360
# Time with CF-compliant attributes
time = f.create_variable('time', ('time',), dtype='f8')
time.attrs['standard_name'] = 'time'
time.attrs['long_name'] = 'time'
time.attrs['units'] = 'days since 1850-01-01 00:00:00'
time.attrs['calendar'] = 'standard'
time.attrs['axis'] = 'T'
# Temperature with full CF metadata
temp = f.create_variable('temperature_anomaly', ('time', 'lat', 'lon'), dtype='f4')
temp.attrs['standard_name'] = 'air_temperature_anomaly'
temp.attrs['long_name'] = 'Near-Surface Air Temperature Anomaly'
temp.attrs['units'] = 'K'
temp.attrs['cell_methods'] = 'time: mean'
temp.attrs['grid_mapping'] = 'crs'
temp.attrs['coordinates'] = 'lon lat'
temp.attrs['valid_range'] = [-50.0, 50.0]
temp.attrs['_FillValue'] = -9999.0with h5netcdf.File('modify_attrs.nc', 'r+') as f: # Note: 'r+' mode for modification
if 'temperature' in f.variables:
temp = f.variables['temperature']
# Modify existing attribute
if 'processing_level' in temp.attrs:
temp.attrs['processing_level'] = 'Level 2B'
# Add new attribute
temp.attrs['last_modified'] = '2023-11-15T14:30:00Z'
# Delete attribute
if 'obsolete_attr' in temp.attrs:
del temp.attrs['obsolete_attr']
# Update global attributes
f.attrs['history'] += f"; Modified {datetime.now().isoformat()}"def validate_cf_attributes(variable):
"""Validate CF convention compliance."""
required_attrs = ['standard_name', 'units']
recommended_attrs = ['long_name', 'valid_range']
missing_required = [attr for attr in required_attrs
if attr not in variable.attrs]
missing_recommended = [attr for attr in recommended_attrs
if attr not in variable.attrs]
if missing_required:
print(f"Missing required attributes: {missing_required}")
if missing_recommended:
print(f"Missing recommended attributes: {missing_recommended}")
# Check units format
if 'units' in variable.attrs:
units = variable.attrs['units']
if not isinstance(units, str):
print("Units should be a string")
# Usage
with h5netcdf.File('validate.nc', 'r') as f:
for var_name, variable in f.variables.items():
print(f"Validating {var_name}:")
validate_cf_attributes(variable)Install with Tessl CLI
npx tessl i tessl/pypi-h5netcdfdocs
evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10