Source code for ncempy.eval.ring_diff

"""
Module to process ring diffraction patterns.
"""

import ncempy.algo.local_max
import ncempy.algo.distortion
import ncempy.algo.radial_profile
import ncempy.algo.math
import ncempy.io.emd

#import matplotlib.pyplot as plt
import numpy as np
import h5py


# used to indicate settings format
cur_set_vers = 'ring_diffraction_setting_vers0.1'
'''str : Used to identify settings hdf5 groups.'''

cur_eva_vers = 'ring_diffraction_evaluation_vers0.1'
'''str : Used to identify evaluation hdf5 groups.'''

dummy_settings = {'lmax_r': 1,
                    'lmax_thresh': 1,
                    'lmax_cinit': (1,1),
                    'lmax_range': (1.,2.),
                    'plt_imgminmax': (0.0,1.0),
                    'ns': (1,),
                    'rad_rmax': 1,
                    'rad_dr': 0.1,
                    'rad_sigma': 0.1,
                    'mask': np.ones((5,5)),
                    'fit_rrange': (1.0, 2.0),
                  'back_xs': (1.0, 2.0, 3.0),
                  'back_xswidth': 0.1,
                  'back_init': (1.0, 1.0, 1.0),
                  'fit_funcs': ('voigt',),
                  'fit_init': (1.0, 1.0, 1.0, 1.0),
                  'fit_maxfev':10
                  }
'''dict : Dummy settings with all parameters set.'''

min_dummy_settings = {'lmax_r': 1,
                        'lmax_thresh': 1,
                        'lmax_cinit': (1,1),
                        'lmax_range': (1.,2.),
                        'plt_imgminmax': None,
                        'ns': (1,),
                        'rad_rmax': None,
                        'rad_dr': None,
                        'rad_sigma': None,
                        'mask': None,
                        'fit_rrange': (1.0, 2.0),
                      'back_xs': (1.0, 2.0, 3.0),
                      'back_xswidth': 0.1,
                      'back_init': (1.0, 1.0, 1.0),
                      'fit_funcs': ('voigt',),
                      'fit_init': (1.0, 1.0, 1.0, 1.0),
                      'fit_maxfev': None
                      }
'''dict : Dummy settings with all parameters set but all optional ones as Nones.'''


[docs]def get_settings( parent ): """Get settings for radial profile evaluation. Parameters ---------- parent : h5py.Group Input group. Returns ------- : dict Settings read from parent. """ try: assert(isinstance(parent, h5py._hl.group.Group)) except: raise TypeError('Something wrong with the input.') if not parent.attrs['type'] == np.string_(cur_set_vers): print('Don\'t know the format of these settings.') return None settings = {} settings['lmax_r'] = parent.attrs['lmax_r'] settings['lmax_thresh'] = parent.attrs['lmax_thresh'] settings['lmax_cinit'] = parent.attrs['lmax_cinit'] settings['lmax_range'] = parent.attrs['lmax_range'] settings['ns'] = parent.attrs['ns'] settings['fit_rrange'] = parent.attrs['fit_rrange'] settings['back_xs'] = parent.attrs['back_xs'] settings['back_xswidth'] = parent.attrs['back_xswidth'] settings['back_init'] = parent.attrs['back_init'] settings['fit_init'] = parent.attrs['fit_init'] if isinstance(parent.attrs['fit_funcs'], np.ndarray): in_funcs = parent.attrs['fit_funcs'][0] else: in_funcs = parent.attrs['fit_funcs'] in_funcs = in_funcs.split(b',') out_funcs = [] for i in range(len(in_funcs)): out_funcs.append(in_funcs[i].decode('utf-8').strip()) settings['fit_funcs'] = tuple(out_funcs) if 'plt_imgminmax' in parent.attrs: settings['plt_imgminmax'] = parent.attrs['plt_imgminmax'] else: settings['plt_imgminmax'] = None if 'rad_rmax' in parent.attrs: settings['rad_rmax'] = parent.attrs['rad_rmax'] else: settings['rad_rmax'] = None if 'rad_dr' in parent.attrs: settings['rad_dr'] = parent.attrs['rad_dr'] else: settings['rad_dr'] = None if 'rad_sigma' in parent.attrs: settings['rad_sigma'] = parent.attrs['rad_sigma'] else: settings['rad_sigma'] = None if 'mask' in parent: settings['mask'] = np.copy(parent['mask']) else: settings['mask'] = None if 'fit_maxfev' in parent.attrs: settings['fit_maxfev'] = parent.attrs['fit_maxfev'] else: settings['fit_maxfev'] = None return settings
[docs]def put_settings( parent, settings ): """Put settings for radial profile evaluation. Creates a subgroup in parent holding the settings as attributes. Parameters ---------- parent : h5py.Group Group to hold settings subgroup. setting : dict Settings to write. Returns ------- : h5py.Group Handle to settings group. """ try: assert( isinstance(parent, h5py._hl.group.Group) ) assert( type(settings) is dict ) except: raise TypeError('Something wrong with the input.') try: grp_set = parent.create_group('settings_ringdiffraction') except: raise RuntimeError('Could not write to {}'.format(parent)) # set version information grp_set.attrs['type'] = np.string_(cur_set_vers) # hardcoding the written settings to keep control grp_set.attrs['lmax_r'] = settings['lmax_r'] grp_set.attrs['lmax_thresh'] = settings['lmax_thresh'] grp_set.attrs['lmax_cinit'] = settings['lmax_cinit'] grp_set.attrs['lmax_range'] = settings['lmax_range'] grp_set.attrs['ns'] = settings['ns'] grp_set.attrs['fit_rrange'] = settings['fit_rrange'] grp_set.attrs['back_xs'] = settings['back_xs'] grp_set.attrs['back_xswidth'] = settings['back_xswidth'] grp_set.attrs['back_init'] = settings['back_init'] grp_set.attrs['fit_init'] = settings['fit_init'] fit_funcs = [] for i in range(len(settings['fit_funcs'])): fit_funcs.append(settings['fit_funcs'][i]) grp_set.attrs['fit_funcs'] = np.string_(', '.join(fit_funcs)) if not settings['plt_imgminmax'] is None: grp_set.attrs['plt_imgminmax'] = settings['plt_imgminmax'] if not settings['rad_rmax'] is None: grp_set.attrs['rad_rmax'] = settings['rad_rmax'] if not settings['rad_dr'] is None: grp_set.attrs['rad_dr'] = settings['rad_dr'] if not settings['rad_sigma'] is None: grp_set.attrs['rad_sigma'] = settings['rad_sigma'] if not settings['mask'] is None: grp_set.create_dataset('mask', data=settings['mask']) if not settings['fit_maxfev'] is None: grp_set.attrs['fit_maxfev'] = settings['fit_maxfev'] return grp_set
[docs]def put_sglgroup(parent, label, data_grp): """Adds the evaluation into parent. Remember that the resource of the external link must not be already opened elsewhere to access data. Parameters ---------- parent : h5py.Group Hdf5 group to add this evaluation group to. label : str Label for the evaluation group. data_grp : h5py.Group Emdtype group where to find the data. Returns ------- : h5py.Group Handle to group. """ try: assert( isinstance(parent, h5py._hl.group.Group) ) label = str(label) assert( isinstance(data_grp, h5py._hl.group.Group) ) except TypeError: raise TypeError('Something wrong with the input') # create the evaluation group grp = parent.create_group(label) grp.attrs['type'] = np.string_(cur_eva_vers) # put a link to the data grp.attrs['filename'] = np.string_(data_grp.file.filename) grp.attrs['internal_path'] = np.string_(data_grp.name) #grp['emdgroup'] = h5py.ExternalLink(data_grp.file.filename, data_grp.name) return grp
[docs]def run_sglgroup(group, outfile, overwrite=False, verbose=False, showplots=False): """Run evaluation on a single group. Parameters ---------- group : h5py.Group Handle to evaluation group to execute. outfile : ncempy.io.emd.fileEMD Emdfile for output. overwrite : bool Set to overwrite existing results in outfile. verbose : bool Set to get verbose output during run. showplots : bool Set to directly show plots interactively. """ try: assert(isinstance(group, h5py._hl.group.Group)) assert( group.attrs['type'] == np.string_(cur_eva_vers) ) assert(isinstance(outfile, ncempy.io.emd.fileEMD)) except: raise TypeError('Something wrong with the input.') if verbose: print('Running evaluation of "{}".'.format(group.name)) # get the emdgroup if verbose: print('.. getting data from {}:{}'.format(group.attrs['filename'].decode('utf-8'), group.attrs['internal_path'].decode('utf-8'))) readfile = ncempy.io.emd.fileEMD( group.attrs['filename'].decode('utf-8'), readonly=True ) data, dims = readfile.get_emdgroup(readfile.file_hdl[group.attrs['internal_path'].decode('utf-8')]) # find the settings moving upwards in hierarchy if verbose: print('.. searching for settings.') def proc_group(grp): #print('scanning group {}'.format(grp)) if 'settings_ringdiffraction' in grp: stt = grp['settings_ringdiffraction'] if stt.attrs['type'] == np.string_(cur_set_vers): return stt else: if not grp == grp.file: return proc_group(grp.parent) grp_set = proc_group(group) if grp_set is None: raise RuntimeError('Could not find settings in evaluation group or its parents.') else: if verbose: print('.. loading settings from {}.'.format(grp_set.name)) settings = get_settings(grp_set) # what data to collect profiles = None centers = None distss = None fits = None rawprofiles = None fits_back = None # run evaluation with settings if len(data.shape) == 3: for i in range(data.shape[0]): profile, res, center, dists, rawprofile, res_back, myset = ncempy.algo.radial_profile.run_singleImage( data[i,:,:], dims[1:3], settings, show=showplots) # after first run I know the size if profiles is None: profiles = np.zeros( (profile.shape[0], data.shape[0]) ) fits = np.zeros( (res.shape[0], data.shape[0]) ) centers = np.zeros( (2, data.shape[0]) ) distss = np.zeros( (dists.shape[0], data.shape[0]) ) rawprofiles = np.zeros( (rawprofile.shape[0], data.shape[0]) ) fits_back = np.zeros( (res_back.shape[0], data.shape[0]) ) # assign data profiles[:, i] = profile[:, 1] fits[:, i] = res[:] centers[:, i] = center[:] distss[:, i] = dists[:] rawprofiles[:, i] = rawprofile[:, 1] fits_back[:, i] = res_back[:] # save results in this group outfile.put_emdgroup('radial_profile', profiles, ( (profile[:,0], 'radial distance', dims[2][2]) , dims[0]), parent=group, overwrite=overwrite) outfile.put_emdgroup('fit_results', fits, ( ( np.array(range(fits.shape[0])), 'parameters', '[]') , dims[0]), parent=group, overwrite=overwrite) outfile.put_emdgroup('centers', centers, ( ( np.array(range(2)), 'dimension', dims[2][2]) , dims[0]), parent=group, overwrite=overwrite) outfile.put_emdgroup('distortions', distss, ( ( np.array(range(distss.shape[0])), 'parameters', '[]') , dims[0]), parent=group, overwrite=overwrite) outfile.put_emdgroup('radial_profile_noback', rawprofiles, ( (rawprofile[:,0], 'radial distance', dims[2][2]) , dims[0]), parent=group, overwrite=overwrite) outfile.put_emdgroup('back_results', fits_back, ( ( np.array(range(fits_back.shape[0])), 'background parameters', '[]') , dims[0]), parent=group, overwrite=overwrite) elif len(data.shape) == 2: profile, res, center, dists, rawprofile, res_back, myset = ncempy.algo.radial_profile.run_singleImage( data[:,:], dims, settings, show=showplots) # save results in this group outfile.put_emdgroup('radial_profile', profile[:,1], ( (profile[:,0], 'radial distance', dims[0][2]), ), parent=group, overwrite=overwrite) outfile.put_emdgroup('fit_results', res, ( ( np.array(range(res.shape[0])), 'parameters', '[]'), ), parent=group, overwrite=overwrite) outfile.put_emdgroup('centers', center, ( ( np.array(range(2)), 'dimension', dims[0][2]), ), parent=group, overwrite=overwrite) outfile.put_emdgroup('distortions', dists, ( ( np.array(range(dists.shape[0])), 'parameters', '[]'), ), parent=group, overwrite=overwrite) outfile.put_emdgroup('radial_profile_noback', rawprofile[:,1], ( (rawprofile[:,0], 'radial distance', dims[0][2]), ), parent=group, overwrite=overwrite) outfile.put_emdgroup('back_results', res_back, ( ( np.array(range(res_back.shape[0])), 'background parameters', '[]'), ), parent=group, overwrite=overwrite) else: raise RuntimeError('Cannot handle that data.') # save a log comment outfile.put_comment('Evaluated "{}" using ring diffraction analysis.'.format(group.name))
[docs]def run_all(parent, outfile, overwrite=False, verbose=False, showplots=False): """ Run on a set-up emd file to do evaluations and save results. All evaluations within parent are run. Parameters ---------- parent : h5py.Group Handle to parent. outfile : ncempy.io.emd.fileEMD Emdfile for output. overwrite : bool Set to overwrite existing results in outfile. verbose : bool Set to get verbose output during run. showplots : bool Set to directly show plots interactively. """ # get all groups with evaluations to do todo = [] # recursive function def proc_group(grp, todo): for item in grp: if grp.get(item, getclass=True) == h5py._hl.group.Group: item = grp.get(item) if 'type' in item.attrs: if item.attrs['type'] == np.string_(cur_eva_vers): todo.append(item) if verbose: print('Found evaluation group at "{}".'.format(item.name) ) proc_group(item, todo) proc_group(parent, todo) # run through all evaluations for i in range(len(todo)): run_sglgroup(todo[i], outfile, overwrite=overwrite, verbose=verbose, showplots=showplots)