def process_tf(self, exc_floor=10): """ Generates a Transfer Function using GKPixel function :param exc_floor: :type exc_floor: float """ defl = get_utils.get_pixel(self.h5_main, [0, 0], array_form=True).flatten() _gk = GKPixel(defl, self.parm_dict) _gk.load_tf(self.parm_dict['tip_response'], self.parm_dict['tip_excitation']) _gk.process_tf(exc_floor=exc_floor) self.TF_norm = _gk.TF_norm del _gk if any(np.isnan(self.TF_norm)): warnings.warn( 'TF is NaN! Lower exc_floor value to lower threshold of pass TF_norm explicitly' ) return
def _get_pixel_for_filtering(hdf_file, parameters={}, pixelnum=[0, 0]): """ :param hdf_file: :type hdf_file: :param parameters: :type parameters: dict :param pixelnum: See test_filter below :type pixelnum: list :returns: tuple (hdf_file, num_pts, drive, samp_rate) WHERE [type] hdf_file is... int num_pts is... [type] drive is... [type] samp_rate is... """ ftype = str(type(hdf_file)) if ('h5py' in ftype) or ('Dataset' in ftype): # hdf file parameters = usid.hdf_utils.get_attributes(hdf_file) hdf_file = get_utils.get_pixel(hdf_file, [pixelnum[0], pixelnum[1]], array_form=True, transpose=False) hdf_file = hdf_file.flatten() if len(hdf_file.shape) == 2: hdf_file = hdf_file.flatten() num_pts = hdf_file.shape[0] drive = parameters['drive_freq'] samp_rate = parameters['sampling_rate'] return hdf_file, num_pts, drive, samp_rate
def test(self, pixel_ind=[0, 0]): """ Test the Pixel analysis of a single pixel :param pixel_ind: Index of the pixel in the dataset that the process needs to be tested on. If a list it is read as [row, column] :type pixel_ind: uint or list :returns: List [inst_freq, tfp, shift] WHERE array inst_freq is the instantaneous frequency array for that pixel float tfp is the time to first peak float shift the frequency shift at time t=tfp (i.e. maximum frequency shift) """ # First read the HDF5 dataset to get the deflection for this pixel if type(pixel_ind) is not list: col = int(pixel_ind % self.parm_dict['num_rows']) row = int(np.floor(pixel_ind % self.parm_dict['num_rows'])) pixel_ind = [row, col] # as an array, not an ffta.Pixel defl = get_utils.get_pixel(self.h5_main, pixel_ind, array_form=True) pix = Pixel(defl, self.parm_dict, **self.pixel_params) tfp, shift, inst_freq = pix.analyze() pix.plot() return self._map_function(defl, self.parm_dict, self.pixel_params, self.impulse)
def test(self, pixel_ind=[0, 0], phases_to_test=[2.0708, 2.1208, 2.1708]): """ Test the Pixel analysis of a single pixel Parameters ---------- pixel_ind : uint or list Index of the pixel in the dataset that the process needs to be tested on. If a list it is read as [row, column] phases_to_test : list, optional Which phases to shift the signal with. The default is [2.0708, 2.1208, 2.1708], which is 0.5, 0.55, 0.5 + pi/2 Returns ------- [inst_freq, tfp, shift] : List inst_freq : array the instantaneous frequency array for that pixel tfp : float the time to first peak shift : float the frequency shift at time t=tfp (i.e. maximum frequency shift) """ # First read the HDF5 dataset to get the deflection for this pixel if type(pixel_ind) is not list: col = int(pixel_ind % self.parm_dict['num_rows']) row = int(np.floor(pixel_ind % self.parm_dict['num_rows'])) pixel_ind = [row, col] # as an array, not an ffta.Pixel defl = get_utils.get_pixel(self.h5_main, pixel_ind, array_form=True).flatten() _gk = GKPixel(defl, self.parm_dict, exc_wfm=self.exc_wfm, TF_norm=self.TF_norm) _gk.min_phase(phases_to_test=phases_to_test) _gk.force_out(plot=True, noise_tolerance=self.parm_dict['noise_tolerance']) if self.parm_dict['denoise']: print('aa') _gk.noise_filter() _gk.analyze_cpd(use_raw=False, periods=self.parm_dict['periods']) if self.parm_dict['filter_cpd']: print('bb') _gk.CPD = gaussian_filter1d(_gk.CPD, 1)[:_gk.num_CPD] _gk.plot_cpd() self.cpd_dict = _gk._calc_cpd_params(return_dict=True, periods=self.parm_dict['periods']) _, _, _, = self._map_function(defl, self.parm_dict, self.TF_norm, self.exc_wfm) return _gk
def _get_pixel_for_filtering(hdf_file, parameters={}, pixelnum=[0, 0]): ftype = str(type(hdf_file)) if ('h5py' in ftype) or ('Dataset' in ftype): # hdf file parameters = usid.hdf_utils.get_attributes(hdf_file) hdf_file = get_utils.get_pixel(hdf_file, [pixelnum[0], pixelnum[1]], array_form=True, transpose=False) hdf_file = hdf_file.flatten() if len(hdf_file.shape) == 2: hdf_file = hdf_file.flatten() num_pts = hdf_file.shape[0] drive = parameters['drive_freq'] samp_rate = parameters['sampling_rate'] return hdf_file, num_pts, drive, samp_rate
def test(self, pixel_ind=[0, 0], phases_to_test=[2.0708, 2.1208, 2.1708]): """ Test the Pixel analysis of a single pixel Parameters ---------- pixel_ind : uint or list Index of the pixel in the dataset that the process needs to be tested on. If a list it is read as [row, column] phases_to_test : list, optional Which phases to shift the signal with. The default is [2.0708, 2.1208, 2.1708], which is 0.5, 0.55, 0.5 + pi/2 Returns ------- [inst_freq, tfp, shift] : List inst_freq : array the instantaneous frequency array for that pixel tfp : float the time to first peak shift : float the frequency shift at time t=tfp (i.e. maximum frequency shift) """ # First read the HDF5 dataset to get the deflection for this pixel if type(pixel_ind) is not list: col = int(pixel_ind % self.parm_dict['num_rows']) row = int(np.floor(pixel_ind % self.parm_dict['num_rows'])) pixel_ind = [row, col] # as an array, not an ffta.Pixel defl = get_utils.get_pixel(self.h5_main, pixel_ind, array_form=True).flatten() _gk = GKPixel(defl, self.parm_dict, exc_wfm=self.exc_wfm, TF_norm=self.TF_norm)
def __init__(self, h5_main, parm_dict={}, can_params={}, pixel_params={}, TF_norm=[], exc_wfm=[], periods=2, tip_response='', tip_excitation='', exc_wfm_file='', override=False, noise_tolerance=1e-4, **kwargs): """ Parameters ---------- h5_main : h5py.Dataset object Dataset to process parm_dict : dict, optional Additional updates to the parameters dictionary. e.g. changing the trigger. You can also explicitly update self.parm_dict.update({'key': value}) can_params : dict, optional Cantilever parameters describing the behavior Can be loaded from ffta.pixel_utils.load.cantilever_params pixel_params : dict, optional override : bool, optional If True, forces creation of new results group. Use in _get_existing_datasets kwargs : dictionary or variable Keyword pairs to pass to Process constructor """ self.parm_dict = parm_dict for key, val in parm_dict.items(): self.parm_dict.update({key: val}) if any(can_params): if 'Initial' in can_params: # only care about the initial conditions for key, val in can_params['Initial'].items(): self.parm_dict.update({key: val}) else: for key, val in can_params.items(): self.parm_dict.update({key: val}) self.pixel_params = pixel_params self.override = override self.parm_dict['tip_response'] = tip_response self.parm_dict['tip_excitation'] = tip_excitation self.exc_wfm = exc_wfm self.parm_dict['periods'] = periods self.parm_dict['noise_tolerance'] = noise_tolerance super().__init__(h5_main, parm_dict=self.parm_dict, can_params=can_params, process_name='GKPFM', **kwargs) # save Transfer Function defl = get_utils.get_pixel(self.h5_main, [0, 0], array_form=True).flatten() _gk = GKPixel(defl, self.parm_dict, exc_wfm=exc_wfm) _gk.load_tf(self.parm_dict['tip_response'], self.parm_dict['tip_excitation']) _gk.process_tf() self.TF_norm = _gk.TF_norm del _gk self.parm_dict['denoise'] = False self.parm_dict['filter_cpd'] = False return
def test_filter(hdf_file, freq_filts, parameters={}, pixelnum=[0, 0], noise_tolerance=5e-7, show_plots=True, check_filter=True): """ Applies FFT Filter to the file at a specific line and displays the result :param hdf_file: hdf_file to work on, e.g. hdf.file['/FF-raw'] if that's a Dataset if ndarray, uses passed or default parameters Use ndarray.flatten() to ensure correct dimensions :type hdf_file: h5Py file or Nx1 NumPy array (preferred is NumPy array) :param freq_filts: Contains the filters to apply to the test signal :type freq_filts: list of FrequencyFilter class objects :param parameters: Contains parameters in FF-raw file for constructing filters. Automatic if a Dataset/File Must contain num_pts and samp_rate to be functional :type parameters: dict, optional :param pixelnum: For extracting a specific pixel to do FFT Filtering on :type pixelnum: int, optional :param noise_tolerance: Amount of noise below which signal is set to 0 :type noise_tolerance: float 0 to 1 :param show_plots: Turns on FFT plots from Pycroscopy :type show_plots : bool, optional :returns: tuple (filt_line, freq_filts, fig_filt, axes_filt) WHERE numpy.ndarray filt_line is filtered signal of hdf_file list freq_filts is the filter parameters to be passed to SignalFilter matplotlib controls fig_filt, axes_filt - Only functional if show_plots is on """ reshape = False ftype = str(type(hdf_file)) if ('h5py' in ftype) or ('Dataset' in ftype): # hdf file parameters = get_utils.get_params(hdf_file) hdf_file = get_utils.get_pixel(hdf_file, [pixelnum[0], pixelnum[1]], array_form=True, transpose=False) hdf_file = hdf_file.flatten() if len(hdf_file.shape) == 2: reshape = True hdf_file = hdf_file.flatten() sh = hdf_file.shape # Test filter on a single line: filt_line, fig_filt, axes_filt = px.processing.gmode_utils.test_filter( hdf_file, frequency_filters=freq_filts, noise_threshold=noise_tolerance, show_plots=show_plots) # If need to reshape if reshape: filt_line = np.reshape(filt_line, sh) # Test filter out in Pixel if check_filter: plt.figure() plt.plot(hdf_file, 'b') plt.plot(filt_line, 'k') h5_px_filt = pixel.Pixel(filt_line, parameters) h5_px_filt.clear_filter_flags() h5_px_filt.analyze() h5_px_filt.plot(newplot=True) h5_px_raw = pixel.Pixel(hdf_file, parameters) h5_px_raw.analyze() h5_px_raw.plot(newplot=True) # h5_px_raw_unfilt = pixel.Pixel(hdf_file, parameters) # h5_px_raw_unfilt.clear_filter_flags() # h5_px_raw_unfilt.analyze() # h5_px_raw_unfilt.plot(newplot=False,c1='y', c2='c') return filt_line, freq_filts, fig_filt, axes_filt
def hdf_commands(h5_path, ds='FF_Raw'): """ Creates a bunch of typical workspace HDF5 variables for scripting use Parameters ---------- h5_path : str String path to H5PY file ds : str, optional The dataset to search for and set as h5_main. This prints the valid commands to the workspace. Then just highlight and copy-paste to execute h5_path : str Path to hdf5 file on disk """ commands = ['***Copy-paste all commands below this line, then hit ENTER***', 'import h5py'] if not isinstance(h5_path, str): raise TypeError('Pass a file path (string), not an H5 file') try: hdf = h5py.File(h5_path, 'r+') commands.append("hdf = h5py.File(h5_path, 'r+')") except: pass try: h5_file = hdf.file commands.append("h5_file = hdf.file") except: pass try: h5_main = usid.hdf_utils.find_dataset(hdf.file, ds)[0] commands.append("h5_main = usid.hdf_utils.find_dataset(hdf.file, '" + ds + "')[0]") except: pass try: h5_if = usid.hdf_utils.find_dataset(hdf.file, 'inst_freq')[-1] commands.append("h5_if = usid.hdf_utils.find_dataset(hdf.file, 'inst_freq')[-1]") except: pass try: h5_if = usid.hdf_utils.find_dataset(hdf.file, 'Inst_Freq')[-1] commands.append("h5_if = usid.hdf_utils.find_dataset(hdf.file, 'Inst_Freq')[-1]") except: pass try: h5_tfp = usid.hdf_utils.find_dataset(hdf.file, 'tfp')[-1] commands.append("h5_tfp= usid.hdf_utils.find_dataset(hdf.file, 'tfp')[-1]") except: pass try: h5_shift = usid.hdf_utils.find_dataset(hdf.file, 'shift')[-1] commands.append("h5_shift= usid.hdf_utils.find_dataset(hdf.file, 'shift')[-1]") except: pass try: h5_avg = usid.hdf_utils.find_dataset(hdf.file, 'FF_Avg')[-1] commands.append("h5_avg = usid.hdf_utils.find_dataset(hdf.file, 'FF_Avg')[-1]") except: pass try: h5_filt = usid.hdf_utils.find_dataset(hdf.file, 'Filtered_Data')[-1] commands.append("h5_filt = usid.hdf_utils.find_dataset(hdf.file, 'Filtered_Data')[-1]") except: pass try: h5_rb = usid.hdf_utils.find_dataset(hdf.file, 'Rebuilt_Data')[-1] commands.append("h5_rb = usid.hdf_utils.find_dataset(hdf.file, 'Rebuilt_Data')[-1]") except: pass try: parameters = usid.hdf_utils.get_attributes(h5_avg) commands.append("parameters = usid.hdf_utils.get_attributes(h5_avg)") except: pass try: h5_ll = get_utils.get_line(h5_if, line_num=0) commands.append("h5_ll = ffta.load.get_utils.get_line(h5_if, line_num=0)") except: pass try: h5_px = get_utils.get_pixel(h5_if, rc=[0, 0]) commands.append("h5_px = ffta.load.get_utils.get_pixel(h5_if, rc=[0,0])") except: pass try: h5_svd = usid.hdf_utils.find_dataset(hdf.file, 'U')[-1] commands.append("h5_svd = usid.hdf_utils.find_dataset(hdf.file, 'U')[-1].parent") except: pass try: h5_cpd = usid.hdf_utils.find_dataset(hdf.file, 'cpd')[-1] commands.append("h5_cpd = usid.hdf_utils.find_dataset(hdf.file, 'cpd')[-1]") except: pass try: h5_ytime = usid.hdf_utils.find_dataset(hdf.file, 'y_time')[-1] commands.append("h5_ytime = usid.hdf_utils.find_dataset(hdf.file, 'y_time')[-1]") except: pass try: h5_Y = usid.hdf_utils.find_dataset(hdf.file, 'Y')[-1] commands.append("h5_Y = usid.hdf_utils.find_dataset(hdf.file, 'Y')[-1]") except: pass for i in commands: print(i) return
def test(self, pixel_ind=[0, 0], phases_to_test=[2.0708, 2.1208, 2.1708], smooth=None): """ Test the Pixel analysis of a single pixel :param pixel_ind: Index of the pixel in the dataset that the process needs to be tested on. If a list it is read as [row, column] :type pixel_ind: uint or list :param phases_to_test: Which phases to shift the signal with. The default is [2.0708, 2.1208, 2.1708], which is 0.5, 0.55, 0.5 + pi/2 :type phases_to_test: list, optional :param smooth: :type smooth: :returns: List [inst_freq, tfp, shift] WHERE array inst_freq is the instantaneous frequency array for that pixel float tfp is the time to first peak float shift shift is the frequency shift at time t=tfp (i.e. maximum frequency shift) """ # First read the HDF5 dataset to get the deflection for this pixel if type(pixel_ind) is not list: col = int(pixel_ind % self.parm_dict['num_rows']) row = int(np.floor(pixel_ind % self.parm_dict['num_rows'])) pixel_ind = [row, col] # as an array, not an ffta.Pixel defl = get_utils.get_pixel(self.h5_main, pixel_ind, array_form=True).flatten() _gk = GKPixel(defl, self.parm_dict, exc_wfm=self.exc_wfm, TF_norm=self.TF_norm) _gk.min_phase(phases_to_test=phases_to_test, noise_tolerance=self.parm_dict['noise_tolerance'], verbose=False) print("Set self.parm_dict['phase_shift'] to desired value") # If User supplies a phase shift if 'phase_shift' in self.parm_dict: _gk.force_out(plot=True, noise_tolerance=self.parm_dict['noise_tolerance'], phase_shift=self.parm_dict['phase_shift']) else: _gk.force_out(plot=True, noise_tolerance=self.parm_dict['noise_tolerance']) self.parm_dict['phase_shift'] = phases_to_test[-1] if self.parm_dict['denoise']: print('aa') _gk.noise_filter() try: _gk.analyze_cpd(use_raw=False, periods=self.parm_dict['periods']) except LinAlgError: print( 'Make sure TF_norm is set correctly. Pass TF_norm explicitly.') return _gk if self.parm_dict['filter_cpd']: print('bb') _gk.CPD = gaussian_filter1d(_gk.CPD, 1)[:_gk.num_CPD] _gk.plot_cpd(smooth) self.cpd_dict = _gk._calc_cpd_params(return_dict=True, periods=self.parm_dict['periods']) _, _, _, = self._map_function(defl, self.parm_dict, self.TF_norm, self.exc_wfm) return _gk
def test_deconv(self, window, pixel_ind=[0, 0], iterations=10): """ Tests the deconvolution by bracketing the impulse around window A reasonable window size might be 100 us pre-trigger to 500 us post-trigger :param window: List of format [left_index, right_index] for impulse :type window: list :param pixel_ind: Index of the pixel in the dataset that the process needs to be tested on. If a list it is read as [row, column] :type pixel_ind: uint or list :param iterations: Number of Richardson-Lucy deconvolution iterations :type iterations: int """ if len(window) != 2 or not isinstance(window, list): raise ValueError('window must be specified[left, right]') if isinstance(window[0], float): # passed a time index window = np.array(window) / self.parm_dict['sampling_rate'] window = int(window) if type(pixel_ind) is not list: col = int(pixel_ind % self.parm_dict['num_rows']) row = int(np.floor(pixel_ind % self.parm_dict['num_rows'])) pixel_ind = [row, col] # as an array, not an ffta.Pixel defl = get_utils.get_pixel(self.h5_main, pixel_ind, array_form=True) pixraw = Pixel(defl, self.parm_dict, **self.pixel_params) tfp, shift, inst_freq = pixraw.analyze() impulse = self.impulse[window[0]:window[1]] self.parm_dict['impulse_window'] = window self.parm_dict['conv_iterations'] = iterations pixconv = restoration.richardson_lucy(inst_freq, impulse, clip=False, num_iter=iterations) pixrl = pixraw tfp_raw = pixraw.tfp fit_raw = pixraw.best_fit if_raw = pixraw.inst_freq pixrl.inst_freq = pixconv pixrl.find_tfp() tfp_conv = pixrl.tfp fit_conv = pixrl.best_fit if_conv = pixrl.inst_freq print(tfp_raw, tfp_conv) # Plot the results of the original+fit compared to deconvolution+fit ridx = int(self.parm_dict['roi'] * self.parm_dict['sampling_rate']) fidx = int(pixraw.tidx) ifx = np.array([fidx - 1100, fidx + ridx ]) * 1e3 / self.parm_dict['sampling_rate'] windx = np.array(window) * 1e3 / self.parm_dict['sampling_rate'] yl0 = [ if_raw[fidx:(fidx + ridx)].min(), if_raw[fidx:(fidx + ridx)].max() ] yl1 = [ if_conv[fidx:(fidx + ridx)].min(), if_conv[fidx:(fidx + ridx)].max() ] yl2 = [ self.impulse[fidx:(fidx + ridx)].min(), self.impulse[fidx:(fidx + ridx)].max() ] fig, ax = plt.subplots(nrows=2, ncols=2, facecolor='white', figsize=(12, 8)) tx = np.arange(0, pixraw.total_time, 1 / pixraw.sampling_rate) * 1e3 ax[0][0].plot(tx, if_raw, 'b', label='Pre-Conv') ax[0][0].plot(tx[fidx:(fidx + ridx)], fit_raw, 'r--', label='Pre-Conv, fit') ax[0][0].set_title('Raw') ax[1][0].plot(tx, if_conv, 'b', label='Conv') ax[1][0].plot(tx[fidx:(fidx + ridx)], fit_conv, 'r--', label='Conv, fit') ax[1][0].set_title('Deconvolved') ax[0][1].plot(tx, self.impulse, 'k') ax[0][1].axvspan(windx[0], windx[1], alpha=0.5, color='red') ax[0][1].set_title('Impulse response') ax[1][1].plot(tx[fidx:(fidx + ridx)], fit_raw, 'r--', label='Pre-Conv, fit') ax[1][1].plot(tx[fidx:(fidx + ridx)], fit_conv, 'k--', label='Conv, fit') ax[1][1].set_title('Comparing fits') ax[1][1].legend() ax[0][0].set_xlim(ifx) ax[0][0].set_ylim(yl0) ax[1][0].set_xlim(ifx) ax[1][0].set_ylim(yl1) ax[0][1].set_xlim(ifx) ax[0][1].set_ylim(yl2) ax[1][1].set_xlim(ifx) ax[1][0].set_xlabel('Time (ms)') ax[1][1].set_xlabel('Time (ms)') plt.tight_layout() return pixrl