def calculate_histogram_sizes(tracks_queue, config, out_queue): params = config['tracking']['process'] df = DataFrame() sleep(5) while True: while not tracks_queue.empty() or tracks_queue.qsize() > 0: data = tracks_queue.get() df = df.append(data) if len(df) % 100 == 0: # t1 = tp.filter_stubs(df, params['min_traj_length']) # print(t1.head()) # t2 = t1[((t1['mass'] > params['min_mass']) & (t1['size'] < params['max_size']) & # (t1['ecc'] < params['max_ecc']))] # print(t2.head()) # t2 = t1 # d = tp.compute_drift(t1) # tm = tp.subtract_drift(t2.copy(), d) im = tp.imsd(df, config['tracking']['process']['um_pixel'], config['camera']['fps']) values = [] for pcle in im: data = im[pcle] slope, intercept, r, p, stderr = stats.linregress(np.log(data.index), np.log(data.values)) values.append([slope, intercept]) out_queue.put(values)
def _compute_individual_msd(trajectory, space_scale, fps, max_lagtime=100): # Calculate the MSD msd = tp.imsd(trajectory, space_scale, fps, max_lagtime=max_lagtime) # Format the output into a dictionnary msd_dict = {} for particle_id in msd.keys(): # Extract the array msd_array = np.array([msd.index, msd[particle_id].to_numpy()]) msd_dict[particle_id] = np.copy(msd_array.T) return msd_dict
def get_chart(self, data): """ The logarithmic format of the graph was disabled as requested. If it is needed to return place this: - ax.set_xscale('log') - ax.set_yscale('log') """ im = tp.imsd(data.filtered, 1, 1) fig = plt.figure(figsize=(16, 9), dpi=300) ax = fig.add_subplot(1, 1, 1) ax.plot(im.index, im, 'k-', alpha=0.1) ax.set_title("Mean squared displacement for each particle") plot_pil_image = current_plt_to_fig() fig.clear() plt.close(fig) return plot_pil_image
def mergedf_to_msddata(self): df = pd.read_csv(self.settings['Input path'] + self.root_name + '.csv') exp_labels = df['exp_label'].drop_duplicates().sort_values() figdata_dfs = [] if 'alpha' in df: df = df[df['alpha'] > 0] if 'traj_length' in df: df = df[df['traj_length'] > self.settings['traj_length_thres']] for exp_label in exp_labels: exp_df = df.loc[ df['exp_label']==exp_label, \ ['x', 'y', 'frame', 'particle'] ] im = tp.imsd( exp_df, mpp=self.settings['pixel_size'], fps=self.settings['frame_rate'], max_lagtime=np.inf, ) n = len(im.index) #for use in stand err calculation m = int(round(len(im.index) / 5)) im = im.head(m) im = im * 1e6 imsd_mean = im.mean(axis=1) imsd_std = im.std(axis=1, ddof=0) x = imsd_mean.index.to_numpy() y = imsd_mean.to_numpy() n_data_pts = np.sqrt(np.linspace(n - 1, n - m, m)) yerr = np.divide(imsd_std.to_numpy(), n_data_pts) tmp_df = pd.DataFrame({ exp_label + '_t': x, exp_label + '_MSD': y, exp_label + '_err': yerr, }) figdata_dfs.append(tmp_df) df_figdata = pd.concat(figdata_dfs, axis=1) df_figdata.round(3).to_csv(self.settings['Output path'] + \ self.root_name + '-msd' + \ '.csv', index=False)
def add_D_alpha(df, pixel_size, frame_rate, divide_num, fit_method='fit_msd1_log'): for col in ['D', 'alpha']: if col in df: df = df.drop(col, axis=1) df_cut = df[['frame', 'x', 'y', 'particle']] im = tp.imsd(df_cut, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf) n = int(round(len(im.index) / divide_num)) im = im.head(n) #get diffusion coefficient of each particle particles = im.columns ind = 1 tot = len(particles) for particle in particles: print("(%d/%d)" % (ind, tot)) ind = ind + 1 # Remove NaN, Remove non-positive value before calculate log() msd = im[particle].dropna() msd = msd[msd > 0] if len(msd) > 2: # Only fit when msd has more than 2 data points x = msd.index.values y = msd.to_numpy() y = y * 1e6 #convert to nm if fit_method == 'fit_msd2': popt = fit_msd2(x, y) elif fit_method == 'fit_msd1': popt = fit_msd1(x, y) else: popt = fit_msd1_log(x, y) df.loc[df['particle'] == particle, 'D'] = popt[0] df.loc[df['particle'] == particle, 'alpha'] = popt[1] return df
def nd2msd(nd_fh, params_locate_start={'diameter':11,'minmass_percentile':92}, params_msd={'mpp':0.0645,'fps':0.2, 'max_lagtime':100}, get_coords=True,out_fh=None): frames=nd2frames(nd_fh) t_cor=frames2coords_cor(frames,params_locate_start=params_locate_start,params_msd=params_msd,out_fh=out_fh) # debug imsd=tp.imsd(t_cor,statistic='msd',**params_msd) emsd=tp.emsd(t_cor,**params_msd) emsd=pd.DataFrame(emsd) emsd.index.name='lag time [s]' # print emsd import statsmodels.tsa.stattools as st acf=pd.DataFrame(columns=emsd.columns) for c in emsd: acf[c]=st.acf(emsd.loc[:,c],nlags=len(emsd)) acf.index=emsd.index if not out_fh is None: figure=plt.figure() ax=plt.subplot(111) acf.plot(ax=ax) plt.savefig('%s.acf.pdf' % out_fh,format='pdf') # plt.clf() if not out_fh is None: imsd.to_csv(out_fh+".imsd") emsd.to_csv(out_fh+".emsd") acf.to_csv(out_fh+".acf") dpkl={} dpkl['imsd']=imsd dpkl['emsd']=emsd dpkl['acf']=acf # dpkl['t']=t # dpkl['t_flt']=t_flt # dpkl['f_batch']=f_batch dpkl['t_cor']=t_cor to_pkl(dpkl,out_fh+".pkl") if get_coords: t_cor.to_csv(out_fh+".coords") return imsd,emsd
def calculate_histogram(self): self.calculating_histograms = True locations = self.locations.copy() t1 = tp.filter_stubs(locations, self.config['process']['min_traj_length']) # t2 = t1[((t1['mass'] > self.config['process']['min_mass']) & (t1['size'] < self.config['process']['max_size']) & # (t1['ecc'] < self.config['process']['max_ecc']))] im = tp.imsd(t1, self.config['process']['um_pixel'], self.config['process']['fps']) self.histogram_values = [] for pcle in im: if general_stop_event.is_set(): break data = im[pcle] t = data.index[~np.isnan(data.values)] val = data.values[~np.isnan(data.values)] try: slope, intercept, r, p, stderr = stats.linregress(np.log(t), np.log(val)) self.histogram_values.append([slope, intercept]) except: pass self.calculating_histograms = False self.publisher.publish('histogram', self.histogram_values)
def calculate_histogram(self): """ Starts a new thread to calculate the histogram of fit-parameters based on the mean-squared displacement of individual particles. It publishes the data on topic `histogram`. .. warning:: This method is incredibly expensive. Since it runs on a thread it can block other pieces of code, especially the GUI, which runs on the same process. .. TODO:: The histogram loops over all the particles. It would be better to skeep particles for which there is no new data .. TODO:: Make this method able to run on a separate process. So far is not possible because it relies on data stored on the class itself (`self.locations`). """ self.calculating_histograms = True locations = self.locations.copy() t1 = tp.filter_stubs(locations, self.config['process']['min_traj_length']) t2 = t1[((t1['mass'] > self.config['process']['min_mass']) & (t1['size'] < self.config['process']['max_size']) & (t1['ecc'] < self.config['process']['max_ecc']))] im = tp.imsd(t2, self.config['process']['um_pixel'], self.config['process']['fps']) self.histogram_values = [] for pcle in im: if general_stop_event.is_set(): break data = im[pcle] t = data.index[~np.isnan(data.values)] val = data.values[~np.isnan(data.values)] try: slope, intercept, r, p, stderr = stats.linregress( np.log(t), np.log(val)) self.histogram_values.append([slope, intercept]) except: pass self.calculating_histograms = False self.publisher.publish('histogram', self.histogram_values)
def track_mrna(self): det_df = pd.read_csv(self.config.OUTPUT_PATH + self.config.ROOT_NAME + \ '-detData.csv') blobs_df = tp.link_df( det_df, search_range=self.config.mRNA_SEARCH_RANGE, memory=self.config.mRNA_MEMORY, ) blobs_df = tp.filter_stubs(blobs_df, 5) blobs_df = blobs_df.reset_index(drop=True) blobs_df = add_traj_length(blobs_df) blobs_df_cut = blobs_df[['frame', 'x', 'y', 'particle']] blobs_df_cut = blobs_df_cut.apply(pd.to_numeric) im = tp.imsd( blobs_df_cut, mpp=self.config.PIXEL_SIZE, fps=self.config.FRAME_RATE, max_lagtime=np.inf, ) blobs_df = get_d_values(blobs_df, im, self.config.mRNA_DIVIDE_NUM) blobs_df = blobs_df.apply(pd.to_numeric) traj_num_before = blobs_df['particle'].nunique() after_filter_df = blobs_df[ blobs_df['traj_length'] >= self.config.mRNA_TRAJ_LEN_THRES] print("######################################") print("Trajectory number before filters: \t%d" % traj_num_before) print("Trajectory number after filters: \t%d" % after_filter_df['particle'].nunique()) print("######################################") blobs_df.round(6).to_csv(self.config.OUTPUT_PATH + self.config.ROOT_NAME + \ '-physData.csv', index=False) self.config.save_config()
def nd2msd(nd_fh): # print nd_fh frames=pims.ND2_Reader(nd_fh) logging.info('number of frames = %d' % len(np.shape(frames))) if len(np.shape(frames))==4: frames = average_z(frames) threshold=np.percentile(frames,75) f_batch = tp.batch(frames,diameter=11,threshold=threshold) t = tp.link_df(f_batch, search_range=11, memory=3) t_flt = tp.filter_stubs(t, 3*int(len(frames)/4)) try: d = tp.compute_drift(t_flt) t_cor = tp.subtract_drift(t_flt, d) except: t_cor=t_flt logging.info("drift correction excepted") # plt.figure() # tp.plot_traj(t_flt) # plt.figure() # d.plot() imsd=tp.imsd(t_cor,0.1,0.2, max_lagtime=100, statistic='msd') emsd=tp.emsd(t_cor,0.1,0.2, max_lagtime=100) return imsd,emsd
def fig_quick_msd(df=pd.DataFrame([]), ): # """ # ~~~~~~~~~~~Initialize the page layout~~~~~~~~~~~~~~ # """ fig, whole_page = plt.subplots(1, 1, figsize=(8, 6)) fig1 = whole_page.inset_axes([0.25, 0.25, 0.7, 0.7]) for spine in ['top', 'bottom', 'left', 'right']: whole_page.spines[spine].set_visible(False) for axis in [whole_page]: axis.set_xticks([]) axis.set_yticks([]) # """ # ~~~~Prepare df for the whole page~~~~ # """ if not df.empty: pixel_size = df['pixel_size'].mean() frame_rate = df['frame_rate'].mean() divide_num = 3 im = tp.imsd( df, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf, ) n = int(round(len(im.index) / divide_num)) im = im.head(n) # Remove NaN, Remove non-positive value before calculate log() msd = im.dropna() msd = msd[msd > 0] if len(msd) > 2: # Only fit when msd has more than 2 data points x = msd.index.values y = msd.to_numpy() y = y * 1e6 #convert um^2 to nm^2 print(y[0]) # y = y - y[0] try: popt_msd1 = fit_msd1_log(x, y) except: popt_msd1 = (0, 0) y_msd1 = msd1(x, popt_msd1[0], popt_msd1[1]) # """ # ~~~~Plot D~~~~ # """ figs = [fig1] datas = [df] xlabels = ['Time (s)'] ylabels = [r'MSD (nm$^2$)'] for i in range(len(figs)): print("\n") print("Plotting (%d/%d)" % (i + 1, len(figs))) figs[i].plot(x, y, '-o', color=(0, 0, 0, 0.8), linewidth=2, markersize=10) figs[i].plot(x, y_msd1, '--', color=(0, 0, 0, 0.6), linewidth=5) set_xylabel( figs[i], xlabel=xlabels[i], ylabel=ylabels[i], ) # """ # ~~~~format figures~~~~ # """ for figure in [ fig1, ]: format_spine(figure, spine_linewidth=1) format_tick(figure, tk_width=1) format_tklabel(figure, tklabel_fontsize=12) format_label(figure, label_fontsize=15) # figs = [fig1] # xscales = [[1.5, 20.5, 5], ] # yscales = [[15000, 48000, 10000], ] # for i in range(len(figs)): # format_scale(figs[i], # xscale=xscales[i], # yscale=yscales[i], # ) # """ # ~~~~Save the figure into pdf file, preview the figure in webbrowser~~~~~~~ # """ fig.savefig('/home/linhua/Desktop/Figure_1.tiff', dpi=300) # import webbrowser # webbrowser.open_new(r'/home/linhua/Desktop/Figure_1.pdf') plt.clf() plt.close()
def plot_msd( blobs_df, other_blobs_df, image, output_path, root_name, pixel_size, frame_rate, divide_num, ax=None, plot_without_sorter=False, cb_min=None, cb_max=None, cb_major_ticker=None, cb_minor_ticker=None, ): """ Generates the 3 panel msd figure with color-coded trajectories, msd curves, and a histogram of d values Parameters ---------- im: DataFrame: Mean squared displacement, each column is a particle blobs_df : DataFrame DataFrame containing 'D', 'frame', 'x', and 'y' columns image: 2D ndarray The image the trajectories will be plotted on output_path: string The folder where output files should be saved root_name: string The root file name to use for output files pixel_size: float The pixel_size of the images in microns/pixel divide_num: int The number used to divide the msd curves Returns ------- blobs_df_tracked : DataFrame object DataFrame with added column for particle number Examples -------- >>> from cellquantifier import data >>> from cellquantifier.smt.detect import detect_blobs, detect_blobs_batch >>> from cellquantifier.smt.fit_psf import fit_psf, fit_psf_batch >>> from cellquantifier.smt.track import track_blobs >>> from cellquantifier.smt.fit_msd import plot_msd >>> frames = data.simulated_cell() >>> blobs_df, det_plt_array = detect_blobs_batch(frames) >>> psf_df, fit_plt_array = fit_psf_batch(frames, blobs_df) >>> blobs_df, im = track_blobs(psf_df, min_traj_length=10) >>> d, alpha = plot_msd(im, blobs_df, image=frames[0], output_path='/home/cwseitz/Desktop/', root_name='file', pixel_size=.1084, divide_num=5) """ if blobs_df.empty: print('\n***Trajectories num is zero***\n') return # """ # ~~~~~~~~~~~Plot trajectory annotation~~~~~~~~~~~~~~ # """ anno_traj(ax[0], blobs_df, image, pixel_size, cb_min=cb_min, cb_max=cb_max, cb_major_ticker=cb_major_ticker, cb_minor_ticker=cb_minor_ticker) # """ # ~~~~~~~~~~~Plot the MSD curves for each particle~~~~~~~~~~~~~~ # """ #cut the msd curves and convert units to nm im = tp.imsd(blobs_df, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf) n = int(round(len(im.index) / divide_num)) im = im.head(n) im = im * 1e6 # im.to_csv(output_path + root_name + "-allMSD.csv", header=True) if len(im) > 1: ax[1].plot(im, 'k-', alpha=0.3) # """ # ~~~~~~~~~~~Get the avg/stdev for D,alpha of each particle~~~~~~~~~~~~~~ # """ if len(im) > 1: d_avg = (blobs_df.drop_duplicates( subset='particle')['D']).mean() #average D value d_std = (blobs_df.drop_duplicates( subset='particle')['D']).std() #stdev of D value #avg/stdev of alpha alpha_avg = (blobs_df.drop_duplicates( subset='particle')['alpha']).mean() #average alpha value alpha_std = (blobs_df.drop_duplicates( subset='particle')['alpha']).std() #stdev of alpha value # """ # ~~~~~~~~~~~Save D and alpha values per particle~~~~~~~~~~~~~~ # """ # blobs_df.drop_duplicates(subset='particle')[['D', 'alpha']].to_csv(output_path + root_name + "-Dalpha.csv", index=False) # """ # ~~~~~~~~~~~Get the mean MSD curve and its standard dev~~~~~~~~~~~~~~ # """ imsd_mean = im.mean(axis=1) imsd_std = im.sem(axis=1, ddof=0) # imsd_mean.to_csv(output_path + root_name + "-meanMSD.csv", header=True) x = imsd_mean.index y = imsd_mean.to_numpy() yerr = imsd_std.to_numpy() ax[1].errorbar(x, y, yerr=yerr, linestyle='None', marker='o', color='black') t = imsd_mean.index.to_numpy() popt_log = fit_msd( t, y, space='log') #fit the average msd curve in log space popt_lin = fit_msd( t, y, space='linear') #fit the average msd curve in linear space # """ # ~~~~~~~~~~~Plot the fit of the average and the average of fits~~~~~~~~~~~~~~ # """ fit_of_avg = msd(t, popt_log[0], popt_log[1]) avg_of_fits = msd(t, d_avg, alpha_avg) ax[1].plot(t, fit_of_avg, '-', color='b', linewidth=4, markersize=12, label="Fit of Average") ax[1].plot(t, avg_of_fits, '-', color='r', linewidth=4, markersize=12, label="Average of Fit") # """ # ~~~~~~~~~~~Write out the averages and errors to text box~~~~~~~~~~~~~~ # """ textstr = '\n'.join( (r'$D_{FOA}: %.2f \pm %.2f \mathbf{nm^{2}/s}$' % (popt_log[0], d_std), r'$\alpha_{FOA}: %.2f \pm %.2f$' % (popt_log[1], alpha_std), r'$D_{AOF}: %.2f \pm %.2f \mathbf{nm^{2}/s}$' % (d_avg, d_std), r'$\alpha_{AOF}: %.2f \pm %.2f$' % (alpha_avg, alpha_std))) props = dict(boxstyle='round', facecolor='wheat', alpha=0.0) ax[1].text(.1, .8, textstr, transform=ax[1].transAxes, horizontalalignment='left', verticalalignment='top', fontsize=12, color='black', bbox=props) ax[1].set_xlabel(r'$\tau (\mathbf{s})$') ax[1].set_ylabel(r'$\langle \Delta r^2 \rangle$ [$nm^2$]') ax[1].legend() # """ # ~~~~~~~~~~~Add D value histogram~~~~~~~~~~~~~~ # """ if plot_without_sorter: ax[2].hist(blobs_df.drop_duplicates(subset='particle')['D'].to_numpy(), bins=30, color=(0, 0, 0, 0.5)) else: ax[2].hist(blobs_df.drop_duplicates(subset='particle')['D'].to_numpy(), bins=30, color=(1, 0, 0, 0.5), label='Inside the sorter') if not other_blobs_df.empty: ax[2].hist( other_blobs_df.drop_duplicates(subset='particle')['D'].to_numpy(), bins=30, color=(0, 0, 1, 0.3), label='Outside the sorter') ax[2].legend(loc='upper right') ax[2].set_ylabel('Frequency') ax[2].set_xlabel(r'$D (\mathbf{nm^{2}/s})$') # """ # ~~~~~~~~~~~Add alpha value histogram~~~~~~~~~~~~~~ # """ if plot_without_sorter: ax[3].hist( blobs_df.drop_duplicates(subset='particle')['alpha'].to_numpy(), bins=30, color=(0, 0, 0, 0.5)) else: ax[3].hist( blobs_df.drop_duplicates(subset='particle')['alpha'].to_numpy(), bins=30, color=(1, 0, 0, 0.5), label='Inside the sorter') if not other_blobs_df.empty: ax[3].hist(other_blobs_df.drop_duplicates( subset='particle')['alpha'].to_numpy(), bins=30, color=(0, 0, 1, 0.3), label='Outside the sorter') ax[3].legend(loc='upper right') ax[3].set_ylabel('Frequency') ax[3].set_xlabel(r'$alpha$')
def track_blobs(blobs_df, search_range=3, memory=5, pixel_size=.1084, frame_rate=3.3, divide_num=5, filters=None, do_filter=False): """ Wrapper for trackpy library functions (assign detection instances to particle trajectories) Parameters ---------- blobs_df : DataFrame DataFrame with column for frame number and x,y particle coordinates search_range: int the maximum distance a particle can move between frames and still be tracked memory: int the number of frames to remember a particle that has disappeared filters: dict a dictionary of filters to apply to the blob DataFrame pixel_size: float the pixel_size of the images in microns/pixel frame_rate: float the frequency of the time-series acquisition in frames/sec divide_num: int The number used to divide the msd curves Returns ------- blobs_df_tracked : DataFrame object DataFrame with added column for particle number Examples -------- >>> from cellquantifier import data >>> from cellquantifier.smt.detect import detect_blobs, detect_blobs_batch >>> from cellquantifier.smt.fit_psf import fit_psf, fit_psf_batch >>> from cellquantifier.smt.track import track_blobs >>> frames = data.simulated_cell() >>> blobs_df, det_plt_array = detect_blobs_batch(frames) >>> psf_df, fit_plt_array = fit_psf_batch(frames, blobs_df) >>> blobs_df, im = track_blobs(psf_df, min_traj_length=10) frame x_raw y_raw r ... particle delta_area D alpha 0 0 500.0 525.0 9.0 ... 0 0 24216.104785 1.260086 40 1 499.0 525.0 9.0 ... 0 0.013233 24216.104785 1.260086 59 2 501.0 525.0 9.0 ... 0 0.039819 24216.104785 1.260086 86 3 500.0 526.0 9.0 ... 0 0.011217 24216.104785 1.260086 106 4 501.0 526.0 9.0 ... 0 0.013546 24216.104785 1.260086 .. ... ... ... ... ... ... ... ... ... 133 5 462.0 430.0 9.0 ... 33 0.050422 46937.634668 1.685204 158 6 462.0 432.0 9.0 ... 33 0.014778 46937.634668 1.685204 181 7 462.0 433.0 9.0 ... 33 0.043379 46937.634668 1.685204 203 8 461.0 434.0 9.0 ... 33 0.036314 46937.634668 1.685204 225 9 463.0 436.0 9.0 ... 33 0.021886 46937.634668 1.685204 """ blobs_df = blobs_df.dropna(subset=['x', 'y', 'frame']) # """ # ~~~~~~~~~~~Apply filters, Link Trajectories~~~~~~~~~~~~~~ # """ if do_filter: print("######################################") print("Filtering out suspicious data points") print("######################################") blobs_df = blobs_df[blobs_df['dist_err'] < filters['MAX_DIST_ERROR']] blobs_df = blobs_df[blobs_df['delta_area'] < filters['MAX_DELTA_AREA']] blobs_df = blobs_df[ blobs_df['sigx_to_sigraw'] < filters['SIG_TO_SIGRAW']] blobs_df = blobs_df[ blobs_df['sigy_to_sigraw'] < filters['SIG_TO_SIGRAW']] blobs_df = tp.link_df(blobs_df, search_range=search_range, memory=memory) blobs_df = tp.filter_stubs(blobs_df, 5) blobs_df = blobs_df.reset_index(drop=True) else: blobs_df = tp.link_df(blobs_df, search_range=search_range, memory=memory) blobs_df = blobs_df.reset_index(drop=True) # """ # ~~~~~~~~~~~Check if DataFrame is empty~~~~~~~~~~~~~ # """ if blobs_df.empty: print('\n***Trajectories num is zero***\n') return blobs_df, blobs_df # """ # ~~~~~~~~~~~Get dA/A~~~~~~~~~~~~~ # """ print("######################################") print("Calculating delta_area") print("######################################") blobs_df = blobs_df.sort_values(['particle', 'frame']) blobs_df['delta_area'] = np.abs( (blobs_df.groupby('particle')['area'].apply(pd.Series.pct_change))) blobs_df['delta_area'] = blobs_df['delta_area'].fillna(0) # """ # ~~~~~~~~~~~Get Individual Particle D Values~~~~~~~~~~~~~~ # """ blobs_df_cut = blobs_df[['frame', 'x', 'y', 'particle']] blobs_df_cut = blobs_df_cut.apply(pd.to_numeric) im = tp.imsd(blobs_df_cut, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf) blobs_df = get_d_values(blobs_df, im, divide_num) blobs_df = blobs_df.apply(pd.to_numeric) return blobs_df, im
a = coeff[0] for i in range(len(x)): disp = (1 / (1 + a**2)) * ((y[i] - y_approx[i])**2) / len(x) squared_displacements.append(disp) plt.title('MSD') plt.hist(squared_displacements, 100) plt.show() with tp.PandasHDFStore('data.h5') as store: trajectories = pd.concat(iter(store)) #filtered = tp.filter_stubs(trajectories) filtered = trajectories drift = tp.compute_drift(filtered) im = tp.imsd(filtered, 1, 1) plt.plot(im.index, im, 'k-', alpha=0.1) plt.xscale('log') plt.yscale('log') plt.title("Mean squared displacement for each particle") plt.show() disp_x = [] disp_y = [] for i in range(1, len(drift.x.values)): disp_x.append(drift.x.values[i] - drift.x.values[i - 1]) disp_y.append(drift.y.values[i] - drift.y.values[i - 1]) plt.figure(dpi=300) plt.hist(disp_x, 100) plt.title('X displacement')
def plot_msd_fitting(df, output_path): """ Plot msd fitting curve for each particle. Save pdf file for each particle. (WATCH OUT!!! A LOT OF PDFS!!!) Pseudo code ---------- 1. Iterate every 'raw_data' file. 2. Iterate every 'particle'. 3. Plot fitting curve for each particle, and save as pdf. Parameters ---------- df : DataFrame With columns ['x', 'y', 'frame', 'particle', 'raw_data', 'pixel_size', 'frame_rate', 'divide_num'] output_path : str Output path for all the pdf files Returns ------- None return values. A bunch of pdf files. """ raw_files = df['raw_data'].unique() ind = 1 tot = len(raw_files) for raw_file in raw_files: print("\n") print("Plot msd fitting curves (%d/%d): %s" % (ind, tot, raw_file)) ind = ind + 1 curr_df = df[df['raw_data'] == raw_file] particles = curr_df['particle'].unique() for particle in particles: curr_ptcl = curr_df[curr_df['particle'] == particle] pixel_size = curr_ptcl['pixel_size'].mean() frame_rate = curr_ptcl['frame_rate'].mean() divide_num = curr_ptcl['divide_num'].mean() im = tp.imsd( curr_ptcl, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf, ) n = int(round(len(im.index) / divide_num)) im = im.head(n) # Remove NaN, Remove non-positive value before calculate log() msd = im[particle].dropna() msd = msd[msd > 0] if len(msd) > 2: # Only fit when msd has more than 2 data points x = msd.index.values y = msd.to_numpy() y = y * 1e6 #convert um^2 to nm^2 print(particle) print(y[0]) y = y - y[0] try: popt_msd1 = fit_msd1(x, y) except: popt_msd1 = (0, 0) try: popt_msd1_log = fit_msd1_log(x, y) except: popt_msd1_log = (0, 0) try: popt_msd2 = fit_msd2(x, y) except: popt_msd2 = (0, 0, 0) y_msd1 = msd1(x, popt_msd1[0], popt_msd1[1]) y_msd1_log = msd1(x, popt_msd1_log[0], popt_msd1_log[1]) y_msd2 = msd2(x, popt_msd2[0], popt_msd2[1], popt_msd2[2]) rmse_msd1 = np.sqrt(((y_msd1 - y)**2).mean()) rmse_msd1_log = np.sqrt(((y_msd1_log - y)**2).mean()) rmse_msd2 = np.sqrt(((y_msd2 - y)**2).mean()) fig, whole_page = plt.subplots(figsize=(18, 4)) fig1 = whole_page.inset_axes([0.13, 0.15, 0.2, 0.7]) fig2 = whole_page.inset_axes([0.45, 0.15, 0.2, 0.7]) fig3 = whole_page.inset_axes([0.77, 0.15, 0.2, 0.7]) for axis in [whole_page]: axis.set_xticks([]) axis.set_yticks([]) for spine in ['top', 'bottom', 'left', 'right']: whole_page.spines[spine].set_visible(False) fig1.plot(x, y, '-o', color=(0, 0, 0), linewidth=1, markersize=5) fig1.plot(x, y_msd1, '-', color=(0, 0, 1), linewidth=2) fig2.plot(x, y, '-o', color=(0, 0, 0), linewidth=1, markersize=5) fig2.plot(x, y_msd1_log, '-', color=(0, 0, 1), linewidth=2) fig3.plot(x, y, '-o', color=(0, 0, 0), linewidth=1, markersize=5) fig3.plot(x, y_msd2, '-', color=(0, 0, 1), linewidth=2) fig1.text( -0.3, 1.05, r""" MSD = 4Dt$^\alpha$ D: %.2f $\alpha$: %.2f rmse: %.2f """ % (popt_msd1[0], popt_msd1[1], rmse_msd1), horizontalalignment='left', verticalalignment='top', fontname='Liberation Sans', fontsize=12, fontweight='bold', color=(0, 0, 0), transform=fig1.transAxes, ) fig2.text( -0.3, 1.05, r""" MSD = 4D + $\alpha$ln(t) D: %.2f $\alpha$: %.2f rmse: %.2f """ % (popt_msd1_log[0], popt_msd1_log[1], rmse_msd1_log), horizontalalignment='left', verticalalignment='top', fontname='Liberation Sans', fontsize=12, fontweight='bold', color=(0, 0, 0), transform=fig2.transAxes, ) fig3.text( -0.3, 1.05, r""" MSD = 4Dt$^\alpha$ + c D: %.2f $\alpha$: %.2f c: %.2f rmse: %.2f """ % (popt_msd2[0], popt_msd2[1], popt_msd2[2], rmse_msd2), horizontalalignment='left', verticalalignment='top', fontname='Liberation Sans', fontsize=12, fontweight='bold', color=(0, 0, 0), transform=fig3.transAxes, ) whole_page.text( 0, -0.15, """ (MSD curve fitting model comparison) """, horizontalalignment='left', verticalalignment='bottom', fontname='Liberation Sans', fontsize=12, fontweight='normal', color=(0, 0, 0), transform=whole_page.transAxes, ) # """ # ~~~~format figures~~~~ # """ for figure in [fig1, fig2, fig3]: format_spine(figure, spine_linewidth=1) format_tklabel(figure, tklabel_fontsize=12) format_label(figure, label_fontsize=12) set_xylabel( figure, xlabel='Time (s)', ylabel=r'D (nm$^2$/s)', ) file_name = output_path + raw_file[:-len('physData.csv')] file_name = file_name + 'particle' + str( particle) + '-msdFitting.pdf' fig.savefig(file_name) plt.clf() plt.close()
def plot_tracks_MSD(N, a, logmu, Tf, ax_lim, MSD_show, refresh, log_scale): '''Function plotting random tracks of particles and their associated mean square displacements, depending on several physical parameters and plotting options. Designed to be used with ipywidgets INPUTS: N : number of particles a : radius of particles [um] logmu: log of viscosity of fluid log[Pa s] Tf: length of tracks [s] ax_lim: limit of axis display [um] MSD_show: boolean for showing graphs of mean square displacements (MSDs) refresh: dummy argument for the widgets log_scale: boolean to show MSDs in loglog scale ''' # we have a few constants dt = 1e-2 # timestep of simulation [s] T = 305 # temperature, fixed [K] k_B = 1.38e-23 # Boltzman constant [J K-1] # we compute the diffusivity [m2/s] D = k_B*T/(6*np.pi*10**(logmu)*a*1e-6) # # we start all tracks from the center of the plot pos0 = [0, 0] # initialisation of figure fig, (ax, ax2) = plt.subplots(1,2,figsize = (12,6)) # option to use gridspec here # we add a bullseye pattern for guiding the viewer angle = np.linspace( 0 , 2 * np.pi , 150 ) x = np.cos( angle ) y = np.sin( angle ) r_list = np.arange(15) # in microns for i, r in enumerate(r_list): ax.plot(r*x, r*y, color = 'k', linestyle = '--', alpha = 0.5) pos = [] for i in range(N): track = generate_diff_track(pos0, D, dt, Tf) track = track*1e6 # convert to microns # Now, we draw the trajectory and final position ax.plot(track[0,:],track[1,:], color = 'k', alpha = 0.5) ax.plot(track[0,-1],track[1,-1],marker='o', ms=6, markerfacecolor = 'm', markeredgecolor = 'k') # we also populate a tracks panda frame (mostly empty) for use with trackpy track_pd = np.concatenate((track, np.zeros((6,track.shape[1])), np.arange(0,track.shape[1],1)[np.newaxis,:], i*np.ones((1,track.shape[1]))),axis =0) if i==0: pos = track_pd else: pos = np.concatenate((pos, track_pd), axis=1) # mark initial position ax.plot(0,0,marker='o', ms=6, markerfacecolor = 'w', markeredgecolor = 'k') # we also plot the scaling ax.plot(np.sqrt(4*D*Tf)*1e6*x,np.sqrt(4*D*Tf)*1e6*y, color = 'r', linestyle = '--') ax.text(0.0, 1.3*np.sqrt(4*D*Tf)*1e6, r"$r = \sqrt{4 D t_\mathrm{f}}$", fontsize=16, color='r', ha="center", va="center", bbox=dict(boxstyle="square", ec=(1.0, 1.0, 1.0), fc=(1., 1., 1.),alpha = 0.7)) # polish the plot ax.set_xlabel(r'$x$ ($\mu$m)') ax.set_ylabel(r'$y$ ($\mu$m)') ax.axis('equal') ax.set_xlim(-ax_lim, ax_lim) ax.set_ylim(-ax_lim, ax_lim) #ax.set_axis_off() if MSD_show: # we finish formatting the panda frame for use with Trackpy pos = np.transpose(pos) df = pd.DataFrame(pos, columns=['x', 'y','mass', 'size', 'ecc', 'signal', 'raw_mass', 'ep', 'frame','particle']) # we compute the msd of each particle, and the ensemble value im = tp.imsd(df, mpp = 1., fps = 1/dt, max_lagtime=int(np.floor((Tf/dt)/2))) em = tp.emsd(df, mpp = 1., fps = 1/dt, max_lagtime=int(np.floor((Tf/dt)/2))) # we do a linear regression in log space on the whole range of times slope, intercept, r, p, stderr = stats.linregress(np.log(em.index), np.log(em)) # we plot the individual msd with the theoretical trend and ensemble average overlaid ax2.plot(im.index, im, 'k-', alpha=0.2) ax2.plot(em.index, 1e12*4*D*em.index, linestyle = '--', color='r', label=r'theoretical power law $\langle \Delta r^2 \rangle = 4 D \Delta t$') ax2.plot(em.index, em, 'o', label='ensemble average', alpha = 0.8) ax2.plot(em.index, np.exp(intercept)*em.index**slope,linestyle = '-.', color='m', label=r'fitted power law $\langle \Delta r^2 \rangle = \alpha \Delta t^\beta$') ax2.set(ylabel=r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', xlabel='lag time $\Delta t$ [s]') if log_scale: ax2.set_xscale('log') ax2.set_yscale('log') plt.legend(loc=2, prop={'size': 12}) else: ax2.set_axis_off() fig.tight_layout() if MSD_show: print(' ================================================================================================') print('| Theoretical Diffusivity D = {0:.2E} um2/s | Fitted power law: beta = {1:.2E} |'.format(D*1e12,slope)) print(' ================================================================================================') else: print(' =============================================') print('| Theoretical Diffusivity D = {:.2E} um2/s |'.format(D*1e12)) print(' =============================================') plt.show()
def plot_tracks_MSD_box(N, D, Tf, L, refresh, log_scale): '''Function plotting random tracks of particles in a square box and their associated mean square displacements, depending on several physical parameters and plotting options. Designed to be used with ipywidgets INPUTS: N : number of particles D : diffusivity of particles [um2/s] Tf: length of tracks [s] L: half-width of of bounding box [um] refresh: dummy argument for the widgets log_scale: boolean to show MSDs in loglog scale ''' # we have a few constants dt = 1e-2 # timestep of simulation [s] # we start all tracks from the center of the plot pos0 = [0, 0] # initialisation of figure fig, (ax, ax2) = plt.subplots(1,2,figsize = (12,6)) # option to use gridspec here # we add the box ax.plot([L,L,-L,-L,L], [-L,L,L,-L,-L], color = 'c', linestyle = '-.', alpha = 1,lw=2) pos = [] for i in range(N): track = generate_diff_track([np.random.uniform(-L,L),np.random.uniform(-L,L)], D, dt, Tf) track_box = reflect(track,L) track_box = track_box*1e6 # convert to microns # Now, we draw the trajectory and final position ax.plot(track[0,:],track[1,:], color = 'k', alpha = 0.5) ax.plot(track[0,-1],track[1,-1],marker='o', ms=6, markerfacecolor = 'm', markeredgecolor = 'k') ax.plot(track[0,0],track[1,0],marker='o', ms=6, markerfacecolor = 'w', markeredgecolor = 'k') # we also populate a tracks panda frame (mostly empty) for use with trackpy track_pd = np.concatenate((track, np.zeros((6,track.shape[1])), np.arange(0,track.shape[1],1)[np.newaxis,:], i*np.ones((1,track.shape[1]))),axis =0) if i==0: pos = track_pd else: pos = np.concatenate((pos, track_pd), axis=1) # mark initial position #ax.plot(0,0,marker='o', ms=6, markerfacecolor = 'w', markeredgecolor = 'k') # polish the plot ax.set_xlabel(r'$x$ ($\mu$m)') ax.set_ylabel(r'$y$ ($\mu$m)') ax.axis('equal') ax.set_xlim(-1.2*L, 1.2*L) ax.set_ylim(-1.2*L, 1.2*L) #ax.set_axis_off() # we finish formatting the panda frame for use with Trackpy pos = np.transpose(pos) df = pd.DataFrame(pos, columns=['x', 'y','mass', 'size', 'ecc', 'signal', 'raw_mass', 'ep', 'frame','particle']) # we compute the msd of each particle, and the ensemble value im = tp.imsd(df, mpp = 1., fps = 1/dt, max_lagtime=int(np.floor((Tf/dt)/2))) em = tp.emsd(df, mpp = 1., fps = 1/dt, max_lagtime=int(np.floor((Tf/dt)/2))) # we plot the individual msd with the theoretical trend and ensemble average overlaid ax2.plot(im.index, im, 'k-', alpha=0.2) ax2.plot(em.index, 4*D*em.index, linestyle = '--', color='r', label=r'theoretical power law $\langle \Delta r^2 \rangle = 4 D \Delta t$') ax2.plot(em.index, em, 'o', label='ensemble average', alpha = 0.8) ax2.plot(em.index, 0*em.index + 4*L**2/3,linestyle = '-.', color='c', label=r'box limit $4 L^2/3$') ax2.set(ylabel=r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', xlabel='lag time $ \Delta t$ [s]') if log_scale: ax2.set_xscale('log') ax2.set_yscale('log') ax2.set_ylim(2*D*dt, 10*L**2) else: ax2.set_ylim(0, 3*L**2) plt.legend(loc=2, prop={'size': 12}) fig.tight_layout() plt.show()
['x', 'y', 'frame', 'particle']] df_NcUV3s200925 = df_uv2.loc[df_uv2['exp_label'] == 'NcUV3s', ['x', 'y', 'frame', 'particle']] df_NcUV5s200925 = df_uv2.loc[df_uv2['exp_label'] == 'NcUV5s', ['x', 'y', 'frame', 'particle']] df_NcUV7s200925 = df_uv2.loc[df_uv2['exp_label'] == 'NcUV7s', ['x', 'y', 'frame', 'particle']] data_dfs = [] dfs = [df_200NcBLM, df_200NcLiving] names = ['200NcBLM', '200NcLiving'] for (df, name) in zip(dfs, names): im = tp.imsd( df, mpp=0.163, fps=5, max_lagtime=np.inf, ) n = len(im.index) #for use in stand err calculation m = int(round(len(im.index) / 5)) im = im.head(m) im = im * 1e6 imsd_mean = im.mean(axis=1) imsd_std = im.std(axis=1, ddof=0) x = imsd_mean.index.to_numpy() y = imsd_mean.to_numpy() n_data_pts = np.sqrt(np.linspace(n - 1, n - m, m)) yerr = np.divide(imsd_std.to_numpy(), n_data_pts)
def plot_msd_merged(blobs_df, cat_col, output_path, root_name, pixel_size, frame_rate, divide_num, pltshow=True): fig, ax = plt.subplots(1, 3, figsize=(18, 6)) cats = blobs_df[cat_col].unique() blobs_dfs = [blobs_df.loc[blobs_df[cat_col] == cat] for cat in cats] colors = plt.cm.jet(np.linspace(0, 1, len(cats))) # # ~~~~~~~~~~~Run a t-test~~~~~~~~~~~~~~ # """ if len(cats) == 2: x = blobs_df.drop_duplicates('particle')[['D', 'alpha', cat_col]] D_stats = t_test(x.loc[x[cat_col] == cats[0]]['D'], \ x.loc[x[cat_col] == cats[1]]['D']) alpha_stats = t_test(x.loc[x[cat_col] == cats[0]]['alpha'], \ x.loc[x[cat_col] == cats[1]]['alpha']) # # ~~~~~~~~~~~Check if blobs_df is empty~~~~~~~~~~~~~~ # """ for i, blobs_df in enumerate(blobs_dfs): if blobs_df.empty: return # Calculate individual msd im = tp.imsd(blobs_df, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf) #Get the diffusion coefficient for each individual particle D_ind = blobs_df.drop_duplicates('particle')['D'].mean() # """ # ~~~~~~~~~~~Get the avg/stdev for D,alpha of each particle~~~~~~~~~~~~~~ # """ if len(im) > 1: d_avg = (blobs_df.drop_duplicates( subset='particle')['D']).mean() #average D value d_std = (blobs_df.drop_duplicates( subset='particle')['D']).std() #stdev of D value #avg/stdev of alpha alpha_avg = (blobs_df.drop_duplicates( subset='particle')['alpha']).mean() #average alpha value alpha_std = (blobs_df.drop_duplicates( subset='particle')['alpha']).std() #stdev of alpha value # """ # ~~~~~~~~~~~Get the mean MSD curve and its standard dev~~~~~~~~~~~~~~ # """ #cut the msd curves and convert units to nm n = int(round(len(im.index) / divide_num)) im = im.head(n) im = im * 1e6 imsd_mean = im.mean(axis=1) imsd_std = im.std(axis=1, ddof=0) x = imsd_mean.index y = imsd_mean.to_numpy() yerr = imsd_std.to_numpy() t = imsd_mean.index.to_numpy() popt_log = fit_msd( t, y, space='log') #fit the average msd curve in log space popt_lin = fit_msd( t, y, space='linear') #fit the average msd curve in linear space # """ # ~~~~~~~~~~~Plot the fit of the average and the average of fits~~~~~~~~~~~~~~ # """ fit_of_avg = msd(t, popt_log[0], popt_log[1]) avg_of_fits = msd(t, d_avg, alpha_avg) ax[0].errorbar(x, avg_of_fits, yerr=yerr, linestyle='None', marker='o', color=(colors[i][0], colors[i][1], colors[i][2], 0.5)) ax[0].plot(t, avg_of_fits, '-', color=(colors[i][0], colors[i][1], colors[i][2], 0.5), linewidth=4, markersize=12, label=cats[i]) ax[0].set_xlabel(r'$\tau (\mathbf{s})$') ax[0].set_ylabel(r'$\langle \Delta r^2 \rangle$ [$nm^2$]') ax[0].legend() # """ # ~~~~~~~~~~~Add D value histogram~~~~~~~~~~~~~~ # """ ax[1].hist(blobs_df.drop_duplicates(subset='particle')['D'].to_numpy(), bins=30, color=(colors[i][0], colors[i][1], colors[i][2], 0.5), label=cats[i], normed=True) textstr = '\n'.join((r'$t-value: %.2f$' % (D_stats[0]), r'$p-value: %.2f$' % (D_stats[1]))) props = dict(boxstyle='round', facecolor='wheat', alpha=0.0) ax[1].text(.6, .8, textstr, transform=ax[1].transAxes, horizontalalignment='left', verticalalignment='top', fontsize=12, color='black', bbox=props) ax[1].legend(loc='upper right') ax[1].set_ylabel('Frequency') ax[1].set_xlabel('D') # """ # ~~~~~~~~~~~Add alpha value histogram~~~~~~~~~~~~~~ # """ ax[2].hist( blobs_df.drop_duplicates(subset='particle')['alpha'].to_numpy(), bins=30, color=(colors[i][0], colors[i][1], colors[i][2], 0.5), label=cats[i], normed=True) textstr = '\n'.join((r'$t-value: %.2f$' % (alpha_stats[0]), r'$p-value: %.2f$' % (alpha_stats[1]))) props = dict(boxstyle='round', facecolor='wheat', alpha=0.0) ax[2].text(.6, .8, textstr, transform=ax[2].transAxes, horizontalalignment='left', verticalalignment='top', fontsize=12, color='black', bbox=props) ax[2].legend(loc='upper right') ax[2].set_ylabel('Frequency') ax[2].set_xlabel('alpha') plt.tight_layout() # """ # ~~~~~~~~~~~Save the plot as pdf, and open the pdf in browser~~~~~~~~~~~~~~ # """ start_ind = root_name.find('_') end_ind = root_name.find('_', start_ind + 1) today = str(date.today().strftime("%y%m%d")) fig.savefig(output_path + today + root_name[start_ind:end_ind] + '-mergedResults.pdf') if pltshow: plt.show()
plt.figure() tp.plot_traj(tra1); d =tp.compute_drift(tra1) ##subtract overall drift from trajectory d.plot() plt.show() tm=tp.subtract_drift(tra1.copy(),d) ##plot filtered trajectory ax=tp.plot_traj(tm) plt.show() ##MSD Calculation and Plot im=tp.imsd(tm,1/5.,60) ##microns per pixel, frames per second=60 fig, ax = plt.subplots() ax.plot(im.index, im, 'k-', alpha=0.1) # black lines, semitransparent ax.set(ylabel=r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', xlabel='lag time $t$',title='MSD') ax.set_xscale('log') ax.set_yscale('log') ##Total Ensemble MSD and Plot em=tp.emsd(tm,1/5.,60) fig, ax = plt.subplots() ax.plot(em.index, em, 'o-') ax.set_xscale('log') ax.set_yscale('log')
def add_local_D_alpha( df, pixel_size, frame_rate, divide_num=5, window_width=20, ): # """ # ~~~~Initialize df~~~~ # """ df = df.sort_values(['particle', 'frame']) for col in ['local_D', 'local_alpha', 'local_v']: if col in df: df = df.drop(col, axis=1) # """ # ~~~~Iterate df by particle~~~~ # """ half_window = window_width // 2 particles = sorted(df['particle'].unique()) ind = 1 tot = len(particles) for particle in particles: print("Calculating local_D and local_alpha (%d/%d)" % (ind, tot)) ind = ind + 1 curr_df = df[df['particle'] == particle] curr_df = curr_df.sort_values(['particle', 'frame']) curr_df = curr_df.reset_index(drop=True) for index in curr_df.index: if half_window < (index + 1) <= (len(curr_df) - half_window): tmp_df = curr_df.iloc[index - half_window:index + half_window + 1, :] tmp_df_cut = tmp_df[['frame', 'x', 'y', 'particle']] im = tp.imsd(tmp_df_cut, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf) tmp_df = get_d_values(tmp_df, im, divide_num) curr_df.loc[index, 'local_D'] = tmp_df['D'].mean() curr_df.loc[index, 'local_v'] = (tmp_df['D'].mean() * 4)**0.5 curr_df.loc[index, 'local_alpha'] = tmp_df['alpha'].mean() else: curr_df.loc[index, 'local_D'] = None curr_df.loc[index, 'local_v'] = None curr_df.loc[index, 'local_alpha'] = None df.loc[df['particle'] == particle, 'local_D'] = curr_df['local_D'].to_numpy() df.loc[df['particle'] == particle, 'local_v'] = curr_df['local_v'].to_numpy() df.loc[df['particle'] == particle, 'local_alpha'] = curr_df['local_alpha'].to_numpy() return df
def main(): for case_idx, case in enumerate(cases.values()): res_path = gen_path + case[1] frames = pims.ImageSequence(gen_path + case[0], as_grey=True) # Stores the unfiltered annotated image of a frame to local file path if plots["Annotate_unfiltered"]: k = tp.locate(frames[0], 11, invert=[case_idx in [0, 1]], minmass=200) fig = plt.figure("Annotated_unfiltered_image_" + case[2]) ax1 = fig.add_subplot() a = ["k", "w"][case_idx in [2, 3]] tp.annotate(k, frames[0], color=a, ax=ax1) #ax1.set_title("Annotated unfiltered image case: "+ case[2]) #ax1.set_xlabel("x[px]", fontsize=size) #ax1.set_ylabel("y[px]", fontsize=size) ax1.tick_params(axis="both", which="both", top=False, bottom=False, labelbottom=False, right=False, left=False, labelleft=False) fig.savefig(res_path + "Annotated_unfiltered_image_" + case[2] + ".png", bbox_inches="tight", pad_inches=0) plt.close(fig) # If True: Tracks all frames and stores .csv to locally, else: imports such .csv file from local if plots["Generate_batch"]: f = tp.batch(frames[:225], 11, minmass=100, invert=[case_idx in [0, 1]]) f.to_csv(res_path + "batch_" + case[2] + ".csv") if not plots["Generate_batch"]: f = pd.read_csv(res_path + "batch_" + case[2] + ".csv") # Linking and filtering t = tp.link_df(f, 5, memory=3) t1 = tp.filter_stubs(t, 50) # Plots the size vs mass profile and saves to local file path if plots["Size_vs_mass"]: fig = plt.figure("Size_vs_mass_" + case[2]) ax1 = fig.add_subplot() tp.mass_size( t1.groupby('particle').mean(), ax=ax1) # convenience function -- just plots size vs. mass #ax1.set_title("Size vs mass case: " + case[2]) ax1.set_xlabel("mass", fontsize=size) ax1.set_ylabel("Gyration radius [px]", fontsize=size) ax1.spines['top'].set_visible(False) ax1.spines['right'].set_visible(False) ax1.tick_params(axis="both", which="major", labelsize=size) ax1.tick_params(axis="both", which="minor", labelsize=size) fig.savefig(res_path + "Size_vs_mass_" + case[2] + ".png", bbox_inches="tight", pad_inches=0) plt.close(fig) if plots["Annotate_filtered"]: if case_idx in [0, 1]: # Set BF condition condition = lambda x: ( (x['mass'].mean() > 250) & (x['size'].mean() < 3.0) & (x['ecc'].mean() < 0.1)) elif case_idx in [2, 3]: # Set DF condition condition = lambda x: ( (x['mass'].mean() > 100) & (x['size'].mean() < 5.0) & (x['ecc'].mean() < 0.1)) t2 = tp.filter( t1, condition ) # a wrapper for pandas' filter that works around a bug in v 0.12 fig = plt.figure("Annotated_filtered_image_" + case[2]) ax1 = fig.add_subplot() k = ["k", "w"][case_idx in [2, 3]] tp.annotate(t2[t2['frame'] == 0], frames[0], color=k, ax=ax1) #ax1.set_title("Annotated filtered image case: " + case[2]) #ax1.set_xlabel("x[px]", fontsize=size) #ax1.set_ylabel("y[px]", fontsize=size) ax1.tick_params(axis="both", which="both", top=False, bottom=False, labelbottom=False, right=False, left=False, labelleft=False) fig.savefig(res_path + "Annotated_filtered_image_" + case[2] + ".png", bbox_inches="tight", pad_inches=0) plt.close(fig) if plots["Gyration_radius_filtered"]: size_dis_t1 = [i * ratio_μm_px for i in t1['size']] plt.figure("Gyration_radius_filtered_" + case[2]) plt.hist(size_dis_t1, bins=300, color="k", alpha=0.5) #plt.title("Gyration radius filtered case: "+ case[2]) plt.ylabel("Events", fontsize=size) plt.xlabel("Gyration radius [μm]", fontsize=size) plt.gca().spines['top'].set_visible(False) plt.gca().spines['right'].set_visible(False) plt.tick_params(axis="both", which="major", labelsize=size) plt.tick_params(axis="both", which="minor", labelsize=size) plt.savefig(res_path + "Gyration_radius_filtered" + case[2] + ".png", bbox_inches="tight", pad_inches=0) plt.close("all") if plots["Gyration_radius_unfiltered"]: size_dis_t = [i * ratio_μm_px for i in t['size']] plt.figure("Gyration_radius_unfiltered_" + case[2]) plt.hist(size_dis_t, bins=300, color="k", alpha=0.5) #plt.title("Gyration radius unfiltered case: " + case[2]) plt.ylabel("Events", fontsize=size) plt.xlabel("Gyration radius [μm]", fontsize=size) plt.gca().spines['top'].set_visible(False) plt.gca().spines['right'].set_visible(False) plt.tick_params(axis="both", which="major", labelsize=size) plt.tick_params(axis="both", which="minor", labelsize=size) plt.savefig(res_path + "Gyration_radius_unfiltered" + case[2] + ".png", bbox_inches="tight", pad_inches=0) plt.close("all") d = tp.compute_drift(t1) tm = tp.subtract_drift(t1, d) if plots["Trajectory_drift"]: fig = plt.figure("Trajectory_drift_subtracted_" + case[2]) ax1 = fig.add_subplot() ax1.tick_params(axis="both", which="major", labelsize=size) ax1.tick_params(axis="both", which="minor", labelsize=size) ax1.spines['top'].set_visible(False) ax1.spines['right'].set_visible(False) tp.plot_traj(tm, ax=ax1) #ax1.set_title("Trajectory with drift subtracted case: " + case[2]) plt.savefig(res_path + "Trajectory_drift_subtracted_" + case[2] + ".png", bbox_inches="tight", pad_inches=0) plt.close(fig) if plots["Variance_all_parts"]: im = tp.imsd( tm, ratio_μm_px, fps, max_lagtime=225 ) # microns per pixel = 100/285., frames per second = 24 plt.figure("Variance_for_all_particles_" + case[2]) #plt.title("Variance for all particles case: " + case[2]) plt.plot(im.index, im, 'k-', alpha=0.1) # black lines, semitransparent plt.ylabel(r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', fontsize=size), plt.xlabel('time $t$', fontsize=size) plt.gca().spines['top'].set_visible(False) plt.gca().spines['right'].set_visible(False) plt.xscale('log') plt.yscale('log') plt.savefig(res_path + "Variance_for_all_particles_" + case[2] + ".png", bbox_inches="tight", pad_inches=0) if plots["Variance_linear"] or plots["Variance_power_fit"] or plots[ "Return_A_and_D"]: em = tp.emsd(tm, ratio_μm_px, fps, max_lagtime=225) if plots["Variance_linear"]: plt.figure("Variance_linear_fit_" + case[2]) #plt.title("Variance linear fit case: " + case[2]) plt.plot(em.index, em, 'ko', alpha=0.5) plt.ylabel(r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', fontsize=size), plt.xlabel('time $t$ [s]', fontsize=size) plt.gca().spines['top'].set_visible(False) plt.gca().spines['right'].set_visible(False) plt.tick_params(axis="both", which="major", labelsize=size) plt.tick_params(axis="both", which="minor", labelsize=size) plt.xscale('log') plt.yscale('log') plt.ylim(1e-2, 50) plt.savefig(res_path + "Variance_linear_fit_" + case[2] + ".png", bbox_inches="tight", pad_inches=0) if plots["Variance_power_fit"]: fig = plt.figure("Variance_power_fit_" + case[2]) ax1 = fig.add_subplot() tp.utils.fit_powerlaw(em, ax=ax1, color="k", alpha=0.5) #ax1.set_title("Variance power fitted case: " + case[2]) ax1.set_ylabel(r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', fontsize=size) ax1.set_xlabel('time $t$ [s]', fontsize=size) plt.gca().spines['top'].set_visible(False) plt.gca().spines['right'].set_visible(False) ax1.tick_params(axis="both", which="major", labelsize=size) ax1.tick_params(axis="both", which="minor", labelsize=size) fig.savefig(res_path + "Variance_power_fit_" + case[2] + ".png", bbox_inches="tight", pad_inches=0) plt.close(fig) if plots["Hydrodynamic_radius_filtered"]: im = tp.imsd(tm, ratio_μm_px, fps, max_lagtime=225) r_h = [] count = 0 im = im.rename_axis("ID").values for index in range(1, len(im[0])): if isinstance(im[40][index], float) and isinstance( im[8][index], float): D = (im[40][index] - im[8][index]) / (4 * (40 - 8) / fps) * 10**(-12) if isinstance(D, float): r_h += [abs(10**6 * (k_b * T) / (6 * np.pi * μ * D))] if 0 < abs(10**6 * (k_b * T) / (6 * np.pi * μ * D)) < 6: count += 1 print("In interval: ", count, "Total: ", len(r_h), "Ratio: ", count / len(r_h)) plt.figure("Hydrodynamic_radius_filtered_" + case[2]) plt.hist(r_h, bins=int(count / 3), color="k", alpha=0.5, range=(0, 6)) #plt.title("Hydrodynamic radius filtered case: "+ case[2]) plt.ylabel("Trajectories", fontsize=size) plt.xlabel("Hydrodynamic radius [μm]", fontsize=size) plt.gca().spines['top'].set_visible(False) plt.gca().spines['right'].set_visible(False) plt.tick_params(axis="both", which="major", labelsize=size) plt.tick_params(axis="both", which="minor", labelsize=size) plt.savefig(res_path + "Hydrodynamic_radius_filtered" + case[2] + ".png", bbox_inches="tight", pad_inches=0) plt.close("all") if plots["Return_A_and_D"]: A = tp.utils.fit_powerlaw(em, ax=ax1, color="k", alpha=0.5)["A"] * 10**(-12) print(tp.utils.fit_powerlaw(em, ax=ax1, color="k", alpha=0.5)) print("For case ", case[2], " A=", A, ", and D=", A / 4, ".")
def add_mean_msd2( ax, df, pixel_size, frame_rate, divide_num, cat_col=None, cat_order=None, color_order=None, RGBA_alpha=1, fitting_linewidth=3, elinewidth=None, markersize=None, capsize=2, ): """ Add mean MSD curve in matplotlib axis. The MSD data are obtained from df. Parameters ---------- ax : object matplotlib axis to annotate ellipse. df : DataFrame DataFrame containing 'particle', 'frame', 'x', and 'y' columns cat_col : None or str Column to use for categorical sorting Returns ------- Annotate mean MSD in the ax. """ # """ # ~~~~Check if df is empty~~~~ # """ if df.empty: return # """ # ~~~~Prepare the data, category, color~~~~ # """ if cat_col: # cats if cat_order: cats = cat_order else: cats = sorted(df[cat_col].unique()) # dfs dfs = [df.loc[df[cat_col] == cat] for cat in cats] # cats_label cats_label = cats.copy() for i in range(len(cats_label)): cats_label[i] = cats_label[i] + ' (%d)' \ % len(dfs[i].drop_duplicates('particle')) # colors if color_order: palette = np.array(color_order) colors = np.zeros((palette.shape[0], 4)) colors[:, 0:3] = palette[:, 0:3] colors[:, 3] = RGBA_alpha else: palette = np.array(sns.color_palette('muted')) colors = np.zeros((palette.shape[0], 4)) colors[:, 0:3] = palette[:, 0:3] colors[:, 3] = RGBA_alpha else: dfs = [df] cats_label = ['MSD'] colors = [(0, 0, 0, RGBA_alpha)] # """ # ~~~~Prepare the data, category, color~~~~ # """ for i, df in enumerate(dfs): im = tp.imsd( df, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf, ) n = len(im.index) #for use in stand err calculation m = int(round(len(im.index) / divide_num)) im = im.head(m) im = im * 1e6 if len(im) > 1: # """ # ~~~~~~Plot the mean MSD data and error bar~~~~ # """ imsd_mean = im.mean(axis=1) imsd_std = im.std(axis=1, ddof=0) x = imsd_mean.index.to_numpy() y = imsd_mean.to_numpy() n_data_pts = np.sqrt(np.linspace(n - 1, n - m, m)) yerr = np.divide(imsd_std.to_numpy(), n_data_pts) # """ # ~~~~~~~~~~~Plot the fit of the average~~~~~~~~~~~~~~ # """ popt_log = fit_msd(x, y, space='log') fit_of_mean_msd = msd(x, popt_log[0], popt_log[1]) ax.plot( x, fit_of_mean_msd, '-', color=colors[i], label=cats_label[i], linewidth=fitting_linewidth, ) ax.errorbar( x, fit_of_mean_msd, yerr=yerr, linestyle='None', marker='.', markersize=markersize, elinewidth=elinewidth, capsize=capsize, color=colors[i], ) ax.legend()
def add_mean_msd(ax, df, pixel_size, frame_rate, divide_num, cat_col=None, cat_order=None, RGBA_alpha=0.5, fitting_linewidth=3, elinewidth=None, markersize=None, capsize=2, set_format=True): """ Add mean MSD curve in matplotlib axis. The MSD data are obtained from df. Parameters ---------- ax : object matplotlib axis to annotate ellipse. df : DataFrame DataFrame containing 'particle', 'frame', 'x', and 'y' columns cat_col : None or str Column to use for categorical sorting Returns ------- Annotate mean MSD in the ax. Examples -------- import matplotlib.pyplot as plt import pandas as pd from cellquantifier.plot.plotutil import add_mean_msd path = 'cellquantifier/data/physDataMerged.csv' df = pd.read_csv(path, index_col=None, header=0) fig, ax = plt.subplots() add_mean_msd(ax, df, 'exp_label', pixel_size=0.108, frame_rate=3.33, divide_num=5, RGBA_alpha=0.5) plt.show() """ # """ # ~~~~~~~~~~~Check if df is empty~~~~~~~~~~~~~~ # """ if df.empty: return # """ # ~~~~~~~~~~~Prepare the data, category, color~~~~~~~~~~~~~~ # """ if cat_col: if cat_order: cats = cat_order else: cats = sorted(df[cat_col].unique()) dfs = [df.loc[df[cat_col] == cat] for cat in cats] colors = plt.cm.coolwarm(np.linspace(0,1,len(cats))) colors[:, 3] = RGBA_alpha cats_label = cats.copy() if 'sort_flag_' in cat_col: for m in range(len(cats_label)): cats_label[m] = cat_col[len('sort_flag_'):] + ': ' + str(cats[m]) cats_label[m] = cats_label[m] + ' (%d)' % len(dfs[m].drop_duplicates('particle')) else: for m in range(len(cats_label)): cats_label[m] = cats_label[m] + ' (%d)' % len(dfs[m].drop_duplicates('particle')) else: dfs = [df] cats_label = ['MSD'] colors = [(0, 0, 0, RGBA_alpha)] for i, df in enumerate(dfs): # Calculate individual msd im = tp.imsd(df, mpp=pixel_size, fps=frame_rate, max_lagtime=np.inf) #cut the msd curves and convert units to nm n = len(im.index) #for use in stand err calculation m = int(round(len(im.index)/divide_num)) im = im.head(m) im = im*1e6 if len(im) > 1: # """ # ~~~~~~~~~~~Plot the mean MSD data and error bar~~~~~~~~~~~~~~ # """ imsd_mean = im.mean(axis=1) imsd_std = im.std(axis=1, ddof=0) #print(imsd_std) x = imsd_mean.index.to_numpy() y = imsd_mean.to_numpy() n_data_pts = np.sqrt(np.linspace(n-1, n-m, m)) yerr = np.divide(imsd_std.to_numpy(), n_data_pts) # # """ # # ~~~~~~~~~~~Plot the fit of the average~~~~~~~~~~~~~~ # # """ popt_log = fit_msd(x, y, space='log') fit_of_mean_msd = msd(x, popt_log[0], popt_log[1]) ax.plot(x, fit_of_mean_msd, color=colors[i], label=cats_label[i], linewidth=fitting_linewidth) ax.errorbar(x, fit_of_mean_msd, yerr=yerr, linestyle='None', marker='.', markersize=markersize, elinewidth=elinewidth, capsize=capsize, color=colors[i]) # """ # ~~~~~~~~~~~Set the label~~~~~~~~~~~~~~ # """ if set_format: ax.spines['right'].set_visible(False) ax.spines['top'].set_visible(False) ax.spines['left'].set_linewidth(2) ax.spines['bottom'].set_linewidth(2) ax.tick_params(labelsize=13, width=2, length=5) ax.set_xlabel(r'$\mathbf{Time (s)}$', fontsize=15) ax.set_ylabel(r'$\mathbf{MSD(nm^2)}$', fontsize=15)