Source code for stompy.model.delft.nefis_nc

"""
Converting between nefis and netcdf
In a separate module to separate dependencies

Relies on the qnc wrapper of netcdf4
"""

from collections import defaultdict
from ...io import qnc

[docs]def nefis_to_nc(nef,squeeze_unl=True,squeeze_element=True, short_if_unique=True,to_lower=True,unl_name='time', element_map={},nc_kwargs={},nc=None): """ nef: an open Nefis object squeeze_unl: unit length unlimited dimensions in groups are dropped groups can't be dimensionless, so parameter values are often in a unit-length group. short_if_unique: element names which appear in only one group get just the element name. others are group_element to_lower: make names lower case squeeze_element: unit dimensions in elements are also removed unl_name: if there is a unique unlimited dimension length (ignoring unit lengths if squeeze_unl is set) - use this name for it. element_map: map original element names to new names. this matches against element names before to_lower (but after strip), and the results will *not* be subject to to_lower. nc_kwargs: dict of argument to pass to qnc.empty nc: altenatively, an already open QDataset """ if nc is None: nc=qnc.empty(**nc_kwargs) # required for writing to disk nc._set_string_mode('fixed') # string handling is a little funky - # still working out whether it should be varlen or fixed. # fixed makes the string length a new dimension, just annoying # to get strings back from that. # varlen ends up having an object dtype, which may not write out # well with netcdf. # check for unique element names name_count=defaultdict(lambda: 0) for group in nef.groups(): for elt_name in group.cell.element_names: name_count[elt_name]+=1 # check for unique unlimited dimension: n_unl=0 for group in nef.groups(): if 0 in group.shape and (group.unl_length()>1 or not squeeze_unl): n_unl+=1 for group in nef.groups(): # print group.name g_shape=group.shape grp_slices=[slice(None)]*len(g_shape) grp_dim_names=[None]*len(g_shape) if 0 in g_shape: # has an unlimitied dimension idx=list(g_shape).index(0) if group.unl_length()==1 and squeeze_unl: # which will be squeezed grp_slices[idx]=0 elif n_unl==1 and unl_name: # which will be named grp_dim_names[idx]=unl_name for elt_name in group.cell.element_names: # print elt_name if name_count[elt_name]==1 and short_if_unique: vname=elt_name else: vname=group.name + "_" + elt_name if vname in element_map: vname=element_map[vname] elif to_lower: vname=vname.lower() value=group.getelt(elt_name) # apply slices value=value[tuple(grp_slices)] if squeeze_element: # slices specific to this element val_slices=[slice(None)]*len(value.shape) # iterate over just the element portion of the shape for idx in range(len(g_shape),len(val_slices)): if value.shape[idx]==1: val_slices[idx]=0 value=value[val_slices] # mimics qnc naming. names=[qnc.anon_dim_name(size=l) for l in value.shape] for idx,name in enumerate(grp_dim_names): if name: names[idx]=name names.append(Ellipsis) nc[vname][names] = value setattr(nc.variables[vname],'group_name',group.name) return nc