Source code for omas.omas_nc
'''save/load from NC routines
-------
'''
from .omas_utils import *
from .omas_core import ODS, ODC, dynamic_ODS
# --------------------------------------------
# save and load OMAS with NetCDF
# --------------------------------------------
[docs]def save_omas_nc(ods, filename, **kw):
"""
Save an ODS to NetCDF file
:param ods: OMAS data set
:param filename: filename to save to
:param kw: arguments passed to the netCDF4 Dataset function
"""
printd('Saving to %s' % filename, topic='nc')
from netCDF4 import Dataset
odsf = ods.flat()
with Dataset(filename, 'w', **kw) as dataset:
for item in odsf:
dims = []
data = numpy.asarray(odsf[item])
std = None
if is_uncertain(odsf[item]):
std = std_devs(data)
data = nominal_values(data)
for k in range(len(numpy.asarray(odsf[item]).shape)):
dims.append('dim_%d' % (data.shape[k]))
if dims[-1] not in dataset.dimensions:
dataset.createDimension(dims[-1], data.shape[k])
if std is None:
dataset.createVariable(item, data.dtype, dims)[:] = data
else:
dataset.createVariable(item, data.dtype, dims)[:] = data
dataset.createVariable(item + '_error_upper', data.dtype, dims)[:] = std
def get_ds_item(dataset, item):
"""
Convenience function for loading OMAS data stored in a NC file variable
Handles arrays, scalars, strings, and uncertain quantities
:param dataset: nc dataset
:param item: variable name
:return: data
"""
if dataset.variables[item].shape:
# arrays
if item + '_error_upper' in dataset.variables.keys():
tmp = uarray(numpy.array(dataset.variables[item]), numpy.array(dataset.variables[item + '_error_upper']))
else:
tmp = numpy.array(dataset.variables[item])
else:
# uncertain scalars
if item + '_error_upper' in dataset.variables.keys():
tmp = ufloat(dataset.variables[item][0].item(), dataset.variables[item + '_error_upper'][0].item())
else:
try:
# scalars
tmp = dataset.variables[item][0].item()
except AttributeError:
# strings
tmp = dataset.variables[item][0]
return tmp
[docs]def load_omas_nc(filename, consistency_check=True, imas_version=omas_rcparams['default_imas_version'], cls=ODS):
"""
Load ODS or ODC from NetCDF file
:param filename: filename to load from
:param consistency_check: verify that data is consistent with IMAS schema
:param imas_version: imas version to use for consistency check
:param cls: class to use for loading the data
:return: OMAS data set
"""
printd('Loading from %s' % filename, topic='nc')
from netCDF4 import Dataset
ods = cls(imas_version=imas_version, consistency_check=False)
with Dataset(filename, 'r') as dataset:
for item in dataset.variables.keys():
if item.endswith('_error_upper'):
continue
ods.setraw(p2l(item), get_ds_item(dataset, item))
ods.consistency_check = consistency_check
return ods
class dynamic_omas_nc(dynamic_ODS):
"""
Class that provides dynamic data loading from NC file
This class is not to be used by itself, but via the ODS.open() method.
"""
def __init__(self, filename):
self.kw = {'filename': filename}
self.dataset = None
self.active = False
def open(self):
printd('Dynamic open %s' % self.kw, topic='dynamic')
from netCDF4 import Dataset
self.dataset = Dataset(self.kw['filename'], 'r')
self.active = True
return self
def close(self):
printd('Dynamic close %s' % self.kw, topic='dynamic')
self.dataset.close()
self.dataset = None
self.active = False
return self
def __getitem__(self, key):
if not self.active:
raise RuntimeError('Dynamic link broken: %s' % self.kw)
printd('Dynamic read %s: %s' % (self.kw['filename'], key), topic='dynamic')
return get_ds_item(self.dataset, key)
def __contains__(self, key):
if not self.active:
raise RuntimeError('Dynamic link broken: %s' % self.kw)
return key in self.dataset.variables
def keys(self, location):
return numpy.unique(
[convert_int(k[len(location) :].lstrip('.').split('.')[0]) for k in self.dataset.variables.keys() if k.startswith(location)]
)
[docs]def through_omas_nc(ods, method=['function', 'class_method'][1]):
"""
Test save and load NetCDF
:param ods: ods
:return: ods
"""
filename = omas_testdir(__file__) + '/test.nc'
ods = copy.deepcopy(ods) # make a copy to make sure save does not alter entering ODS
if method == 'function':
save_omas_json(ods, filename)
ods1 = load_omas_json(filename)
else:
ods.save(filename)
ods1 = ODS().load(filename)
return ods1