def plot_frequencies_zoom(psd_data, peak_data, image_folder, nbin, df_zoom): """ Args: psd_data: peak_data: image_folder: nbin: df_zoom: Returns: """ for i in range(len(peak_data)): fig = plt.figure() mode = peak_data.iloc[i]['mode'][0] fo = peak_data.iloc[i]['peak freq'] f = avrg(psd_data['f'][1:], nbin) x = avrg(psd_data[mode][1:], nbin) # rough selection # fmin, fmax = fo - 3 * df_zoom / 2, 3 * fo + df_zoom / 2 # xs = x[np.all([f > fmin, f < fmax], axis=0)] # fs = f[np.all([f > fmin, f < fmax], axis=0)] # # fo = fs[np.argmax(xs)] fmin, fmax = fo - df_zoom / 2, fo + df_zoom / 2 x = x[np.all([f > fmin, f < fmax], axis=0)] fs = f[np.all([f > fmin, f < fmax], axis=0)] plt.plot(fs, x, '-o') plt.xlabel('frequency (Hz)') print(fo,' {:04.3f}Hz'.format(fo), ' {:04.03f}Hz'.format(fo)) plt.title('mode ' + str(peak_data.index[i]) + ' {:04.3f}Hz'.format(fo)) filename = '{:02d}_{:s}_{:04.0f}Hz.png'.format(i, mode, fo) fig.savefig(os.path.join(image_folder, filename)) plt.close(fig)
def plot_rot_angle_dist(data, info, frame_max=100, n_avrg_list = [1,2, 4, 8, 16, 32, 64, 128]): """ plots the distribution of angles as a function of binning length Args: data: time_step: source_folder_positions: verbose: frame_max: Returns: """ time_step = info['info']['FrameRate'] rot_angle = data['ellipse angle'] fig, axes = plt.subplots(2, 2, sharey=False, sharex=False, figsize=(20, 8)) res = [] for n_avrg in n_avrg_list: rot_angle_avrg = avrg(rot_angle, n=n_avrg) x = axes[0,0].hist(rot_angle_avrg, log=True, bins=50, density=True, alpha=0.3) res.append(get_rotation_frequency(data, info)[0:2]) axes[1,0].plot(np.arange(int(frame_max/n_avrg))*time_step*n_avrg, rot_angle_avrg[:int(frame_max/n_avrg)], '.-', label='n_avrg={:d}'.format(n_avrg)) axes[0,1].semilogx(n_avrg_list, [abs(val[0]) for val in res],'o') axes[0,1].set_xlabel('number of averages') axes[0,1].set_ylabel('mean freq') axes[1,1].loglog(n_avrg_list, [val[1] for val in res], 'o') axes[1,1].set_xlabel('number of averages') axes[1,1].set_ylabel('std dev freq') axes[0,0].set_xlabel('angle (deg') axes[0,0].set_ylabel('prob. density') axes[1,0].set_xlabel('time (s)') axes[1,0].set_ylabel('angle (deg)') return fig, axes
def spectra_2D_map(position_file_names,source_folder_positions=None, modes='xy', navrg=10, frequency_range=None, tag='_Sample_6_Bead_1_', nmax=None, y_axis = '', method = 'fit_ellipse', verbose=False): """ calculated the psds and plots them as a waterfall plot Args: position_file_names: modes: navrg: y_axis: determines what to use for the y-axis, ['run', 'time (h)', ''] if '' y is equilly spaced xlim: tag: nmax: verbose: Returns: """ fig, ax = plt.subplots(len(modes), 1, sharex=True, figsize=(18, 5 * len(modes))) if len(modes)==1: ax = [ax] psd_data = {'y_axis':[]} for i, filename in enumerate(position_file_names): run = int(filename.split(tag)[1].split('-')[0].strip('_')) if verbose: print(filename, run) data, info = load_time_trace(filename, source_folder_positions=source_folder_positions, verbose=False) dt = 1./info['info']['FrameRate'] if verbose: print('FrameRate', info['info']['FrameRate']) if y_axis == '': psd_data['y_axis'].append(i) elif y_axis == 'run': psd_data['y_axis'].append(run) elif y_axis == 'time (h)': time = info['info']['File_Modified_Date_Local'] time = datetime.strptime(time.split('.')[0], '%Y-%m-%d %H:%M:%S') if i==0: start = time time = time-start psd_data['y_axis'].append(time.seconds/(60 * 60) + time.days * 24) # calculate the psd for mode in modes: if method == 'fit_ellipse': if mode == 'r': x = data['ellipse angle'] elif mode == 'z': x = data['ellipse a'] * data['ellipse b'] else: x = data['ellipse ' + mode] elif method.lower() == 'bright px': x = data['bright px ' + mode] x -= np.mean(x) if nmax is not None: x = x[0:nmax] f, p = power_spectral_density(x, time_step=dt, frequency_range=frequency_range) p = avrg(p, navrg) if mode in psd_data: psd_data[mode] = np.vstack([psd_data[mode],p]) else: psd_data[mode] = p psd_data['f'] = avrg(f, navrg) for a, mode in enumerate(modes): z = np.log10(psd_data[mode]) # get data y = psd_data['y_axis'] x = psd_data['f'] ax[a].pcolormesh(x, y, z) # plot ax[a].set_title(mode + ' data') ax[a].set_xlabel('frequency (Hz)') ax[a].set_ylabel(y_axis) return fig
def waterfall(position_file_names,source_folder_positions=None, modes='xy', navrg=10, off_set_factor=-3, frequency_range=None, tag='_Sample_6_Bead_1_', nmax=None, method = 'fit_ellipse', verbose=False): """ calculated the psds and plots them as a waterfall plot Args: position_file_names: modes: navrg: off_set_factor: xlim: tag: nmax: verbose: Returns: """ fig, ax = plt.subplots(len(modes), 1, sharex=True, figsize=(18, 5 * len(modes))) if len(modes)==1: ax = [ax] for i, filename in enumerate(position_file_names): run = int(filename.split(tag)[1].split('-')[0].strip('_')) if verbose: print(filename, run) data, info = load_time_trace(filename, source_folder_positions=source_folder_positions, verbose=False) dt = 1./info['info']['FrameRate'] # calculate the psd psd_data = {} for mode in modes: if method == 'fit_ellipse': if mode == 'r': x = data['ellipse angle'] elif mode == 'z': x = data['ellipse a'] * data['ellipse b'] else: x = data['ellipse ' + mode] elif method.lower() == 'bright px': x = data['bright px ' + mode] x -= np.mean(x) if nmax is not None: x = x[0:nmax] f, p = power_spectral_density(x, time_step=dt, frequency_range=frequency_range) psd_data[mode] = p psd_data['f'] = f f = psd_data['f'][1:] # get rid of first point (DC) f = avrg(f, navrg) # refold (assume that signal is aliasied) # f = np.mean(df_modes['FrameRate'])-avrg(f, navrg) # refold (assume that signal is aliasied) for a, mode in enumerate(modes): d = psd_data[mode] # get data d = avrg(d[1:] * 10 ** (off_set_factor * i), navrg) # shift on a log scale to get the waterfall effect ax[a].semilogy(f, d, label=str(run), alpha=0.5) # plot # if xlim is not None: # assert len(xlim) == 2 # ax[0].set_xlim(xlim) for a, mode in enumerate(modes): ax[a].set_title(mode + ' data') ax[a].set_xlabel('frequency (Hz)') plt.legend(loc=(1, 0.0)) return fig
def plot_rotations_vs_time(data, time_step, t_max=0.1, n_avrg=20,n_avrg_unwrapped=20, axes=None, verbose=False, wrap_angle=None): """ plots a zoom in of the unwrapped angle, the full time trace and the distribution histogram of frequencies which are calculated from the derivative of the phase Args: data: time_step: zoom_frames: n_avrg: axes: verbose: wrap_angle: if None find wrap_angle automatically otherwise wrap angles at this value Returns: """ if wrap_angle is None: wrap_angle = get_wrap_angle(data['ellipse angle'], navrg=n_avrg) if verbose: print('wrap_angle', wrap_angle) min_frame, max_frame = 0, int(t_max/time_step/n_avrg) if axes is None: fig, axes = plt.subplots(2, 2, sharey=False, sharex=False, figsize=(18, 8)) else: fig = None ax1, ax2 = axes[0] ax3, ax4 = axes[1] rot_angle = data['ellipse angle'] rot_angle = avrg(rot_angle, n=n_avrg) x = ax4.hist(rot_angle, log=True, bins=50, alpha=0.3) rot_angle = np.unwrap(rot_angle, discont=wrap_angle) frames = np.arange(min_frame, max_frame) t = time_step * frames* n_avrg ax1.plot(t, rot_angle[frames] / 360) t2 = time_step *n_avrg* np.arange(len(rot_angle)) if max(rot_angle)>1e3: ax2.plot(t2, 1e-3 * rot_angle / 360) label2 = 'rotations (x 1000)' else: ax2.plot(t2, rot_angle / 360) label2 = 'rotations' rot_angle = avrg(rot_angle, n=n_avrg_unwrapped) freqs = np.diff(rot_angle) / (360 * time_step * n_avrg_unwrapped) freq_estimate = np.mean(freqs) if verbose: print('{:d} datapoints'.format(len(rot_angle))) print('freq_estimate {:0.3f}'.format(freq_estimate)) print('wrap angle {:0.2f} deg'.format(wrap_angle)) x = ax3.hist(freqs, log=True, bins=50, alpha=0.3) # if fig is None: ax1.set_title('zoom') ax2.set_title('full') ax1.set_ylabel('rotations') ax2.set_ylabel(label2) ax3.set_ylabel('probability density') ax1.set_xlabel('time (s)') ax2.set_xlabel('time (s)') ax3.set_xlabel('rotation freq. (Hz)') ax4.set_xlabel('angles') ax4.set_ylabel('prob density') return fig, axes
def plot_ellipse_spectra(data, info, annotation_dict={}, freq_range=None, n_avrg=None, plot_type = 'lin', verbose=False, normalize=True, return_data=False, axes = None): """ Args: data: info: annotation_dict: freq_range: n_avrg: average n_avrg successive datapoint to smoothen the data plot_type: Returns: """ coordinates = [['x', 'y', 'area'], ['a', 'b', 'angle']] feature = 'ellipse' time_step = 1. / info['info']['FrameRate'] axes_shape = np.shape(coordinates) if axes is None: fig, axes = plt.subplots(axes_shape[0], axes_shape[1], sharey=False, sharex=False, figsize=(8 * axes_shape[1], 3 * axes_shape[0])) else: fig = None if return_data: #containers for the data p_list = [] modes = {} for i, row in enumerate(zip(coordinates, axes)): # print('row', row) c_row, a_row = row for c, ax in zip(c_row, a_row): if verbose: print('plotting ' + c) if c == 'area': d = data[feature + ' a'] * data[feature + ' b'] * np.pi else: d = data[feature + ' ' + c] d = d - np.mean(d) # get rid of DC off set f, p = power_spectral_density(d, time_step, frequency_range=freq_range) if n_avrg is not None: f, p = avrg(f, n=n_avrg), avrg(p, n=n_avrg) if normalize: p = p / max(p) if plot_type == 'log': ax.loglog(f, p, linewidth=3) elif plot_type == 'lin': ax.plot(f, p, linewidth=3) elif plot_type == 'semilogy': ax.semilogy(f, p, linewidth=3) elif plot_type == 'semilogx': ax.semilogx(f, p, linewidth=3) # if we plot on a preexisting plot, don't add labels if fig is not None: if len(annotation_dict) > 0: annotate_frequencies(ax, annotation_dict, higher_harm=1) # annotate_frequencies(ax, annotation_dict, higher_harm=1) modes[c] = f[np.argmax(p)] ax.set_ylabel(c + ' (norm)') ax.set_xlim((min(f), max(f))) if i == len(coordinates) - 1: ax.set_xlabel('frequency (Hz)') if return_data: # containers for the data p_list.append(p) if return_data: return fig, axes, {'frequencies': f, 'spectra':p_list, 'coordinates':coordinates} else: return fig, axes
def plot_ellipse_spectra_zoom(data, info, annotation_dict={}, freq_window=1, n_avrg=None, plot_type='lin', normalize=True, axes=None, verbose=False): for mode in ['x', 'y', 'z', '2r', 'r', 'm']: assert mode in annotation_dict if normalize is True: normalize = 'max_peak' elif normalize is False: normalize = 'false' assert normalize in ['max_peak', 'false', 'std_dev'] coordinates = [['x', 'y', 'z'], ['r', '2r', 'm']] feature = 'ellipse' time_step = 1. / info['info']['FrameRate'] axes_shape = np.shape(coordinates) if axes is None: fig, axes = plt.subplots(axes_shape[0], axes_shape[1], sharey=False, sharex=False, figsize=(8 * axes_shape[1], 3 * axes_shape[0])) else: fig = None if verbose: print('axes shape', axes_shape, np.shape(axes), np.shape(coordinates)) modes = {} for i, row in enumerate(zip(coordinates, axes)): c_row, a_row = row if verbose: print('row', i, c_row) if verbose: print('columns', np.shape(c_row), np.shape(a_row)) for mode, ax in zip(c_row, a_row): if verbose: print('====', mode) axis_peak = mode # if mode in ['x', 'y', 'z']: # data_labels = ['x', 'y', 'area'] # elif mode in ['r', '2r', 'm']: # data_labels = ['area', 'angle'] if mode in ['x', 'y']: data_labels = [mode] elif mode in ['r', '2r', 'm', 'z']: data_labels = ['area'] for data_label in data_labels: # as a proxy for the z mode we use the area if data_label == 'area': d = data[feature + ' a'] * data[feature + ' b'] * np.pi else: d = data[feature + ' ' + data_label] d = d - np.mean(d) # get rid of DC off set if normalize == 'std_dev': d /= np.std(d) # set the frequency range to be +- freq_window/2 around the peak frequency_range = (max(0, annotation_dict[axis_peak][0] - 0.5 * freq_window), min(annotation_dict[axis_peak][0] + 0.5 * freq_window, 0.5 * info['info']['FrameRate'])) f, p = power_spectral_density(d, time_step, frequency_range=frequency_range) if n_avrg is not None: f, p = avrg(f, n=n_avrg), avrg(p, n=n_avrg) if normalize == 'max_peak': p = p / max(p) if plot_type == 'log': ax.loglog(f, p, linewidth=3) elif plot_type == 'lin': ax.plot(f, p, linewidth=3) elif plot_type == 'semilogy': ax.semilogy(f, p, linewidth=3) elif plot_type == 'semilogx': ax.semilogx(f, p, linewidth=3) # line_length = 0.2 # # trying to get better lengths for log plots but doesn't work... # # if plot_type in ['lin', 'semilogx']: # # line_length = 0.2 # # # # elif plot_type in ['log', 'semilogy']: # # line_length = 1-0.8*min(p / max(p)) # # if len(annotation_dict) > 0: # annotate_frequencies(ax, annotation_dict, x_off=0.1*freq_window, line_length=line_length, higher_harm=1) # # annotate_frequencies(ax, annotation_dict, higher_harm=1) modes[mode] = f[np.argmax(p)] if normalize == 'max_peak': ax.set_ylabel(mode + ' (norm max peak)') elif normalize == 'std_dev': ax.set_ylabel(mode + ' (norm std)') else: ax.set_ylabel(mode) ax.set_xlim((min(f), max(f))) if i == len(coordinates) - 1: ax.set_xlabel('frequency (Hz)') return fig, axes