def FromDict(self, dict_source): """ Initialize kernel from dictionnary Parameters ---------- dict_source : dict. Must have the following keys: ['shape', 'type', 'padding'] """ assert ('shape' in dict_source and 'type' in dict_source and 'padding' in dict_source), 'Source dict missing required keys' _shape = sf.StrParse(dict_source['shape'], int) _type = str(dict_source['type']) _padding = sf.StrParse(dict_source['padding'], bool) if (_type == 'Gauss'): assert 'sigma' in dict_source, 'Gaussian kernel dict missing sigma key' _params = {'sigma': sf.StrParse(dict_source['sigma'], float)} else: _params = {} if 'n_dim' in dict_source: n_dim = int(dict_source['n_dim']) else: n_dim = len(_shape) _conv_kwargs = {} if 'convolve_kwargs' in dict_source: _conv_kwargs.update(sf.StrParse(dict_source['convolve_kwargs'])) self.Initialize(_shape, _type, _params, n_dim, _padding, _conv_kwargs)
def OpenG2M1s(froot, expt_idx=None, roi_idx=None): res = [] filter_str = '' if roi_idx is not None: filter_str += '_' + ROI_PREFIX + str(roi_idx).zfill(ROI_IDXLEN) if expt_idx is not None: filter_str += '_' + EXP_PREFIX + +str(expt_idx).zfill(EXP_IDXLEN) fnames_list = sf.FindFileNames(froot, Prefix=G2M1_PREFIX, Ext='.dat', FilterString=filter_str, Sort='ASC') ROI_list = [sf.FirstIntInStr(name) for name in fnames_list] exptime_list = [sf.LastIntInStr(name) for name in fnames_list] lagtimes = [] imgtimes = [] for i, fname in enumerate(fnames_list): res_g2m1, res_hdr = sf.LoadResFile(os.path.join(froot, fname), delimiter=TXT_DELIMITER, comments=TXT_COMMENT, readHeader=True, isolateFirst=0) res.append(res_g2m1[:, 1::2].T) lagtimes.append(res_g2m1[:, ::2].T) imgtimes.append( np.asarray([ sf.FirstFloatInStr(res_hdr[j]) for j in range(1, len(res_hdr), 2) ])) return res, lagtimes, imgtimes, ROI_list, exptime_list
def ReadCIfile(self, fname): roi_idx = sf.FirstIntInStr(fname) exp_idx = sf.LastIntInStr(fname) cur_cI = np.loadtxt(os.path.join(self.outFolder, fname), **self.loadtxt_kwargs) cur_times = cur_cI[:, 0] cur_cI = cur_cI[:, 1:] # skip first row with image times if (cur_cI.shape != (self.NumTimes(), self.NumLagtimes())): logging.warning( 'cI result file {0} potentially corrupted: shape {1} does not match expected {2}' .format(fname, cur_cI.shape, (self.NumTimes(), self.NumLagtimes()))) return cur_cI, cur_times, roi_idx, exp_idx
def Initialize(self, shape, kernel_type, params={}, n_dim=2, padding=False, convolve_kwargs={}): """ Initialize kernel Parameters ---------- shape : tuple of integers, shape of the output kernel matrix. entries must be odd integers number of entries must match dimensions (n_dim) kernel_type : string, type of kernel. Supported types: ['Gauss', 'flat'] params : dict with type-dependent parameters n_dim : dimensions. Currently only n_dim=2 is supported padding : boolean. If True convolution will be performed using 'same' mode otherwise, only 'valid' convolutions will be accepted (smaller output) convolve_kwargs : dict with additional parameters to be passed to scipy.signal.convolve2d """ assert kernel_type in ['Gauss', 'flat' ], 'Kernel type "' + str() + '" not supported' self.Type = kernel_type self.Shape = sf.CheckIterableVariable(shape, n_dim, cast_type=int) self.Dimensions = n_dim self.Center = np.true_divide(np.subtract(self.Shape, 1), 2) if (kernel_type == 'Gauss'): self.KernelParams = self.GaussParams( sf.CheckIterableVariable(params['sigma'], n_dim)) elif (kernel_type == 'flat'): self.KernelParams = None self.SetPadding(padding) if 'boundary' not in convolve_kwargs: convolve_kwargs['boundary'] = 'fill' if 'fillvalue' not in convolve_kwargs: convolve_kwargs['fillvalue'] = 0 self.convolve_kwargs = convolve_kwargs
def OpenSLS(froot, open_raw=False): if open_raw: fname = os.path.join(froot, SLS_RAW_FNAME) else: fname = os.path.join(froot, SLS_FNAME) res_Ir, res_hdr, r_phi = sf.LoadResFile(fname, delimiter=TXT_DELIMITER, comments=TXT_COMMENT, readHeader=True, isolateFirst=2) times = np.asarray([sf.FirstFloatInStr(hdr) for hdr in res_hdr]) if open_raw: exptimes = np.asarray([sf.LastFloatInStr(hdr) for hdr in res_hdr]) return np.squeeze( res_Ir.reshape( (res_Ir.shape[0], -1, len(set(exptimes))))), r_phi[:, 0], r_phi[:, 1], times, exptimes else: return res_Ir, r_phi[:, 0], r_phi[:, 1], times
def OpenCIs(froot): res = [] fnames_list = sf.FindFileNames(froot, Prefix=CI_PREFIX + '_', Ext='.dat', Sort='ASC') ROI_list = [sf.FirstIntInStr(name) for name in fnames_list] exptime_list = [sf.LastIntInStr(name) for name in fnames_list] lagtimes = [] imgtimes = [] for i, fname in enumerate(fnames_list): res_cI, res_hdr, col_times = sf.LoadResFile(os.path.join(froot, fname), delimiter=TXT_DELIMITER, comments=TXT_COMMENT, readHeader=True, isolateFirst=1) res.append(res_cI) lagtimes.append(np.asarray([sf.FirstIntInStr(hdr) for hdr in res_hdr])) imgtimes.append(col_times) return res, imgtimes, lagtimes, ROI_list, exptime_list
def LoadFolder(mi_folder, config_fname, config_section='MIfile', mi_prefix='', mi_ext='.dat', mi_sort='ASC', open_mifiles=True, stack_type='tau'): """Searches for MIfiles in a folder and loads them Parameters ---------- mi_folder : folder to search. config_fname : full path of configuration filename config_section : title of the configuration section mi_prefix : filter only files in folder whose filename begins with mi_prefix mi_ext : filter only files in folder whose filename ends with mi_ext mi_sort : sort filenames in ascending (ASC) or descending (DESC) order open_mifiles : if True, open all MIfiles for reading stack_type : {'tau','t'}, sets MIstack.StackType Returns ------- conf_cmaps: configuration file for correlation maps cmap_mifiles: list of correlation maps, one per time delay all_lagtimes: list of lagtimes """ assert os.path.isdir( mi_folder), 'MIfile folder ' + str(mi_folder) + ' not found.' assert os.path.isfile( config_fname), 'Configuration file ' + str(config_fname) + ' not found' all_mi_fnames = sf.FindFileNames(mi_folder, Prefix=mi_prefix, Ext=mi_ext, Sort=mi_sort, AppendFolder=True) mi_stack = MIstack(MIfiles=all_mi_fnames, MetaData=config_fname, MetaDataSection=config_section, Load=True, OpenFiles=open_mifiles, StackType=stack_type) return mi_stack
def Get(self, sect, key, default=None, cast_type=None, silent=True): """Gets configuration entry Parameters ---------- sect : section name (string) key : key name (string) default : variable to be returned if section/key is not present cast_type : if not None, cast variable to type default type is string silent : output default without printing any warning message Returns ------- variable. Can be dictionary or list. """ if (self.config.has_option(sect, key)): return sf.StrParse(self.config[sect][key], cast_type) else: if not silent: print('"' + key + '" not found in section "' + sect + '": default value ' + str(default) + ' returned.') return default
def LoadFiles(self, mi_fnames, metadata_section='MIfile', open_mifiles=True, replace_previous=False): """Load list of filenames Parameters ---------- mi_fnames : list of filenames (full path, str) open_mifiles : if True, open each MIfile for reading replace_previous : if True, replace eventual preexisting list of MIfile """ if (replace_previous or self.MIfiles is None): self.MIfiles = [] self.IdxList = [] for i in range(len(mi_fnames)): self.IdxList.append(sf.LastIntInStr(mi_fnames[i])) self.MIfiles.append( MI.MIfile(mi_fnames[i], self.MetaData.ToDict(section=metadata_section))) if open_mifiles: self.MIfiles[-1].OpenForReading() self._loaded = True
def Validate_zRange(zRange, zSize, replaceNone=True): return sf.ValidateRange(zRange, zSize, MinVal=0, replaceNone=replaceNone)
def Compute(self): sf.CheckCreateFolder(self.outFolder) logging.info( 'NonAffMaps.Compute() started! Result will be saved in folder ' + str(self.outFolder)) # Search for correlation map MIfiles, skip autocorrelation maps fw_mistack = self.cmaps_fw.GetCorrMaps(openMIfiles=True) bk_mistack = self.cmaps_bk.GetCorrMaps(openMIfiles=True) common_lags = list( set(fw_mistack.IdxList).intersection(bk_mistack.IdxList)) if self.lag_range is None: if 0 in common_lags: common_lags.remove(0) else: if self.lag_range[1] < 0: self.lag_range[1] = np.max(common_lags) + 1 common_lags = [ lag for lag in common_lags if (lag != 0 and lag >= self.lag_range[0] and lag <= self.lag_range[1]) ] self.lagList = common_lags # Export configuration self.ExportConfiguration() if self.trans_bk_matrix is not None: tr_matrix = np.reshape(np.asarray(self.trans_bk_matrix), (2, 2)) logging.debug( 'Backscattered correlation maps will be transformed using matrix ' + str(tr_matrix) + ' and offset ' + str(self.trans_bk_offset)) # For each couple of correlation maps (with equal lagtime) for lidx in range(len(self.lagList)): logging.info('Now working on lagtime ' + str(lidx) + '/' + str(len(self.lagList)) + ' (d' + str(self.lagList[lidx]) + ')') fw_lidx = fw_mistack.IdxList.index(self.lagList[lidx]) bk_lidx = bk_mistack.IdxList.index(self.lagList[lidx]) # eventually compute normalization factors if self.norm_range is not None: fw_norm_factor = np.mean(fw_mistack.MIfiles[fw_lidx].Read( zRange=self.norm_range[:2], cropROI=self.norm_range[2:], closeAfter=False)) if self.trans_bk_matrix is None and self.trans_bk_offset is None: bk_norm_factor = np.mean(bk_mistack.MIfiles[bk_lidx].Read( zRange=self.norm_range[:2], cropROI=self.norm_range[2:], closeAfter=False)) else: bk_norm_data = bk_mistack.MIfiles[bk_lidx].Read( zRange=self.norm_range[:2], cropROI=None, closeAfter=False) if len(bk_norm_data.shape) > 2: bk_norm_data = np.mean(bk_norm_data, axis=0) logging.debug('shape before transformation: ' + str(bk_norm_data.shape)) bk_norm_data = sp.ndimage.affine_transform(bk_norm_data, tr_matrix, offset=self.trans_bk_offset,\ output_shape=bk_norm_data.shape, order=1, mode='constant', cval=1.0) norm_cropROI = MI.ValidateROI(self.norm_range[2:], bk_norm_data.shape, replaceNone=True) logging.debug('shape after transformation: ' + str(bk_norm_data.shape) + ' will be cropped with ROI ' + str(norm_cropROI)) bk_norm_factor = np.mean(bk_norm_data[norm_cropROI[1]:norm_cropROI[1]+norm_cropROI[3],\ norm_cropROI[0]:norm_cropROI[0]+norm_cropROI[2]]) bk_norm_data = None else: fw_norm_factor, bk_norm_factor = 1, 1 logging.info('Normalization factors: ' + str(fw_norm_factor) + ' (front) and ' + str(bk_norm_factor) + ' (back)') # load, normalize and eventually smooth correlation maps. fw_data = np.true_divide( fw_mistack.MIfiles[fw_lidx].Read(zRange=self.t_range, cropROI=self.cropROI, closeAfter=True), fw_norm_factor) bk_data = np.true_divide( bk_mistack.MIfiles[bk_lidx].Read(zRange=self.t_range, cropROI=self.cropROI, closeAfter=True), bk_norm_factor) if self.smooth_kernel_specs is not None: Kernel3D = self.LoadKernel(self.smooth_kernel_specs) logging.debug('Smoothing with kernel with shape ' + str(Kernel3D.shape)) fw_data = signal.convolve(fw_data, Kernel3D, mode='same') bk_data = signal.convolve(bk_data, Kernel3D, mode='same') # transform backscattered images if self.trans_bk_matrix is not None: tr_matrix3D = np.asarray( [[1, 0, 0], [0, tr_matrix[0, 0], tr_matrix[0, 1]], [0, tr_matrix[1, 0], tr_matrix[1, 1]]]) tr_offset3D = np.asarray( [0, self.trans_bk_offset[0], self.trans_bk_offset[1]]) bk_data = sp.ndimage.affine_transform(bk_data, tr_matrix3D, offset=tr_offset3D,\ output_shape=fw_data.shape, order=1, mode='constant', cval=1.0) # sigma2 = ln(forward-scattering corr / backscattering corr) * 6 / (qz_bk^2 - qz_fw^2) sigma2 = np.log(np.true_divide( fw_data, bk_data)) * 6.0 / (self.qz_bk**2 - self.qz_fw**2) # For the first lagtime, generate and export metadata if (lidx == 0): out_meta = fw_mistack.MIfiles[fw_lidx].GetMetadata().copy() out_meta['hdr_len'] = 0 out_meta['gap_bytes'] = 0 out_meta['shape'] = list(sigma2.shape) if ('fps' in out_meta): val_tRange = fw_mistack.MIfiles[fw_lidx].Validate_zRange( self.t_range) out_meta['fps'] = float( out_meta['fps']) * 1.0 / val_tRange[2] exp_config = cf.Config() exp_config.Import(out_meta, section_name='MIfile') metadata_fname = os.path.join(self.outFolder, 'NAffMap_metadata.ini') exp_config.Export(metadata_fname) logging.info('Metadata exported to file ' + str(metadata_fname)) # export data cur_fname = 'NaffMap_d' + str(self.lagList[lidx]).zfill(4) + '.dat' MI.MIfile(os.path.join(self.outFolder, cur_fname), metadata_fname).WriteData(sigma2) logging.info('Result saved to file ' + str(cur_fname)) fw_mistack.MIfiles[fw_lidx].Close() bk_mistack.MIfiles[bk_lidx].Close()
def Compute(self, silent=True, return_maps=False): """Computes correlation maps Parameters ---------- silent : bool. If set to False, procedure will print to output every time steps it goes through. otherwise, it will run silently return_maps : bool. If set to True, procedure will return the array with correlation maps. Warning: no memory check is done when this happens, so be aware of memory consumption Returns ------- res_4D : list of correlation maps (np.float32), if return_maps==True """ if not silent: start_time = time.time() print('Computing correlation maps:') sf.CheckCreateFolder(self.outFolder) self.ExportConfiguration() if not silent: print( ' STEP 1: Loading images and computing average intensity...') # This will contain image data, eventually zero-padded Intensity = np.empty(self.inputShape) # This will contain kernel-averaged intensity data AvgIntensity = np.empty( [self.inputShape[0], self.outputShape[1], self.outputShape[2]]) # This will contain autocorrelation data ("d0") AutoCorr = np.empty(self.outputShape) # 2D Kernel to convolve to spatially average images ker2D = self.Kernel.ToMatrix() # This is to properly normalize correlations at the edges ConvNorm = signal.convolve2d(np.ones_like(Intensity[0]), ker2D, mode=self.Kernel.convolveMode, **self.Kernel.convolve_kwargs) # Now load all images we need self.MIinput.OpenForReading() for utidx in range(len(self.UniqueIdx)): Intensity[utidx] = self.MIinput.GetImage( img_idx=self.UniqueIdx[utidx], cropROI=self.cropROI) AvgIntensity[utidx] = signal.convolve2d( Intensity[utidx], ker2D, mode=self.Kernel.convolveMode, **self.Kernel.convolve_kwargs) if (self.Kernel.convolveMode == 'same'): AvgIntensity[utidx] = np.true_divide(AvgIntensity[utidx], ConvNorm) self.MIinput.Close() if not silent: print(' STEP 2: Computing contrast...') for tidx in range(self.outputShape[0]): AutoCorr[tidx] = signal.convolve2d(np.square(Intensity[self.imgIdx[tidx,0,0]]),\ ker2D, mode=self.Kernel.convolveMode, **self.Kernel.convolve_kwargs) if (self.Kernel.Padding): AutoCorr[tidx] = np.true_divide(AutoCorr[tidx], ConvNorm) AutoCorr[tidx] = np.subtract( np.true_divide(AutoCorr[tidx], np.square(AvgIntensity[tidx])), 1) MI.MIfile(os.path.join(self.outFolder, 'CorrMap_d0.dat'), self.outMetaData).WriteData(AutoCorr) if not silent: print(' STEP 3: Computing correlations...') if return_maps: res_4D = [np.asarray(AutoCorr, dtype=np.float32)] for lidx in range(self.numLags): if not silent: print(' ...lag ' + str(self.lagList[lidx])) CorrMap = np.empty_like(AutoCorr) for tidx in range(self.imgNumber - self.lagList[lidx]): CorrMap[tidx] = signal.convolve2d(np.multiply(Intensity[self.imgIdx[tidx,lidx,0]], Intensity[self.imgIdx[tidx,lidx,1]]),\ ker2D, mode=self.Kernel.convolveMode, **self.Kernel.convolve_kwargs) if (self.Kernel.Padding): CorrMap[tidx] = np.true_divide(CorrMap[tidx], ConvNorm) CorrMap[tidx] = np.true_divide(np.subtract(np.true_divide(CorrMap[tidx],\ np.multiply(AvgIntensity[self.imgIdx[tidx,lidx,0]],\ AvgIntensity[self.imgIdx[tidx,lidx,1]])),\ 1),\ AutoCorr[tidx]) # NOTE: in principle a better normalization for CorrMap is with # 0.5 * (AutoCorr[t] + AutoCorr[t+tau]) MI.MIfile( os.path.join( self.outFolder, 'CorrMap_d' + str(self.lagList[lidx]).zfill(4) + '.dat'), self.outMetaData).WriteData(CorrMap) if return_maps: res_4D.append(np.asarray(CorrMap, dtype=np.float32)) if not silent: print( 'Procedure completed in {0:.1f} seconds!'.format(time.time() - start_time)) if return_maps: return res_4D else: return None
def LoadFromConfig(ConfigFile, input_sect='input', outFolder=None): """Loads a SALS object from a config file like the one exported with VelMaps.ExportConfig() Parameters ---------- ConfigFile : full path of the config file to read outFolder : folder containing velocity and correlation maps. if None, the value from the config file will be used if not None, the value from the config file will be discarded Returns ------- a SALS object, eventually with an "empty" image MIfile (containing metadata but no actual image data) """ config = cf.Config(ConfigFile) froot = config.Get('global', 'root', '', str) miin_fname = config.Get(input_sect, 'mi_file', None, str) miin_meta_fname = config.Get(input_sect, 'meta_file', None, str) input_stack = False if (miin_fname is not None): # if miin_fname is a string, let's use a single MIfile as input. # otherwise, it can be a list: in that case, let's use a MIstack as input if (isinstance(miin_fname, str)): miin_fname = os.path.join(froot, miin_fname) else: input_stack = True for i in range(len(miin_fname)): miin_fname[i] = os.path.join(froot, miin_fname[i]) if (miin_meta_fname is not None): miin_meta_fname = os.path.join(froot, miin_meta_fname) elif input_stack: logging.error( 'SALS.LoadFromConfig ERROR: medatada filename must be specified when loading a MIstack' ) return None if input_stack: MIin = MIs.MIstack(miin_fname, miin_meta_fname, Load=True, StackType='t') else: MIin = MI.MIfile(miin_fname, miin_meta_fname) ctrPos = config.Get('SALS_parameters', 'center_pos', None, float) if (ctrPos is None): logging.error( 'SALS.LoadFromConfig ERROR: no SALS_parameters.center_pos parameter found in config file ' + str(ConfigFile)) return None else: r_max = ppf.MaxRadius(MIin.ImageShape(), ctrPos) radRange = sf.ValidateRange(config.Get('SALS_parameters', 'r_range', None, float), r_max, MinVal=1, replaceNone=True) angRange = sf.ValidateRange(config.Get('SALS_parameters', 'a_range', None, float), 2 * np.pi, replaceNone=True) rSlices = np.geomspace(radRange[0], radRange[1], int(radRange[2]) + 1, endpoint=True) aSlices = np.linspace(angRange[0], angRange[1], int(angRange[2]) + 1, endpoint=True) if (outFolder is None): outFolder = config.Get(input_sect, 'out_folder', None, str) if (outFolder is not None): outFolder = os.path.join(config.Get('global', 'root', '', str), outFolder) mask = config.Get('SALS_parameters', 'px_mask', None, str) mask = MI.ReadBinary( sf.PathJoinOrNone(froot, config.Get(input_sect, 'px_mask', mask, str)), MIin.ImageShape(), MIin.DataFormat(), 0) dark = MI.ReadBinary( sf.PathJoinOrNone(froot, config.Get(input_sect, 'dark_bkg', None, str)), MIin.ImageShape(), MIin.DataFormat(), 0) opt = MI.ReadBinary( sf.PathJoinOrNone(froot, config.Get(input_sect, 'opt_bkg', None, str)), MIin.ImageShape(), MIin.DataFormat(), 0) PD_data = sf.PathJoinOrNone( froot, config.Get(input_sect, 'pd_file', None, str)) if (PD_data is not None): PD_data = np.loadtxt(PD_data, dtype=float) img_times = config.Get(input_sect, 'img_times', None, str) if img_times is not None: # if miin_fname is a string, let's use a single text file as input. # otherwise, it can be a list: in that case, let's open each text file and append all results if (isinstance(img_times, str)): img_times = np.loadtxt(os.path.join(froot, img_times), dtype=float, usecols=config.Get( 'format', 'img_times_colidx', 0, int), skiprows=1) else: tmp_times = np.empty(shape=(0, ), dtype=float) for cur_f in img_times: tmp_times = np.append( tmp_times, np.loadtxt(os.path.join(froot, cur_f), dtype=float, usecols=config.Get('format', 'img_times_colidx', 0, int), skiprows=1)) img_times = tmp_times exp_times = sf.PathJoinOrNone( froot, config.Get(input_sect, 'exp_times', None, str)) if (exp_times is not None): exp_times = np.unique( np.loadtxt(exp_times, dtype=float, usecols=config.Get('format', 'exp_times_colidx', 0, int))) dlsLags = config.Get('SALS_parameters', 'dls_lags', None, int) tavgT = config.Get('SALS_parameters', 'timeavg_T', None, int) return SALS(MIin, outFolder, ctrPos, [rSlices, aSlices], mask, [dark, opt, PD_data], exp_times, dlsLags, img_times, tavgT)
if ('-skip_cmap' not in cmd_list) or ('-skip_vmap' not in cmd_list) or ('-skip_vmap_assemble' not in cmd_list) or ('-skip_displ' not in cmd_list) or ('-skip_grad' not in cmd_list): # Loop through all 'input_N' sections of the configuration file for cur_sec in conf.GetSections(): if (cur_sec[:len('input_')]=='input_'): # Read current input section mi_fname = os.path.join(froot, conf.Get(cur_sec, 'mi_file')) if ('-silent' not in cmd_list): print(' - ' + str(cur_sec) + ': working with ' + str(mi_fname) + '...') meta_fname = os.path.join(froot, conf.Get(cur_sec, 'meta_file')) out_folder = os.path.join(froot, conf.Get(cur_sec, 'out_folder')) img_range = conf.Get(cur_sec, 'img_range', None, int) crop_roi = conf.Get(cur_sec, 'crop_roi', None, int) SharedFunctions.CheckCreateFolder(out_folder) logging.basicConfig(filename=os.path.join(out_folder, 'DSH' + str(g_params['log_suffix']) + '.log'),\ level=logging.DEBUG, format='%(asctime)s | %(levelname)s:%(message)s') logging.info('Now starting analysis in folder ' + str(out_folder)) # Initialize image and correlation files mi_file = MIfile.MIfile(mi_fname, meta_fname) corr_maps = CorrMaps.CorrMaps(mi_file, out_folder, lag_list, kernel_specs, img_range, crop_roi) # Calculate correlation maps if ('-skip_cmap' not in cmd_list): if ('-silent' not in cmd_list): print(' - Computing correlation maps (multiprocess mode to be implemented)') corr_maps.Compute(silent=True, return_maps=False) if (('-skip_vmap' not in cmd_list) or (num_proc > 1 and '-skip_vmap_assemble' not in cmd_list) or ('-skip_displ' not in cmd_list) or ('-skip_grad' not in cmd_list)):
def __init__(self, MIin, outFolder, centerPos, ROIs=None, maskRaw=None, BkgCorr=None, expTimes=[1], dlsLags=None, imgTimes=None, timeAvg_T=None): """ Initialize SALS Parameters ---------- MIin : input MIfile or MIstack. It can be empty (i.e. initialized with metadata only) outFolder : output folder path. If the directory doesn't exist, it will be created centerPos : [float, float]. Position of transmitted beam [posX, posY], in pixels. The center of top left pixel is [0,0], posX increases leftwards, posY increases downwards ROIs : None, or raw mask with ROI numbers, or couple [rSlices, aSlices]. if raw mask:integer mask with ROI indexes for every pixel, 0-based. Each pixel can only belong to one ROI. Pixels belonging to no ROI are labeled with -1 Number of ROI is given by np.max(mask) None would correspond to [None, None] rSlices : 2D float array of shape (N, 2), or 1D float array of length N+1, or None. If 2D: i-th element will be (rmin_i, rmax_i), where rmin_i and rmax_i delimit i-th annulus (values in pixels) If 1D: i-th annulus will be delimited by i-th and (i+1)-th element of the list If None: one single annulus will be generated, comprising the whole image aSlices : angular slices, same structure as for rSlices. Here, angles are measured clockwise (y points downwards) starting from the positive x axis maskRaw : 2D binary array with same shape as MIin.ImageShape() True values (nonzero) denote pixels that will be included in the analysis, False values (zeroes) will be excluded If None, all pixels will be included. Disregarded if ROIs is already a raw mask BkgCorr : Eventually, data for background correction: [DarkBkg, OptBkg, PDdata], where: DarkBkg : None, float array or MIfile with dark measurement from the camera. If None, dark subtraction will be skipped If MIfile, all images from MIfile will be averaged and the raw result will be stored OptBkg : None, float array or MIfile with empty cell measurement. Sale as MIdark PDdata : 2D float array of shape (Nimgs+2, 2), where Nimgs is the number of images. i-th item is (PD0, PD1), where PD0 is the reading of the incident light, and PD1 is the reading of the transmitted light. Only useful if DarkBkg or OptBkg is not None imgTimes : None or float array of length Nimgs. i-th element will be the time of the image if None, i-th time will be computed using the FPS from the MIfile Metadata expTimes : list of floats """ self.MIinput = MIin self.outFolder = outFolder sf.CheckCreateFolder(self.outFolder) self.centerPos = centerPos self._genROIs(ROIs, maskRaw=maskRaw) self._loadBkg(BkgCorr) self._loadTimes(imgTimes) # check that expTimes is sorted: assert np.all(np.diff(expTimes) >= 0 ), 'Exposure times ' + str(expTimes) + ' must be sorted!' self.expTimes = expTimes # ensure that lags are sorted and include 0 if dlsLags is not None: dlsLags = np.unique(dlsLags) if dlsLags[0] > 0: dlsLags = np.append([0], dlsLags) self.dlsLags = dlsLags self.timeAvg_T = timeAvg_T self._initConstants()
def AverageG2M1(self): if self.timeAvg_T is None: self.timeAvg_T = self.NumTimes() cI_fnames = sf.FindFileNames(self.outFolder, Prefix=CI_PREFIX + '_', Ext='.dat') for cur_f in cI_fnames: cur_cI, cur_times, roi_idx, exp_idx = self.ReadCIfile(cur_f) tavg_num = cur_cI.shape[0] // self.timeAvg_T logging.debug( 'cI time averages will be performed by dividing the {0} images into {1} windows of {2} images each' .format(self.NumTimes(), tavg_num, self.timeAvg_T)) if self.IsTimingConstant(cur_times): g2m1_lags = np.true_divide(self.dlsLags, self.MIinput.GetFPS()) g2m1 = np.nan * np.ones( (self.NumLagtimes(), tavg_num), dtype=float) for tavgidx in range(tavg_num): g2m1[:, tavgidx] = np.nanmean( cur_cI[tavgidx * self.timeAvg_T:(tavgidx + 1) * self.timeAvg_T, :], axis=0) str_hdr_g = self.txt_comment + 'dt' + ''.join([ TXT_DELIMITER + 't{0:.2f}'.format(cur_times[tavgidx * self.timeAvg_T]) for tavgidx in range(tavg_num) ]) g2m1_out = np.append(g2m1_lags.reshape((-1, 1)), g2m1, axis=0).T else: g2m1_alllags, g2m1_laglist = self.FindTimelags(times=cur_times) g2m1 = np.zeros( (tavg_num, np.max([len(l) for l in g2m1_laglist])), dtype=float) g2m1_lags = np.nan * np.ones_like(g2m1, dtype=float) g2m1_avgnum = np.zeros_like(g2m1, dtype=int) for tidx in range(cur_cI.shape[0]): cur_tavg_idx = tidx // self.timeAvg_T #print((tidx, self.timeAvg_T, cur_tavg_idx, len(cur_tavg_idx))) g2m1_lags[ cur_tavg_idx, :len(g2m1_laglist[cur_tavg_idx] )] = g2m1_laglist[cur_tavg_idx] for lidx in range(cur_cI.shape[1]): if (tidx < len(g2m1_alllags[lidx])): cur_lagidx = np.argmin( np.abs( np.subtract(g2m1_laglist[cur_tavg_idx], g2m1_alllags[lidx][tidx]))) if (~np.isnan(cur_cI[tidx, lidx])): g2m1_avgnum[cur_tavg_idx, cur_lagidx] += 1 g2m1[cur_tavg_idx, cur_lagidx] += cur_cI[tidx, lidx] g2m1 = np.divide(g2m1, g2m1_avgnum) str_hdr_g = str(TXT_DELIMITER).join([ 'dt' + TXT_DELIMITER + 't{0:.2f}'.format(cur_times[tavgidx * self.timeAvg_T]) for tavgidx in range(tavg_num) ]) g2m1_out = np.empty((g2m1.shape[1], 2 * tavg_num), dtype=float) g2m1_out[:, 0::2] = g2m1_lags.T g2m1_out[:, 1::2] = g2m1.T np.savetxt(os.path.join(self.outFolder, G2M1_PREFIX + cur_f[2:]), g2m1_out, header=str_hdr_g, **self.savetxt_kwargs)
def GetCorrMaps(self, openMIfiles=True, getAutocorr=True, check_lagtimes=False): """Searches for MIfile correlation maps Parameters ---------- openMIfiles: if true, it opens all MIfiles for reading. getAutocorr: if True, returns d0 in the list of correlation maps otherwise, returns None instead of the autocorrelation map check_lagtimes: if true, checks that the lagtimes extracted from the filenames match with self.lagList Returns ------- corr_config: configuration file for correlation maps corr_mifiles: list of correlation maps, one per time delay lag_list: list of lagtimes """ if not self._corrmaps_loaded: assert os.path.isdir( self.outFolder), 'Correlation map folder ' + str( self.outFolder) + ' not found.' config_fname = os.path.join(self.outFolder, 'CorrMapsConfig.ini') assert os.path.isfile(config_fname), 'Configuration file ' + str( config_fname) + ' not found' self.conf_cmaps = cf.Config(config_fname) all_cmap_fnames = sf.FindFileNames(self.outFolder, Prefix='CorrMap_d', Ext='.dat', Sort='ASC', AppendFolder=True) self.cmap_mifiles = [] self.all_lagtimes = [] for i in range(len(all_cmap_fnames)): cur_lag = sf.LastIntInStr(all_cmap_fnames[i]) self.all_lagtimes.append(cur_lag) self.cmap_mifiles.append( MI.MIfile( all_cmap_fnames[i], self.conf_cmaps.ToDict(section='corrmap_metadata'))) self.cmap_mifiles[-1].OpenForReading() # Check lagtimes for consistency if (check_lagtimes): print( 'These are all lagtimes. They should be already sorted and not contain 0:' ) print(self.all_lagtimes) for cur_lag in self.lagList: if (cur_lag not in self.all_lagtimes): print( 'WARNING: no correlation map found for lagtime ' + str(cur_lag)) self._corrmaps_loaded = True if (self.all_lagtimes[0] == 0 and getAutocorr == False): return self.conf_cmaps, [ None ] + self.cmap_mifiles[1:], self.all_lagtimes else: return self.conf_cmaps, self.cmap_mifiles, self.all_lagtimes