<jupyter_start><jupyter_text>Plotting FRAP Data<jupyter_code># Tells matplotlib to put plot in jupyter
%matplotlib inline
import matplotlib.pyplot as plt
import sys
import numpy as np
import random as rand 
import matplotlib as mpl
import matplotlib.cm as cm
import pandas as pd

with plt.style.context('bmh'):
    fig = plt.figure(figsize = (8, 6))
    ax = fig.add_subplot(1, 1, 1, facecolor = 'white')

    #font
    mpl.rcParams['font.family'] = 'sans-serif'
    mpl.rcParams['font.sans-serif'] = ['Arial']
    font_size = 20
    ax.set_xlabel('Time (s)', fontsize = font_size, color = 'black')
    ax.set_ylabel('Normalized\n Fluorescence (A.U.)', fontsize = font_size, color = 'black')
    #tick font
    label_size = 30
    plt.xticks(fontsize = 15)
    plt.yticks(fontsize = 15)
    #legend
    # ax.plot(x, y, label = "Exp", color = 'steelblue')
    # ax.plot(x, z, label = "Control", color = 'orange')

    df = pd.read_excel('Example_bleached_pole.xlsx')
    dfc = pd.read_excel('Example_unbleached_pole.xlsx')
    x1 = dfc['Time']
    u = dfc['Unbleached Pole']
    v = dfc['Standard Error']
    w = df['Standard Error']
    x = df['Time']
    y = df['Bleached Pole']
 
    
    ax.plot(x , y , '.-', linewidth = 2, color = '#49a078')
    ax.plot(x1 , u, '.-', linewidth = 2, color = '#f98745')
#     ax.scatter(x , y, c = 'black' )

    plt.ylim(0,1.2)

#   Shade Standard error
    ax.fill_between(x, y - w, y + w, color = ('#49a078'), alpha = 0.25, edgecolor = 'black', linewidth = 1.5)
    ax.fill_between(x1 , u - v, u + v, color = ('#f98745'), alpha = 0.25, edgecolor = 'black', linewidth = 1.5 )
    
#     lgd = ax.legend(loc= (1,0.8675), frameon=True, fontsize = font_size/1.5, facecolor = 'white', framealpha = 0.5)
    
    ax.text(90, 0, "n = 12", fontsize = font_size)
    


#     plt.savefig('Example.svg', format = 'svg', dpi = 1200)<jupyter_output><empty_output><jupyter_text>Experimental (Bleached pole curve fit) Here's the procedure:1. Load the data2. Define a function for curve fitting3. Fit the curve4. Plot the data to make sure it fits well<jupyter_code># Import necessary packages

import seaborn as sns  # Since we're working with dataframes, this will make our visualization process easier
from scipy import optimize, stats
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import metrics
%matplotlib inline
  # I made this function to help with the plotting

def tsplot(df, mean='mean', sem='sem', Fit='Fit', xlab='Time(s)', ylab='Normalized Fluorescence (A.U)', legend=True, color="#49a078"):
    """
    Make a nice timeseries plot
    """
    fig = plt.figure(figsize = (9, 6))
    ax = fig.add_subplot(1, 1, 1, facecolor = 'white')
    m = df[mean]
    s = df[sem]
    ax.plot(df.index, m, ".-", lw=2, c=color, label=mean)
    ax.fill_between(df.index, m - s, m + s, color=color, alpha = 0.25, lw=0, label=sem)
    ax.set_xlabel(xlab, fontsize = 16)
    ax.set_ylabel(ylab, fontsize = 16)
    plt.xticks(fontsize = 14)
    plt.yticks(fontsize = 14)
    
    if Fit in df.columns:
        ax.plot(df.index, df[Fit], "k--", alpha = 0.75, lw=2, label=Fit)
        
        ax.text(75, 0.1, '$t$$_1$$_/$$_2$ = {} s\n $R$$^2$ = {} '.format(t_half_2dec, r2_2dec),  fontsize = font_size/1.3)
        
    if legend:
        ax.legend(loc='best', fontsize = 12)
#     plt.savefig('Example_fit.svg', format = 'svg', dpi = 1200)

    return ax

def get_stats(df):
    # Unfortunately the "agg" function isn't very flexible, so we have to transpose the data twice
    return df.T.agg(['mean', 'sem']).T<jupyter_output><empty_output><jupyter_text>Load the DataRead the excel file and display the output so we know what we're working with here<jupyter_code># This is a relative path so it's different on my machine
excel_path = 'Example_bleached_pole.xlsx'
raw_data = pd.read_excel(excel_path)

# I'm going to set the index as Time. Just to make display easier for the "time" being. Ha ha.
raw_data.set_index('Time', inplace=True)
display(raw_data)<jupyter_output><empty_output><jupyter_text>Let's make a pretty data frame to make things easierWe're going to ignore the columns you calculated in excel for now and use them to make sure all calculations are correct<jupyter_code># Here I use a nested list comprehension to only select columns that have an underscore
# This effectively ignores the columns "Bleached Pole" and "Standard Error"
data = raw_data.loc[:, [c for c in raw_data.columns if ("_" in c)]]
# data<jupyter_output><empty_output><jupyter_text>Here's a look at the data. It looks like what we expect** Note: ** seaborn doesn't natively plot standard error, so I did the standard deviation which is directly proporitional. You can ignore the deprecation warning<jupyter_code>data
# Make a dataframe of the statistics.

all_stats = get_stats(data)
all_stats
ax = tsplot(all_stats)
# We'll also filter out the times we don't need by only taking positive times
curve_data = data.loc[data.index >=0]

# So pretty!
display(curve_data.head())
curve_stats = get_stats(curve_data)
display(curve_stats)
ax = tsplot(curve_stats)<jupyter_output><empty_output><jupyter_text>If you want to ignore the times where there are NaNs, uncomment this line, but statistically you can probably keep themIf you do drop the NaN times, you will get different parameters<jupyter_code>#Need to drop NaN because that frame was all noise during acquisition
curve_stats = get_stats(curve_data.dropna())
ax = tsplot(curve_stats)<jupyter_output><empty_output><jupyter_text>Let's fit a curve!I used the function from __[this presentation](https://www.embl.de/eamnet/downloads/courses/FRAP2004/frap_intro_miura.pdf)__ (Slide 12).<jupyter_code>def f(t, a, tau):
    """
    :param t: array; x-values, usually time
    :param a: float; mobile fraction
    :param tau: float; exponential constant. related to half max time
    :return: float
    """
    return a*(1-np.exp(-tau*t))
popt, pcov = optimize.curve_fit(f, curve_stats.index, curve_stats['mean'])

# Popt is a tuple of the parameters A (the mobile fraction) and tau, which is related to the recover halflife
A, tau = popt
t_half = np.log(0.5)/-tau
popt
# Calculate the predicted values
p = f(curve_stats.index.values, *popt)
"""
Note my use of *popt. My function "f" defined above takes 3 arguments. popt is a tuple of length 2. The * syntax
unpacks the tuple as the rest of the arguments of the function

Because I explicitly unpacked them earlier in the line "A, tau = popt" this is equivalent to
p = f(curve_stats.index.values, A, tau)
"""
# The correlation looks pretty good
r2 = metrics.r2_score(curve_stats['mean'], f(curve_stats.index.values, *popt))
print(r2)
r2_float = float(r2)
r2_2dec = '{0:.3f}'.format(r2_float)
# Print the values
print("A: {}, \ntau: {}, \nt_half: {}, \nhalf_max: {}".format(A, tau, t_half, f(t_half, A, tau)))
t_half_float = float(t_half)
t_half_2dec = '{0:.2f}'.format(t_half_float)
## I don't understand how this works. Does this add a column 'prediction' to the curve_stats data frame?
# Let's add the prediction to the plot
curve_stats['Fit'] = p
tsplot(curve_stats)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.12652374947456915, 'fraction_numerical': 0.0201765447667087, 'mean_word_length': 4.109520400858983, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 30, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '626711', 'license': 'MIT', 'n_tokens_mistral': 2649, 'n_tokens_neox': 2479, 'n_words': 789, 'path': 'index.ipynb', 'repo_name': 'heleneayari/FRAP', 'size': '7137'}