def caltrackmsd(self, m_to_p=0.0645, fps=2, plot=True): try: import trackpy as tp except ImportError: print('... install trackpy') exit if len(self._tdata) == 0: print('... add track data') exit em = tp.emsd(self._tdata, m_to_p, fps) a = tp.utils.fit_powerlaw(em, plot=False) tnumber = np.unique(self._tdata['particle'].values).max()+1 if plot: fig = plt.figure(figsize=(6,4)) x = pd.Series(em.index.values, index=em.index, dtype=np.float64) fits = x.apply(lambda x: a['A']*x**a['n']) plt.plot(em.index, em, 'o', label='exp. %i tracks' % tnumber) plt.plot(x, fits, label='y=%.4f x^{%.4f}'% (a['A'], a['n'])) ax = plt.gca() ax.set_xscale('log') ax.set_yscale('log') ax.set(ylabel=r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', xlabel='lag time $t$') plt.legend(loc='best') plt.tight_layout() fname = self._cwd.split('/')[-1]+'_trace_msd.pdf' plt.savefig(fname, dpi=300) plt.show() return a
def test_zero_emsd(self): N = 10 actual = tp.emsd(self.dead_still, 1, 1) expected = Series(np.zeros(N)).iloc[1:].astype('float64') expected.index.name = 'lagt' expected.name = 'msd' assert_series_equal(actual, expected)
def compute_emsd(traj, DT, omit_time=0, printing=False, DS=0.025): '''traj is a pandas.DataFrame instance with columns "frame", "particle", "x" and "y" containing the results of unwrapped trajectories. returns a pandas.DataFrane instance containing the ensemble mean squared displacement.''' #remove the first and last 150ms of each input trajectory by default n_rows_omit = int(omit_time / DT) indices_of_head = traj.groupby('particle').head(n_rows_omit).index indices_of_tail = traj.groupby('particle').tail(n_rows_omit).index drop_id_lst = list(indices_of_head.values) drop_id_lst.extend(list(indices_of_tail.values)) traj.drop(index=drop_id_lst, inplace=True) #truncate max lag to the min lifetime len_lst = traj.groupby('particle').x.count().values if len(len_lst) == 0: return None max_lag = np.min(len_lst) #frames #compute ensemble MSD emsd = trackpy.emsd( traj=traj, mpp=DS, fps=1 / DT, max_lagtime=max_lag, detail=False, pos_columns=None, ) if printing: print(f'max_lag was {DT*max_lag} ms') return emsd
def test_zero_emsd(self): N = 10 actual = tp.emsd(self.dead_still, 1, 1) expected = Series(np.zeros(N, dtype=np.float), index=np.arange(N, dtype=np.float)).iloc[1:] expected.index.name = 'lagt' expected.name = 'msd' assert_series_equal(actual, expected)
def _compute_general_msd(trajectory, space_scale, fps, max_lagtime=100): # Calculate the MSD msd = tp.emsd(trajectory, space_scale, fps, max_lagtime=max_lagtime) # Format into a 2-D numpy array msd = np.array([msd.index, msd.to_numpy()]) return msd.T
def test_zero_emsd(self): N = 10 actual = tp.emsd(self.dead_still, 1, 1) expected = Series(np.zeros(N, dtype=np.float), index=np.arange(N, dtype=np.float)).iloc[1:] expected.index.name = 'lagt' expected.name = 'msd' # HACK: Float64Index imprecision ruins index equality. # Test them separately. If that works, make them exactly the same. assert_almost_equal(actual.index.values, expected.index.values) actual.index = expected.index assert_series_equal(actual, expected)
def test_linear_emsd(self): A = 1 EARLY = 7 # only early lag times have good stats actual = tp.emsd(self.many_walks, 1, 1, max_lagtime=EARLY) a = np.arange(EARLY + 1, dtype='float64') expected = Series(2 * A * a, index=a).iloc[1:] expected.name = 'msd' expected.index.name = 'lagt' # HACK: Float64Index imprecision ruins index equality. # Test them separately. If that works, make them exactly the same. assert_almost_equal(actual.index.values, expected.index.values) actual.index = expected.index assert_series_equal(np.round(actual), expected)
def test_linear_emsd(self): A = 1 EARLY = 7 # only early lag times have good stats actual = tp.emsd(self.many_walks, 1, 1, max_lagtime=EARLY) a = np.arange(EARLY, dtype='float64') expected = Series(2*A*a, index=a).iloc[1:] expected.name = 'msd' expected.index.name = 'lag time [s]' # HACK: Float64Index imprecision ruins index equality. # Test them separately. If that works, make them exactly the same. assert_almost_equal(actual.index.values, expected.index.values) actual.index = expected.index assert_series_equal(np.round(actual), expected)
def test_linear_emsd_gaps(self): A = 1 EARLY = 4 # only early lag times have good stats gapped_walks = self.many_walks.reset_index(drop=True) to_drop = np.random.choice(gapped_walks.index, int(len(gapped_walks) * 0.1), replace=False) gapped_walks = gapped_walks.drop(to_drop, axis=0) actual = tp.emsd(gapped_walks, 1, 1, max_lagtime=EARLY) a = np.arange(EARLY+1, dtype='float64') expected = Series(2*A*a, index=a).iloc[1:] expected.name = 'msd' expected.index.name = 'lagt' # HACK: Float64Index imprecision ruins index equality. # Test them separately. If that works, make them exactly the same. assert_almost_equal(actual.index.values, expected.index.values) actual.index = expected.index assert_series_equal(np.round(actual), expected)
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 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 analyze(self, plot_gif=False): self.drifts = [] self.v_drift_mag = [] self.D_constants = [] self.D_constants2 = [] self.msd_slope = [] self.msd_intercept = [] self.mu_hats = [] self.ed = [] self.em = [] self.frames = [] self.dataframes = [] for i, path in enumerate(self.SXM_PATH): frames = SXMReader(path) self.frames.append(frames) self.NM_PER_PIXEL = frames.meters_per_pixel * 1e9 molecule_size, min_mass, max_mass, separation, min_size, max_ecc, adaptive_stop, search_range, _ = self.PARAMS[ i] f = tp.batch(frames, molecule_size, minmass=min_mass, separation=separation) t = tp.link(f, search_range=search_range, adaptive_stop=adaptive_stop) t1 = t[((t['mass'] > min_mass) & (t['size'] > min_size) & (t['ecc'] < max_ecc)) & (t['mass'] < max_mass)] t2 = tp.filter_stubs(t, 3) # Compare the number of particles in the unfiltered and filtered data. print('Before:', t['particle'].nunique()) print('After:', t2['particle'].nunique()) if plot_gif == True: moviename = "{}-{}".format(min(self.fileranges[i]), max(self.fileranges[i])) singlemoviefolder = self.MOVIE_FOLDER + moviename + "/" if not os.path.exists(singlemoviefolder): os.makedirs(singlemoviefolder) mpl.rcParams.update({'font.size': 14, 'font.weight': 'bold'}) mpl.rc('image', origin='lower') mpl.rc('text', usetex=False) mpl.rc('text', color='orange') fns = [] for j, frame in enumerate(frames): fig = plt.figure(figsize=(5, 5)) tp.plot_traj(t2[(t2['frame'] <= j)], superimpose=frames[j], label=True) fn = singlemoviefolder + "Image_{}.png".format( self.fileranges[i][j]) fig.savefig(fn) fns.append(fn) ax = plt.gca() # get the axis ax.set_ylim(ax.get_ylim()[::-1]) # invert the axis ax.xaxis.tick_top() # and move the X-Axis ax.yaxis.set_ticks(np.arange(0, 16, 1)) # set y-ticks ax.yaxis.tick_left() # remove right y-Ticks plt.clf() mpl.rc('text', color='black') images = [] for fn in fns: images.append(imageio.imread(fn)) imageio.mimsave(singlemoviefolder + moviename + '.gif', images, duration=0.5) self._cleanup_png(singlemoviefolder) # Compute drifts d = tp.compute_drift(t2) d.loc[0] = [0, 0] t3 = t2.copy() # Storing drifts self.drifts.append(d) # Method 1 of calculating D: variance of all displacements of Delta_t=1 displacements = self._calculate_displacements(t3) self.D_constants.append( (displacements.dx.var() + displacements.dy.var()) / 4) # r^2 = x^2 + y^2 = 2Dt + 2Dt self.mu_hats.append(np.mean(displacements[['dx', 'dy']], axis=0)) # Method 2 of calculating D: linear fit to MSD em = tp.emsd(t3, frames.meters_per_pixel * 1e9, self.DIFFUSION_TIME, max_lagtime=len(frames), detail=True) self.em.append(em) self.ed.append([em['<x>'], em['<y>']]) result = linregress(em.index[:-8] * self.DIFFUSION_TIME, em['msd'][:-8]) self.msd_slope.append(result.slope) self.msd_intercept.append(result.intercept) self.D_constants2.append(result.slope / 4) # Store dataframe for future analysis self.dataframes.append(t3) self.v_drift_mag = np.linalg.norm(self.mu_hats, 2, axis=1)
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') ax.set(ylabel=r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', xlabel='lag time $t$', title='Ensemble MSD') ax.set(ylim=(1e-2, 10)); ##Fitting the EMSD #plt.figure() plt.ylabel(r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]') plt.title("EMSD Fit")
fps = 25 # frame per second maxact = 11 ##fig, ax = plt.subplots() # for ploting msd curve of all activites #plt.figure('MSD for aactivities') #plt.clf() for act in range(8, 12): # loop for file name print('Activity', act) # load trajectory traj_f = pd.read_csv(savepath_traj_f.format(act)) #============================================================================== # ## Mean Squared Displacement of Individal Probes # im = tp.imsd(traj_f, mpp, fps, max_lagtime=100, statistic='msd') # microns per pixel = 100/285., frames per second = 24 # # fig, ax = plt.subplots() # ax.plot(im.index, im[18], 'k-', alpha=0.1) # black lines, semitransparent # ax.set(ylabel=r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', xlabel='lag time $t$') # ax.set_xscale('log') # ax.set_yscale('log') #============================================================================== ## Ensemble MSD em = tp.emsd(traj_f, mpp, fps, max_lagtime=1600, detail=True) #detail=True to see also <x>,<y>,<x^2>,<y^2> # save MSD em.to_csv(savepath_MSD.format(act), index=False)
tp.plot_traj(t1) d = tp.compute_drift(t1) d.plot() plt.show() plt.savefig("1.pdf") tm = tp.subtract_drift(t1.copy(),d) ax = tp.plot_traj(tm) plt.show() plt.savefig("2.pdf") em = tp.emsd(tm, 0.00000119029/1, 30) # microns per pixel = 100/285., frames per second = 24 fig, ax = plt.subplots() ax.plot(em.index, em, 'o') ax.set_xscale('log') ax.set_yscale('log') ax.set(ylabel=r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]', xlabel='lag time $t$') ax.set(ylim=(1e-2, 100)); plt.savefig("3.pdf") plt.figure() plt.ylabel(r'$\langle \Delta r^2 \rangle$ [$\mu$m$^2$]') plt.xlabel('lag time $t$'); atre = tp.utils.fit_powerlaw(em) # performs linear best fit in log space, plots] plt.savefig("4.pdf")
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, ".")
max_lagtime = 500 nop = 500 # settings end # reference line x = [0.01,1,10,100,1000] y = x dxb = 0 dyb = 0 datapath = '/Users/Zhengyang/Documents/20160715/a1l' filename = os.path.join(datapath,'trajectory.dat') traj = pd.read_csv(filename,delimiter=',') #remove drift msd = tp.emsd(traj,mpp,fps,max_lagtime,detail=True) p1 = np.polyfit(msd['lagt'],msd['<x>'],1) p2 = np.polyfit(msd['lagt'],msd['<y>'],1) trajr = traj trajr['x'] = traj['x']-p1[0]*traj['frame']/fps trajr['y'] = traj['y']-p2[0]*traj['frame']/fps # mean squared displacement msd = tp.emsd(trajr,mpp,fps,max_lagtime,detail=True) plt.ion() plt.figure(1) plt.loglog(msd['lagt'],msd['msd'],linestyle='None',marker='o',mec='r',mfc='w') plt.loglog(x,y,linestyle='solid') plt.draw()
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()