How to write data in netCDF format.
netCDF is a standalone file format, meaning every meta-information needed to work with the data inside the netCDF file (units, descriptions, source, author, coordinates, etc), has to be provided with the netCDF files itself. To achieve this one has to provide those meta-information already while writing / creating the netCDF file.
Preparation
Before we start, lets prepare some technical things.
First, we have to make SLOTH
available to import by Python. If you already have added SLOTH
to your PYHTONPATH
, below step is not needed.
import os
import sys
cwd = os.getcwd()
sloth_path = f"{cwd}/../"
sys.path.append(sloth_path)
Second, we need to import all libraries needed in the following example.
import netCDF4 as nc
import numpy as np
import datetime as dt
import sloth.IO
Define a target file, where to store the netCDF file
saveFile = '../data/examples_Write2NetCDF_short.nc'
Use SLOTH to generate the target netCDF file.
netCDFFileName = sloth.IO.createNetCDF(saveFile, domain='DE06',
author='Niklas WAGNER', contact='n.wagner@fz-juelich.de',
institution='FZJ - IBG-3', history=f'Created: {dt.datetime.now().strftime("%Y-%m-%d %H:%M")}',
description='Write a short description of your data to ship with the netCDF files!',
source='add source here')
with nc.Dataset(netCDFFileName, 'a') as nc_file:
print(f'DEBUG: nc_file\n{nc_file}')
DEBUG: nc_file
<class 'netCDF4._netCDF4.Dataset'>
root group (NETCDF4 data model, file format HDF5):
author: Niklas WAGNER
contact: n.wagner@fz-juelich.de
institution: FZJ - IBG-3
description: Write a short description of your data to ship with the netCDF files!
history: Created: 2023-09-04 11:48
source: add source here
dimensions(sizes): rlon(2000), rlat(2000), time(0)
variables(dimensions): float32 rlon(rlon), float32 rlat(rlat), int16 rotated_pole()
groups:
The used function (sloth.IO.createNetCDF
) does collect some meta information as e.g. the author name and e-mail address, which are directly stored with the created netCDF file, to not get lost. Further the function does take the target domain as argument (domain='DE06'
), to directly attach the correct axis and coordinates to the target netCDF file.
The target domain could be a keyword (as DE06
above) or the full path to a grid-description file as used by CDO. The keywords are simple predefined, frequently used griddes files shipped with SLOTH under sloth/configs/.
Generate some random example data, open the netCDF file and store the example data as a new variable called TestData
with the netCDF file
# create example data to store with the netCDF file:
# using 5 time steps, and nx, ny of DE05 grid
np.random.seed(42)
data = np.random.rand(5,2000,2000)
# Create the actual variable we want to store the data at.
with nc.Dataset(netCDFFileName, 'a') as nc_file:
# Name of the variable: 'TestData'
ncVar = nc_file.createVariable('TestData', 'f4', ('time', 'rlat', 'rlon',),
fill_value=-9999,
zlib=True)
ncVar.standard_name = 'test_name'
ncVar.long_name = 'variable to test writing netCDF'
ncVar.units ='-'
ncVar.grid_mapping = 'rotated_pole'
ncTime = nc_file.createVariable('time', 'i2', ('time',))
ncTime.standard_name = 'time'
ncTime.units = 'days since 1979-01-01 00:00:00'
ncTime.calendar = '365_day'
ncVar[...] = data[...]
ncTime[...] = np.arange(data.shape[0])
Check the generated data with ncdump -h
>> ncdump -h ../data/examples_Write2NetCDF_short.nc
netcdf examples_Write2NetCDF_short {
dimensions:
rlon = 2000 ;
rlat = 2000 ;
time = UNLIMITED ; // (5 currently)
variables:
float rlon(rlon) ;
rlon:standard_name = "grid_longitude" ;
rlon:long_name = "rotated longitude" ;
rlon:units = "degrees" ;
rlon:axis = "X" ;
float rlat(rlat) ;
rlat:standard_name = "grid_latitude" ;
rlat:long_name = "rotated latitude" ;
rlat:units = "degrees" ;
rlat:axis = "Y" ;
short rotated_pole ;
rotated_pole:long_name = "coordinates of the rotated North Pole" ;
rotated_pole:grid_mapping_name = "rotated_latitude_longitude" ;
rotated_pole:grid_north_pole_latitude = 39.25 ;
rotated_pole:grid_north_pole_longitude = -162. ;
float TestData(time, rlat, rlon) ;
TestData:_FillValue = -9999.f ;
TestData:standard_name = "test_name" ;
TestData:long_name = "variable to test writing netCDF" ;
TestData:units = "-" ;
TestData:grid_mapping = "rotated_pole" ;
short time(time) ;
time:standard_name = "time" ;
time:units = "days since 1979-01-01 00:00:00" ;
time:calendar = "365_day" ;
// global attributes:
:author = "Niklas WAGNER" ;
:contact = "n.wagner@fz-juelich.de" ;
:institution = "FZJ - IBG-3" ;
:description = "Write a short description of your data to ship with the netCDF files!" ;
:history = "Created: 2023-09-04 11:37" ;
:source = "add source here" ;
}