Commit 287f444b authored by payno's avatar payno

[core][io] rework saving of process results.

There was a bug when saving ft.radius... that can be nan or numpy array. When try to save it as a numpy array then it ends up as an array of dtype 'object'.
So to fix it we now store this as a dictionnary.
And we add a try-except section when saving keys if return in the future is unsafe for hdf5.
parent 7b795852
......@@ -121,7 +121,6 @@ class Process(object):
:param xas_obj: object for which we want to save the treatment
:type: :class:`.XASObject`
:param tuple data_keys: keys of the id to save
:param str relative_to: x value
"""
if xas_obj.has_linked_file():
_data = {}
......@@ -140,6 +139,7 @@ class Process(object):
elif key in ('ft.radius', 'ft.intensity', 'ft.imaginary'):
relative_to = 'radius'
use = '_list_res_ft'
if use == '_spectra_volume':
# if we can display the result as a numpy.array 3d
try:
......@@ -153,10 +153,15 @@ class Process(object):
_logger.error(mess)
elif use == '_list_res_ft':
res = []
# for ft we are force to have a dictionary because it
# processing can end with a nan or with a numpy array.
# combining both would make us end up with a ndarray of
# object type
key_ = key.split('.')[-1]
res = {}
for spectrum in xas_obj.spectra:
res.append(getattr(spectrum.ft, key_))
x, y = spectrum.x, spectrum.y
res['_'.join((str(x), str(y)))] = getattr(spectrum.ft, key_)
_data[key] = res
else:
raise ValueError()
......
......@@ -77,7 +77,6 @@ def process_spectr_ft(spectrum, configuration, overwrite=True, callbacks=None,
return None, None
if 'EXAFSNormalized' not in spectrum:
raise ValueError()
_logger.warning('ft window need to be defined first')
return None, None
......
......@@ -1012,9 +1012,9 @@ class _FT(object):
_IMAGINARY_KEY = 'FTImaginary'
def __init__(self, ddict):
self.__radius = None
self.__intensity = None
self.__imaginary = None
self.__radius = numpy.nan
self.__intensity = numpy.nan
self.__imaginary = numpy.nan
self.__other_parameters = {}
self.__key_mapper = {
......
......@@ -359,7 +359,9 @@ class SpectrumViewer(qt.QMainWindow):
if new_curves_op is not None:
curves += new_curves_op
for res in curves:
if res is not None and res.x is not None:
# result can be None or nan if the processing fails. So in this
# case we won't display anything
if res is not None and res.x is not None and res.x is not numpy.nan:
if isinstance(res, _CurveOperation):
kwargs = {
'x': res.x,
......
......@@ -217,7 +217,7 @@ def write_xas_proc(h5_file, entry, process, data, processing_order,
:type: str
"""
process_name = 'xas_process_' + str(processing_order)
# write the xasproc
# write the xasproc default information
with h5py.File(h5_file, 'a') as h5f:
nx_entry = h5f.require_group('/'.join((data_path, entry)))
nx_entry.attrs["NX_class"] = "NXentry"
......@@ -226,7 +226,7 @@ def write_xas_proc(h5_file, entry, process, data, processing_order,
nx_process.attrs['NX_class'] = "NXprocess"
if overwrite:
for key in ('program', 'version', 'date', 'processing_order',
'class_instance'):
'class_instance', 'ft'):
if key in nx_process:
del nx_process[key]
nx_process['program'] = process.program_name()
......@@ -240,30 +240,52 @@ def write_xas_proc(h5_file, entry, process, data, processing_order,
nx_data = nx_entry.require_group('data')
nx_data.attrs['NX_class'] = "NXdata"
nx_data.attrs['signal'] = 'data'
nx_process_path = nx_process.name
def get_interpretation(mydata):
if isinstance(mydata, numpy.ndarray):
if mydata.ndim is 1:
return 'spectrum'
elif mydata.ndim in (2, 3):
return 'image'
return None
if isinstance(data, numpy.ndarray):
data_ = {'data': data}
else:
data_ = data
def get_interpretation(my_data):
"""Return hdf5 attribute for this type of data"""
if isinstance(my_data, numpy.ndarray):
if my_data.ndim is 1:
return 'spectrum'
elif my_data.ndim in (2, 3):
return 'image'
return None
if isinstance(data, numpy.ndarray):
data_ = {'data': data}
def save_key(key_path, value):
"""Save the given value to the associated path. Manage numpy arrays
and dictionaries"""
key_path = key_path.replace('.', '/')
print('saving', key_path, 'type is', type(value))
# save if is dict
if isinstance(value, dict):
h5_path = '/'.join((entry, process_name, key_path))
dicttoh5(value, h5file=h5_file, h5path=h5_path,
overwrite_data=True, mode='a')
else:
data_ = data
for key, value in data_.items():
nx_process[key] = value
interpretation = get_interpretation(value)
if interpretation:
nx_process[key].attrs['interpretation'] = interpretation
nx_process_path = str(nx_process.name)
with h5py.File(h5_file, 'a') as h5f:
nx_process = h5f.require_group(nx_process_path)
try:
nx_process[key_path] = value
except TypeError as e:
_logger.error('Unable to write', str(key_path), 'reason is', str(e))
else:
interpretation = get_interpretation(value)
if interpretation:
nx_process[key_path].attrs['interpretation'] = interpretation
for key, value in data_.items():
save_key(key_path=key, value=value)
if process.getConfiguration() is not None:
h5_path = '/'.join((nx_process_path, 'configuration'))
dicttoh5(process.getConfiguration(),
h5file=h5_file,
h5path='/'.join((nx_process_path, 'configuration')),
h5path=h5_path,
overwrite_data=True,
mode='a')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment