diff --git a/autotest/gdrivers/netcdf.py b/autotest/gdrivers/netcdf.py index 0e046aa759ae..c26d620cbc04 100755 --- a/autotest/gdrivers/netcdf.py +++ b/autotest/gdrivers/netcdf.py @@ -6489,3 +6489,27 @@ def test_gdal_subdataset_bogus(bogus): """Test it doesn't crash""" gdal.GetSubdatasetInfo(bogus) + + +@gdaltest.enable_exceptions() +def test_band_names_creation_option(tmp_path): + + fname = tmp_path / "twobands.nc" + + # 1 band, 2 names + with pytest.raises(Exception, match="but 2 names provided"): + gdal.GetDriverByName("NetCDF").Create( + fname, 1, 1, 1, options={"BAND_NAMES": "t2m,prate"} + ) + + # 2 bands, 2 names + with gdal.GetDriverByName("NetCDF").Create( + fname, 1, 1, 2, options={"BAND_NAMES": "t2m,prate"} + ): + pass + + with gdal.Open(fname) as ds: + sds_names = [sds[0] for sds in ds.GetSubDatasets()] + + assert gdal.GetSubdatasetInfo(sds_names[0]).GetSubdatasetComponent() == "t2m" + assert gdal.GetSubdatasetInfo(sds_names[1]).GetSubdatasetComponent() == "prate" diff --git a/doc/source/drivers/raster/netcdf.rst b/doc/source/drivers/raster/netcdf.rst index 49900cbf7fcb..fbe191d1d1d5 100644 --- a/doc/source/drivers/raster/netcdf.rst +++ b/doc/source/drivers/raster/netcdf.rst @@ -429,6 +429,12 @@ Creation Options installations, but NC4 and NC4C are available if NetCDF was compiled with NetCDF-4 (and HDF5) support. +- .. co:: BAND_NAMES + :default: Band1,Band2,... + :since: 3.9.0 + + A comma-separated list of band names. + - .. co:: COMPRESS :choices: NONE, DEFLATE diff --git a/frmts/netcdf/netcdfdataset.cpp b/frmts/netcdf/netcdfdataset.cpp index 68cf0c28cad4..067ca209634b 100644 --- a/frmts/netcdf/netcdfdataset.cpp +++ b/frmts/netcdf/netcdfdataset.cpp @@ -9156,7 +9156,6 @@ netCDFDataset *netCDFDataset::CreateLL(const char *pszFilename, int nXSize, return poDS; } - // Create the dataset. CPLString osFilenameForNCCreate(pszFilename); #if defined(_WIN32) && !defined(NETCDF_USES_UTF8) @@ -9321,12 +9320,31 @@ GDALDataset *netCDFDataset::Create(const char *pszFilename, int nXSize, : GDAL_DEFAULT_NCDF_CONVENTIONS); } + CPLStringList aosBandNames; + if (const char *pszBandNames = aosOptions.FetchNameValue("BAND_NAMES")) + { + aosBandNames = + CSLTokenizeString2(pszBandNames, ",", CSLT_HONOURSTRINGS); + + if (aosBandNames.Count() != nBandsIn) + { + CPLError(CE_Failure, CPLE_OpenFailed, + "Attempted to create netCDF with %d bands but %d names " + "provided in BAND_NAMES.", + nBandsIn, aosBandNames.Count()); + return nullptr; + } + } + // Define bands. for (int iBand = 1; iBand <= nBandsIn; iBand++) { - poDS->SetBand( - iBand, new netCDFRasterBand(netCDFRasterBand::CONSTRUCTOR_CREATE(), - poDS, eType, iBand, poDS->bSignedData)); + const char *pszBandName = + aosBandNames.empty() ? nullptr : aosBandNames[iBand - 1]; + + poDS->SetBand(iBand, new netCDFRasterBand( + netCDFRasterBand::CONSTRUCTOR_CREATE(), poDS, + eType, iBand, poDS->bSignedData, pszBandName)); } CPLDebug("GDAL_netCDF", "netCDFDataset::Create(%s, ...) done", pszFilename); diff --git a/frmts/netcdf/netcdfdrivercore.cpp b/frmts/netcdf/netcdfdrivercore.cpp index eb034cb4dbfb..9715a08e5160 100644 --- a/frmts/netcdf/netcdfdrivercore.cpp +++ b/frmts/netcdf/netcdfdrivercore.cpp @@ -429,6 +429,7 @@ void netCDFDriverSetCommonMetadata(GDALDriver *poDriver) "description='Path to a XML configuration file (or content inlined)'/>" "