Пример #1
0
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)
Пример #2
0
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
Пример #3
0
    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)
Пример #5
0
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
Пример #6
0
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
Пример #7
0
    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)
Пример #8
0
    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)
Пример #9
0
    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()
Пример #10
0
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
Пример #11
0
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()
Пример #12
0
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$')
Пример #13
0
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
Пример #14
0
    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')
Пример #15
0
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()
Пример #16
0
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()
Пример #17
0
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()
    
    
Пример #18
0
                             ['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)
Пример #19
0
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()
Пример #20
0
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')
Пример #21
0
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
Пример #22
0
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, ".")
Пример #23
0
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()
Пример #24
0
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)