Source code for omas.omas_ds

'''save/load from xarray dataset routines

-------
'''

from .omas_utils import *
from .omas_core import ODS, omas_environment
import itertools


[docs]class ODX(MutableMapping): """ OMAS data xarray class """ def __init__(self, DS=None): self.omas_data = DS self.ucache = {} if DS is not None: for k in self.omas_data.data_vars: self.ucache.setdefault(o2u(k), []).append(k) def __delitem__(self, key): return self.omas_data.__delitem__(key) def __getitem__(self, key): # return data if key is exactly in dataset if key in self.omas_data: return self.omas_data[key].values # identify which element in DS has the requested data ukey = None for k in self.ucache[o2u(key)]: if u2o(key, k) == k: ukey = k break # slice the data as requested tmp = self.omas_data[ukey].values for uk, k in zip(p2l(ukey), p2l(key)): if uk == ':' and isinstance(k, int): tmp = tmp[k] # return data return tmp def __getattr__(self, attr): # avoid picking up deepcopy and pickling methods from dataset if attr in ['__deepcopy__', '__getstate__', '__setstate__']: raise AttributeError('bad attribute `%s`' % attr) return getattr(self.omas_data, attr) def __iter__(self): return self.omas_data.__iter__() def __len__(self): return self.omas_data.__len__() def __setitem__(self, key, value): if key in self.omas_data.data_vars: self.omas_data[key].values[:] = value
[docs] def save(self, *args, **kw): return save_omas_dx(self, *args, **kw)
[docs] def load(self, *args, **kw): ods = load_omas_dx(*args, **kw) self.omas_data = ods.omas_data return self
[docs] def to_ods(self, consistency_check=True): """ Generate a ODS from current ODX :param consistency_check: use consistency_check flag in ODS :return: ODS """ return odx_2_ods(self, consistency_check=consistency_check)
[docs]def save_omas_ds(ods, filename): """ Save an ODS to xarray dataset :param ods: OMAS data set :param filename: filename or file descriptor to save to """ DS = ods.dataset() return DS.to_netcdf(filename, format="NETCDF4")
[docs]def load_omas_dx(filename, consistency_check=True): """ Load ODX from xarray dataset :param filename: filename or file descriptor to load from :param consistency_check: verify that data is consistent with IMAS schema :return: OMAS data xarray """ import xarray DS = xarray.open_dataset(filename, engine="netcdf4") DS.load() DS.close() return ODX(DS)
[docs]def save_omas_dx(odx, filename): """ Save an ODX to xarray dataset :param odx: OMAS data xarray :param filename: filename or file descriptor to save to """ return odx.omas_data.to_netcdf(filename, format="NETCDF4")
[docs]def ods_2_odx(ods, homogeneous=None): """ Map ODS to an ODX :param ods: OMAS data set :param homogeneous: * False: flat representation of the ODS (data is not collected across arrays of structures) * 'time': collect arrays of structures only along the time dimension (always valid for homogeneous_time=True) * 'full': collect arrays of structures along all dimensions (may be valid in many situations, especially related to simulation data with homogeneous_time=True and where for example number of ions, sources, etc. do not vary) * None: smart setting, uses homogeneous='time' if homogeneous_time=True else False :return: OMAS data xarray """ return ODX(ods.dataset(homogeneous=homogeneous))
[docs]def odx_2_ods(odx, consistency_check=True): """ Map ODX to ODS :param odx: OMAS data xarray :param consistency_check: verify that data is consistent with IMAS schema :return: OMAS data set """ DS = odx.omas_data ods = ODS(consistency_check=False) with omas_environment(ods, dynamic_path_creation='dynamic_array_structures'): for uitem in DS.data_vars: depth = uitem.count(':') value = DS[uitem].values if not depth: ods[uitem] = value continue # unroll for kkk in itertools.product(*map(range, DS[uitem].shape[:depth])): item = uitem.replace(':', '{}').format(*kkk) tmp = value for k in kkk: tmp = tmp[k] ods[item] = tmp ods.consistency_check = consistency_check return ods
[docs]def load_omas_ds(filename, consistency_check=True): """ Load ODS from xarray dataset :param filename: filename or file descriptor to load from :param consistency_check: verify that data is consistent with IMAS schema :return: OMAS data set """ import xarray DS = xarray.open_dataset(filename, engine="netcdf4") DS.load() DS.close() odx = ODX(DS) ods = odx_2_ods(odx, consistency_check=consistency_check) return ods
[docs]def through_omas_ds(ods, method=['function', 'class_method'][1]): """ Test save and load ODS via xarray file format :param ods: OMAS data set :return: OMAS data set """ filename = omas_testdir(__file__) + '/test.ds' ods = copy.deepcopy(ods) # make a copy to make sure save does not alter entering ODS if method == 'function': save_omas_ds(ods, filename) ods1 = load_omas_ds(filename) else: ods.save(filename) ods1 = ODS().load(filename) return ods1
[docs]def through_omas_dx(odx, method=['function', 'class_method'][1]): """ Test save and load OMAS data xarray via xarray file format :param ods: OMAS data xarray :return: OMAS data xarray """ filename = omas_testdir(__file__) + '/test.dx' odx = copy.deepcopy(odx) # make a copy to make sure save does not alter entering ODX if method == 'function': save_omas_dx(odx, filename) odx1 = load_omas_dx(filename) else: odx.save(filename) odx1 = ODX().load(filename) return odx1