3 Module containing utilities to manipulate netCDF4 files.
5 __author__ =
'gfireman'
11 from os.path
import basename
13 def nccopy_var(srcvar, dstgrp, indices=None, verbose=False):
14 """Copy a netCDF4 variable, optionally subsetting some dimensions.
16 Function to copy a single netCDF4 variable and associated attributes.
17 Optionally subset specified dimensions.
21 srcvar : netCDF4.Variable
22 Open variable to be copied
23 dstgrp : netCDF4.Group
24 Open Group or Dataset destination object to copy stuff to
25 indices : dict, optional
26 Dict of dimname:[indexarr] to subset a dimension
27 verbose : boolean, optional
32 Strings are written as H5T_CSET_ASCII, not H5T_CSET_UTF8
33 Empty attributes are written as scalar "" instead of NULL
37 zlib = srcvar.filters().get(
'zlib',
False)
38 shuffle = srcvar.filters().get(
'shuffle',
False)
39 complevel = srcvar.filters().get(
'complevel', 0)
40 dstvar = dstgrp.createVariable(srcvar.name,
49 dstvar.setncatts(srcvar.__dict__)
52 if not indices
or not any(k
in indices
for k
in srcvar.dimensions):
54 print(
"\tcopying",srcvar.name)
60 print(
"\tsubsetting",srcvar.name)
62 for dimname
in indices:
64 axis = srcvar.dimensions.index(dimname)
67 tmpvar = np.take(tmpvar, indices[dimname], axis=axis)
74 def nccopy_grp(srcgrp, dstgrp, indices=None, verbose=False):
75 """Recursively copy a netCDF4 group, optionally subsetting some dimensions.
77 Function to recursively copy a netCDF4 group,
78 with associated attributes, dimensions and variables.
79 Optionally subset specified dimensions.
83 srcgrp : netCDF4.Group
84 Open Group or Dataset source object containing stuff to be copied
85 dstgrp : netCDF4.Group
86 Open Group or Dataset destination object to copy stuff to
87 indices : dict, optional
88 Dict of dimname:[indexarr] to subset a dimension
89 verbose : boolean, optional
94 print(
'grp: ', srcgrp.path)
97 dstgrp.setncatts(srcgrp.__dict__)
100 for dimname, dim
in srcgrp.dimensions.items():
101 if dim.isunlimited():
103 elif indices
and dimname
in indices:
104 dimsize = len(indices[dimname])
107 dstgrp.createDimension(dimname, dimsize)
110 for varname, srcvar
in srcgrp.variables.items():
112 print(
'var: ',
'/'.join([srcgrp.path, srcvar.name]))
113 nccopy_var(srcvar, dstgrp, indices=indices, verbose=verbose)
116 for grpname, srcsubgrp
in srcgrp.groups.items():
117 dstsubgrp = dstgrp.createGroup(grpname)
118 nccopy_grp(srcsubgrp, dstsubgrp, indices=indices, verbose=verbose)
121 def nccopy(srcfile, dstfile, verbose=False):
122 """Copy a netCDF4 file.
124 Function to copy a netCDF4 file to a new file.
125 Intended mostly as a demonstration.
130 Path to source file; must be netCDF4 format.
132 Path to destination file; directory must exist.
133 verbose : boolean, optional
137 with netCDF4.Dataset(srcfile,
'r')
as src, \
138 netCDF4.Dataset(dstfile,
'w')
as dst:
140 print(
'\nfile:', src.filepath())
145 """Copy a netCDF4 file, with some dimensions subsetted.
147 Function to copy netCDF4 file to a new file,
149 Function to copy a single netCDF4 variable and associated attributes.
150 Optionally subset specified dimensions.
155 Path to source file; must be netCDF4 format.
157 Path to destination file; directory must exist.
158 subset : dict, optional
159 Dict of dimname:[startindex,endindex] to subset a dimension
160 verbose : boolean, optional
165 Strings are written as H5T_CSET_ASCII, not H5T_CSET_UTF8
166 Empty attributes are written as scalar "" instead of NULL
173 print(
'opening', srcfile)
174 with netCDF4.Dataset(srcfile,
'r')
as src:
177 for dimname
in subset:
178 if dimname
not in src.dimensions:
179 print(
'Warning: dimension "' +
180 dimname +
'" does not exist in input file root group.')
181 if (subset[dimname][0] > subset[dimname][1]):
182 print(
'Invalid indices for dimension "' +
183 dimname +
'"; exiting.')
185 for dimname, dim
in src.dimensions.items():
186 if ((dimname
in subset)
and
187 any((0 > d
or d > len(dim) - 1)
for d
in subset[dimname])):
188 oldsubset = subset.copy()
189 subset[dimname] = np.clip(subset[dimname], a_min=0,
190 a_max=len(dim) - 1).tolist()
191 print(
'Clipping "' + dimname +
192 '" dimension indices to match input file:',
193 oldsubset[dimname],
'->', subset[dimname])
196 indices = {k : np.arange(subset[k][0],
197 subset[k][1] + 1)
for k
in subset}
201 print(
'opening', dstfile)
202 with netCDF4.Dataset(dstfile,
'w')
as dst:
203 nccopy_grp(src, dst, indices=indices, verbose=verbose)
211 """Update 'date_created' and 'history' attributes
213 Function to add or update 'date_created' and 'history'
214 attributes for specified dataset (usually root).
218 dataset : netCDF4.Group
219 Open Group or Dataset destination object to update
220 timestamp : time.struct_time, optional
221 Timestamp to add to history attribute
222 Defaults to current time
223 cmdline : string, optional
224 Description to add to history attribute
228 timestamp = time.gmtime()
229 fmt =
'%Y-%m-%dT%H:%M:%SZ'
230 date_created = time.strftime(fmt, timestamp)
233 cmdline =
' '.join([
basename(sys.argv[0])]+sys.argv[1:])
234 cmdline =
''.join([date_created,
': ', cmdline])
235 if 'history' in dataset.ncattrs():
236 history =
''.join([dataset.history.strip(),
'; ', cmdline])
240 dataset.setncattr(
'date_created', date_created)
241 dataset.setncattr(
'history', history)