CF Convention Compliance

Overview

Output NetCDF files from precip-index declare CF-1.8 (Conventions: CF-1.8) and follow CF Convention guidelines for most attributes. This page documents what is fully compliant, what uses custom extensions, and what impact non-standard attributes may have on third-party tools.

The CF (Climate and Forecast) Convention defines metadata standards for NetCDF files to promote interoperability across climate data tools. Compliance is checked against the CF Standard Name Table.

Compliance Summary

Category Status Notes
Global attributes Compliant Conventions, title, history, institution, source, references
Coordinate names Compliant time, lat, lon follow CF naming
Coordinate metadata Inherited standard_name, units, axis passed through from input data
Data variable long_name Compliant Free-form descriptive name
Data variable units Compliant '1' (CF standard for dimensionless quantities)
Data variable valid_min/max Compliant CF-recognized range attributes
Data variable standard_name Custom Not from CF Standard Name Table (see below)
Data variable _FillValue Compliant -9999.0 in encoding
Compression Compliant zlib with configurable complevel
Grid mapping / CRS Not included Inherited from input; not explicitly written
cell_methods Not included Optional CF attribute, not set
Coordinate bounds Not included Optional CF attribute, not set

Fully Compliant Attributes

Global Attributes

All output files include these CF-recognized global attributes:

Attribute Example Value CF Section
Conventions CF-1.8 2.6.1
title Standardized Precipitation Index (SPI-12) 2.6.2
history Created 2026-04-02T10:30:00 2.6.2
institution Configurable (default: GOST/DEC Data Group, The World Bank) 2.6.2
source Configurable (default: TerraClimate monthly gridded data) 2.6.2
references Auto-built from method + data source citations 2.6.2
comment Computation description 2.6.2

The institution, source, creator_*, and references attributes are configurable via presets and overrides. See Configuring Metadata below.

Additional custom global attributes (index_type, distribution, scale, periodicity, calibration_start_year, calibration_end_year) are domain-specific metadata. CF allows custom attributes at the global level.

Data Variable Attributes

Attribute Example CF Status
long_name Standardized Precipitation Evapotranspiration Index (Pearson III), 12-month Compliant (free-form)
units 1 Compliant (CF standard for dimensionless)
valid_min -3.09 Compliant (CF Section 2.5.1)
valid_max 3.09 Compliant (CF Section 2.5.1)

Fitting Parameter Attributes

Parameter files use long_name, description, comment, and units – all CF-compatible. The comment attribute provides plain-language explanations (e.g., “Higher alpha means the rainfall distribution is more symmetric”).

Configuring Metadata

The package provides presets for common data sources and creator profiles, so metadata is always populated but easily swappable.

Data Source Presets

Available presets via METADATA_PRESETS:

Key Source Description
terraclimate TerraClimate monthly gridded data (default)
chirps CHIRPS v2.0 monthly precipitation
era5_land ERA5-Land monthly averaged reanalysis
imerg GPM IMERG Final Precipitation L3 monthly
cmorph CMORPH Climate Data Record monthly precipitation
mswep MSWEP v2.8 multi-source weighted-ensemble precipitation
gpcc GPCC Full Data Monthly Product

Each preset includes the source string and the full academic citation (source_references), which is automatically combined with the SPI/SPEI method references.

Creator Presets

Available presets via CREATOR_PRESETS:

Key Institution
worldbank GOST/DEC Data Group, The World Bank (default)

Using build_metadata()

The build_metadata() function combines presets with custom overrides:

from config import build_metadata

# Switch data source — keep default creator
meta = build_metadata(source='chirps')

# Switch both source and creator
meta = build_metadata(
    source='era5_land',
    creator='custom',
    institution='University of Tokyo',
    creator_name='Taro Yamada',
    creator_email='taro@example.ac.jp',
)

# Fully custom source (not a preset)
meta = build_metadata(
    source='My Regional Rain Gauge Network v2.0',
    creator='custom',
    institution='National Met Service',
    creator_name='Jane Doe',
    creator_email='jane@example.org',
)

# Pass to any compute function
spi_12 = spi(precip, scale=12, global_attrs=meta)
spei_12 = spei(precip, pet=pet, scale=12, global_attrs=meta)

Alternative: Modify defaults at runtime

To change the default for all subsequent calls without passing global_attrs each time:

from config import DEFAULT_METADATA, METADATA_PRESETS, CREATOR_PRESETS

# Switch to CHIRPS
DEFAULT_METADATA['source'] = METADATA_PRESETS['chirps']['source']

# Or set completely custom values
DEFAULT_METADATA['institution'] = 'My University'
DEFAULT_METADATA['creator_name'] = 'Jane Doe'
DEFAULT_METADATA['creator_email'] = 'jane@example.edu'

Priority order

When attributes are set in multiple places, later values override earlier ones:

  1. DEFAULT_METADATA (lowest priority – package defaults)
  2. Computed attributes (title, history, distribution, calibration years)
  3. global_attrs parameter (highest priority – your overrides)

Custom standard_name Values

ImportantKey Compatibility Note

The standard_name attribute on SPI/SPEI data variables uses custom names that are not in the CF Standard Name Table. This is the primary deviation from strict CF compliance.

What is generated

The variable naming pattern is {index}_{distribution}_{scale}_{periodicity}:

Variable Name standard_name Value
spi_gamma_3_month spi_gamma_3_month
spi_gamma_12_month spi_gamma_12_month
spei_pearson3_6_month spei_pearson3_6_month
spei_gev_12_month spei_gev_12_month

Why custom names are used

SPI and SPEI do not have entries in the CF Standard Name Table. There is no official CF standard name for drought indices. The custom standard_name is used because:

  1. It encodes the index type, distribution, scale, and periodicity in a single machine-readable string
  2. It enables programmatic variable discovery when working with multi-variable datasets
  3. The naming pattern is consistent and self-documenting

Impact on Third-Party Tools

Tools that validate standard_name strictly

Some NetCDF viewers validate standard_name against the CF Standard Name Table. When they encounter a name not in the table, behavior varies:

Tool Behavior with Custom standard_name
Panoply May refuse to open the file or fail to display the variable. This is the most common issue reported.
CF-checker (cfchecks) Will flag as a warning or error
THREDDS/OPeNDAP Generally tolerant; serves data regardless
CDO Ignores standard_name; works normally
NCO Ignores standard_name; works normally

Tools that are unaffected

Tool Behavior
Python (xarray, netCDF4) Works normally; standard_name is just metadata
R (ncdf4, terra) Works normally
QGIS Works normally; reads by variable name
ArcGIS Pro Works normally
GrADS Works normally
GDAL/rasterio Works normally

Workaround for Panoply

If you need to open output files in Panoply, you can remove the standard_name attribute from the NetCDF file using Python:

import xarray as xr

ds = xr.open_dataset('spei_pearson3_12.nc')

# Remove standard_name from all data variables
for var in ds.data_vars:
    if 'standard_name' in ds[var].attrs:
        del ds[var].attrs['standard_name']

ds.to_netcdf('spei_pearson3_12_panoply.nc')
ds.close()

Or using NCO command-line tools:

#| eval: false
ncatted -a standard_name,spei_pearson3_12_month,d,, spei_pearson3_12.nc -o spei_pearson3_12_panoply.nc
Tip

The long_name attribute is always present and is what most tools (including Panoply, after removing standard_name) will display as the variable label.

Coordinate Metadata

Coordinate attributes (standard_name, units, axis, calendar) are inherited from input data and passed through to output files. The package does not overwrite or guarantee these attributes.

If your input data has proper CF coordinate metadata (e.g., TerraClimate, CHIRPS, ERA5-Land), the output will preserve it. If your input lacks these attributes, the output will also lack them.

What CF expects for coordinates

Coordinate standard_name units axis
lat latitude degrees_north Y
lon longitude degrees_east X
time time e.g., days since 1900-01-01 T

Verifying your output

You can check whether coordinates have proper CF metadata:

import xarray as xr

ds = xr.open_dataset('output.nc')

for coord in ['lat', 'lon', 'time']:
    if coord in ds.coords:
        attrs = ds[coord].attrs
        print(f"{coord}:")
        print(f"  standard_name: {attrs.get('standard_name', 'MISSING')}")
        print(f"  units: {attrs.get('units', 'MISSING')}")
        print(f"  axis: {attrs.get('axis', 'MISSING')}")

ds.close()

Attributes Not Included

The following optional CF attributes are not set by the package. They can be added manually if needed for specific use cases:

Grid Mapping / CRS

CF Section 5.6 recommends a grid_mapping variable for geospatial datasets. This package assumes the input CRS is carried through by xarray. If you need explicit CRS metadata (e.g., for GIS interoperability), add it after computation:

import xarray as xr

ds = xr.open_dataset('output.nc')

# Add WGS84 CRS variable
ds['crs'] = xr.DataArray(
    data=0,
    attrs={
        'grid_mapping_name': 'latitude_longitude',
        'semi_major_axis': 6378137.0,
        'inverse_flattening': 298.257223563,
        'crs_wkt': 'GEOGCS["WGS 84", ...]'
    }
)
for var in ds.data_vars:
    if var != 'crs':
        ds[var].attrs['grid_mapping'] = 'crs'

ds.to_netcdf('output_with_crs.nc')
ds.close()

Cell Methods

CF Section 7.3 defines cell_methods to describe how data values represent variation within cells. SPI/SPEI are standardized indices derived from cumulative distribution functions, not simple temporal aggregations, so standard cell_methods descriptors do not apply cleanly.

Coordinate Bounds

CF Section 7.1 recommends bounds variables for coordinates. These are not generated but can be added if required by downstream tools.

Validating CF Compliance

To check your output files against the CF Convention:

#| eval: false
# Install the CF checker
pip install cfchecker

# Run validation
cfchecks output.nc

Expected results for precip-index output:

  • Conventions attribute: PASS
  • Global attributes: PASS
  • Coordinate variables: PASS (if input data had proper CF metadata)
  • standard_name on data variables: WARN (custom names not in CF table)
  • grid_mapping: INFO (not present)
  • cell_methods: INFO (not present)

The warnings about standard_name are expected and do not affect data quality or scientific validity.

Back to top