def test_calc_ratio_mean_sd_num(): numer_mean = 1 denom_mean = 4 numer_sd =0.25 denom_sd = 0.8 result = ep.calc_ratio_mean_sd(numer_mean, numer_sd, denom_mean, denom_sd) # Check that return value is an iterable (should be a tuple) with two # entries, each a number ok_(isinstance(result, tuple)) ok_(len(result) == 2)
def test_calc_ratio_mean_sd_array(): numer_mean = np.array([1, 2, 3]) denom_mean = np.array([2, 4, 6]) numer_sd = np.array([0.25, 0.3, 0.35]) denom_sd = np.array([0.5, 0.6, 0.7]) result = ep.calc_ratio_mean_sd(numer_mean, numer_sd, denom_mean, denom_sd) # Check that return value is an iterable (should be a tuple) with two # entries, each a number ok_(isinstance(result, tuple)) (ratio_mean, ratio_sd) = result ok_(isinstance(ratio_mean, np.ndarray)) ok_(isinstance(ratio_sd, np.ndarray)) ok_(len(ratio_mean.shape) == 1) ok_(len(ratio_sd.shape) == 1) ok_(len(ratio_mean) == len(ratio_sd)) ok_(len(ratio_mean) == len(numer_mean))
def calculate_fret_from_endpoints(wells, fda, fd, fa, bg, num_pts=20, plot=True): """Calculate FRET using the endpoints of the FDA and FD conditions. For the donor + acceptor, subtracts the acceptor-only background average; for the donor-only, subtracts the no donor/no acceptor background average. Then takes the average of the last num_pts of the background-subtracted traces to get the fluorescence value for that condition/replicate. To get an estimate of error across replicates, the values for the FDA and FA wells are then averaged across replicates, yielding a mean fluorescence for each with an associated standard error. The FRET is then calculated by taking the ratio, and the standard error of the FRET value is calculated by sampling the standard deviation of the ratio of two normal distributions with means and standard deviations matching those of the mean and standard errors of the FDA and FD conditions. Note that this approach accounts for error across replicates, but not for error in determining the mean fluorescence of each individual replicate. However, it appears that the variability between replicates is substantially greater than the variability within a single fluorescence timecourse, and the standard error of the mean could be further reduced by averaging across more points. Parameters ---------- wells : collections.OrderedDict Dict containing the timecourses for each well in the plate. fda, fd, fa, bg : collections.OrderedDict Dicts mapping the concentration conditions to the well names of the replicates. num_pts : int The number of final points to average across. plot : boolean Whether to plot the FRET results (defaults to True) Returns ------- tuple : (bid_concs, fret_means, fret_ses) Tuple containing the concentrations of the unlabeled Bid used in each conditions; the mean FRET values calculated for each unabeled Bid concentration; and the standard error of the mean calculated by sampling. """ # Get the background averages bg_avg = get_average_bg(wells, bg, plot=False) fa_avg = get_average_fa(wells, fa, plot=False) # Initialize a few variables num_concs = len(fda.keys()) num_reps = 3 bid568_conc = 10. # Concentration of Bid-568, in nM fda_endpoints = np.zeros((num_concs, num_reps)) fd_endpoints = np.zeros((num_concs, num_reps)) bid_concs = np.zeros(num_concs) # Iterate over the conditions for conc_ix, conc_name in enumerate(fda.keys()): bid_concs[conc_ix] = float(conc_name.split(' ')[1]) # FDA for rep_ix, well_name in enumerate(fda[conc_name]): fda_value = np.array(wells[well_name][VALUE]) # Subtract the FA background: fda_value = fda_value - fa_avg # Calculate endpoint value over last num_pts endpt = np.mean(fda_value[-num_pts:]) fda_endpoints[conc_ix, rep_ix] = endpt # FD for rep_ix, well_name in enumerate(fd[conc_name]): fd_value = np.array(wells[well_name][VALUE]) # Subtract the BG background: fd_value = fd_value - bg_avg # Calculate endpoint value over last num_pts endpt = np.mean(fd_value[-num_pts:]) fd_endpoints[conc_ix, rep_ix] = endpt # Now, calculate the means of the endpts across replicates fda_means = np.mean(fda_endpoints, axis=1) fd_means = np.mean(fd_endpoints, axis=1) fda_ses = np.std(fda_endpoints, axis=1, ddof=1) / np.sqrt(float(num_reps)) fd_ses = np.std(fd_endpoints, axis=1, ddof=1) / np.sqrt(float(num_reps)) # Calculate the mean and SEM of the FDA/FD ratio distributions fret_tuples = [calc_ratio_mean_sd(fda_means[i], fda_ses[i], fd_means[i], fd_ses[i]) for i in range(len(fda_means))] # Convert the list of tuples into two separate lists (fret_means, fret_ses) = zip(*fret_tuples) # Now convert to numpy arrays. We take 1 - the FRET values so that we get # FRET in terms of FRET efficiency instead of % quenching: fret_means = 1 - np.array(fret_means) fret_ses = np.array(fret_ses) if plot: plt.figure('FDA and FD, mean/SEM over reps') plt.errorbar(np.log10(bid_concs), fda_means, yerr=fda_ses) plt.errorbar(np.log10(bid_concs), fd_means, yerr=fd_ses) plt.xlabel('log10([WT Bid]) (nM)') plt.ylabel('RFU') plt.xlim([-0.5, 3.1]) plt.title('FDA and FD, mean/SEM over reps') plt.figure('FRET') plt.errorbar(np.log10(bid_concs), fret_means, yerr=fret_ses) plt.xlabel('log10([WT Bid]) (nM)') plt.ylabel('FRET (%)') plt.xlim([-0.5, 3.1]) plt.title('FRET') return (bid_concs, fret_means, fret_ses)
def quenching_std_curve(dpx_std_file_list, dpx_std_wells, dpx_concs, bg_avgs=None): """Calculates and plots the quenching std curve from the raw ANTS data. Parameters ---------- dpx_std_file_list : list of strings Names of the text files (exported from the FlexStation plate reader) containing the raw fluorescence data at each quenching step. dpx_std_wells : list of strings Names of the replicate wells measured in the quenching assay, e.g., ['A1', 'A2', 'A3'] etc. dpx_concs : numpy.array The concentrations of DPX at each quenching step. Returns ------- tuple : (i_avgs, i_sds, fmax_avg) A tuple; the first element in the tuple is the array of mean quenching values, given as I / I_0, that is, the ratio of the fluorescence at a given amount of DPX to the unquenched fluorescence. The second element contains the standard deviations of this ratio at each concentration. The third element is the average fluorescence intensity of the lysed, unquenched liposomes (liposomes after Triton but before DPX addition. """ num_dilutions = len(dpx_concs) # We'll store the means and SDs for the fluorescence intensities at # each DPX concentration in here: dpx_intensity_avgs = np.zeros(num_dilutions) dpx_intensity_sds = np.zeros(num_dilutions) # Iterate over the files containing the intensity data for dilution_index, std_file in enumerate(dpx_std_file_list): well_vals = np.array([]) timecourse_wells = read_flexstation_kinetics(std_file) # Iterate over all the wells used in the standard curve, calculate # the read average for each one and add it to a list for well_name in dpx_std_wells: well_vals = np.concatenate((well_vals, timecourse_wells[well_name][VALUE])) #well_avgs.append(np.mean(timecourse_wells[well_name][VALUE])) # Now take the average and SD over all of the replicate wells dpx_intensity_avgs[dilution_index] = np.mean(well_vals) dpx_intensity_sds[dilution_index] = np.std(well_vals) # Plot the intensity values at each DPX concentration plt.figure() plt.errorbar(dpx_concs, dpx_intensity_avgs, yerr=dpx_intensity_sds, color='k', linewidth=2) plt.xlabel('[DPX] (M)') plt.ylabel('ANTS Fluorescence (RFU)') plt.title('ANTS Fluorescence vs. [DPX]') # If we have background values, subtract them here if bg_avgs is not None: if not len(bg_avgs) == num_dilutions: return ValueError("The background array must have as many entries " "as there are DPX concentraitons.") dpx_intensity_avgs = dpx_intensity_avgs - bg_avgs # Now calculate the intensity ratios, I / I_0 # To get the standard error of the ratio, we have to account for the # error in both the numerator and the denominator: i_vals = np.zeros(num_dilutions) i_sds = np.zeros(num_dilutions) for i in range(num_dilutions): (i_vals[i], i_sds[i]) = calc_ratio_mean_sd( dpx_intensity_avgs[i], dpx_intensity_sds[i], dpx_intensity_avgs[0], dpx_intensity_sds[0]) return (i_vals, i_sds, dpx_intensity_avgs[0], dpx_intensity_sds[0])
def requenching_analysis(requench_file_list, requench_wells, requench_dpx_concs, q_outs, fmax_avg, fmax_sd, ka, kd, dpx_0, bg_avgs=None, do_plot=True): """Calculates and plots the quenching std curve from the raw ANTS data. Parameters ---------- requench_file_list : list of strings Names of the text files (exported from the FlexStation plate reader) containing the raw fluorescence data at each quenching step. requench_wells : list of strings Names of the replicate wells measured in the quenching assay, e.g., ['A1', 'A2', 'A3'] etc. requench_dpx_concs : numpy.array The concentrations of DPX at each quenching step. """ # FIXME add other comments to docstring # We know how much of the stock DPX we added at each quenching step, but we # have to calculate the actual concentrations: num_dilutions = len(requench_dpx_concs) num_wells = len(requench_wells) # We'll store the means and SDs for the fluorescence intensities at # each DPX concentration in here: requench_well_avgs = np.zeros((num_dilutions, num_wells)) requench_well_sds = np.zeros((num_dilutions, num_wells)) # Iterate over the files containing the intensity data for dilution_index, requench_file in enumerate(requench_file_list): timecourse_wells = read_flexstation_kinetics(requench_file) # Iterate over all the wells, calculate the read average for each one # and add it to a list for well_index, well_name in enumerate(requench_wells): if bg_avgs is not None: well_values = (timecourse_wells[well_name][VALUE] - bg_avgs[dilution_index]) else: well_values = timecourse_wells[well_name][VALUE] requench_well_avgs[dilution_index, well_index] = \ np.mean(well_values) requench_well_sds[dilution_index, well_index] = \ np.std(well_values) # Plot the intensity values at each DPX concentration if do_plot: plt.figure() for well_index in range(num_wells): plt.errorbar(requench_dpx_concs, requench_well_avgs[:, well_index], yerr=requench_well_sds[:, well_index]) plt.xlabel('[DPX] (M)') plt.ylabel('ANTS Fluorescence (RFU)') plt.title('ANTS Fluorescence vs. [DPX]') # Now calculate the total quenching, I / F_max, for each well q_tot_by_well_avgs = np.zeros((num_dilutions, num_wells)) q_tot_by_well_sds = np.zeros((num_dilutions, num_wells)) for well_index, well_name in enumerate(requench_wells): # If we've been given a list of fmax avgs/sds for each well, use the # one for this well; otherwise, assume we've been given a single value # for all wells and use that try: cur_fmax_avg = fmax_avg[well_index] cur_fmax_sd = fmax_sd[well_index] except IndexError: cur_fmax_avg = fmax_avg cur_fmax_sd = fmax_sd # The error associated with the total quenching depends on the # error of the reads for this well/dilution, and the error of the # maximum fluorescence for dilution_index in range(num_dilutions): (q_tot_avg, q_tot_sd) = calc_ratio_mean_sd( requench_well_avgs[dilution_index, well_index], requench_well_sds[dilution_index, well_index], cur_fmax_avg, cur_fmax_sd) q_tot_by_well_avgs[dilution_index, well_index] = q_tot_avg q_tot_by_well_sds[dilution_index, well_index] = q_tot_sd # Calculate the (predicted) Q_out for each of the DPX concentrations used #q_outs = np.array([1. / quenching_func(ka, kd, dpx_conc) # for dpx_conc in requench_dpx_concs]) # FIXME have q_out get associated error by sampling from ka/kd dists # Plot the Q_total / Q_out curves (should be straight lines) q_ins = np.zeros(num_wells) q_in_errs = np.zeros(num_wells) f_outs = np.zeros(num_wells) f_out_errs = np.zeros(num_wells) #plt.figure() for well_index, well_name in enumerate(requench_wells): #if well_index < 30: # continue if do_plot: plt.figure() #plt.subplot(6, 6, well_index+1) plt.errorbar(q_outs, q_tot_by_well_avgs[:, well_index], q_tot_by_well_sds[:, well_index], linestyle='', color='k', linewidth=2) plt.title('$Q_{total}$ vs. $Q_{out}$ for well %s' % well_name) plt.xlim((0, 1)) plt.ylim((0, 1)) plt.xlabel('$Q_{out}$') plt.ylabel('$Q_{total}$') # Add tickmarks only to the plots on the edges #if well_index + 1 > 30 # plt.xticks([0, 0.5, 1.0]) # plt.xlabel('$Q_{out}$') #else: # plt.xticks([]) #if well_index % 6 == 0: # plt.yticks([0, 0.5, 1.0]) # plt.ylabel('$Q_{total}$') #else: # plt.yticks([]) linfit = scipy.stats.linregress(q_outs, q_tot_by_well_avgs[:, well_index]) f_out = linfit[0] intercept = linfit[1] #std_err = linfit[4] n = float(len(q_outs)) sd_slope = linfit[4] sd_intercept = np.sqrt((sd_slope ** 2) * np.sum(q_outs ** 2) / n) # Calculate the internal quenching (q_in_avg, q_in_sd) = calc_ratio_mean_sd(intercept, sd_intercept, 1 - f_out, sd_slope) # THIS IS ALL WRONG! #mean_x = np.mean(q_outs) #sx2 = np.sum((q_outs - mean_x)**2) #sd_intercept = std_err * np.sqrt(1. / len(q_outs) + mean_x*mean_x/sx2) #sd_slope = std_err * np.sqrt(1./sx2) if do_plot: plt.plot(q_outs, (q_outs * f_out) + intercept, color='r', linewidth=1) plt.text(0.05, 0.9, '$F_{out}\ \mathrm{(slope)}\ = %f$' % f_out) plt.text(0.05, 0.8, '$Q_{in}(1 - F_{out})\ \mathrm{(intercept)}\ = %f$' % intercept) plt.text(0.05, 0.7, '$Q_{in} = %f$' % q_in_avg) plt.text(0.05, 0.6, '$R^2 = %f$' % linfit[2]) # Save the results for this well f_outs[well_index] = f_out f_out_errs[well_index] = sd_slope q_ins[well_index] = q_in_avg q_in_errs[well_index] = q_in_sd #plt.tight_layout() # This error is not meaningful because it doesn't account for errorbars! # FIXME FIXME FIXME linfit = scipy.stats.linregress(f_outs, q_ins) f_out_pred = np.linspace(0, 1, 100) if do_plot: plt.figure() plt.errorbar(f_outs, q_ins, xerr=f_out_errs, yerr=q_in_errs, marker='o', color='k', linestyle='') #plt.plot(f_outs[0:12], q_ins[0:12], marker='o', color='r', # linestyle='') #plt.plot(f_outs[12:24], q_ins[12:24], marker='o', color='g', # linestyle='') #plt.plot(f_outs[24:36], q_ins[24:36], marker='o', color='b', # linestyle='') plt.xlabel('$F_{out}$') plt.ylabel('$Q_{in}$') plt.xlim([-0.2, 1.1]) plt.ylim([-0.2, 1.1]) plt.title('$Q_{in}$ vs. $F_{out}$') plt.plot(f_out_pred, (f_out_pred * linfit[0]) + linfit[1], color='r') plt.text(0.1, 0.9, 'Slope = %f' % linfit[0]) plt.text(0.1, 0.85, 'Intercept = %f' % linfit[1]) plt.text(0.1, 0.8, '$R^2 = %f$' % linfit[2]) plt.text(0.1, 0.75, 'p = %f' % linfit[3]) return {'f_outs': f_outs, 'q_ins': q_ins, 'f_out_errs': f_out_errs, 'q_in_errs': q_in_errs}
def quenching_std_curve_by_well(dpx_std_file_list, dpx_std_wells, dpx_concs): """Calculates and plots the quenching std curve from the raw ANTS data. Parameters ---------- dpx_std_file_list : list of strings Names of the text files (exported from the FlexStation plate reader) containing the raw fluorescence data at each quenching step. dpx_std_wells : list of strings Names of the replicate wells measured in the quenching assay, e.g., ['A1', 'A2', 'A3'] etc. dpx_concs : numpy.array The concentrations of DPX at each quenching step. Returns ------- (i_avgs, i_sds) A tuple of arrays; the first element in the tuple is the array of mean quenching values, given as I / I_0, that is, the ratio of the fluorescence at a given amount of DPX to the unquenched fluorescence. The second element contains the standard deviations of this ratio at each concentration. """ # We know how much of the stock DPX we added at each quenching step, but we # have to calculate the actual concentrations: num_dilutions = len(dpx_concs) num_wells = len(dpx_std_wells) # We'll store the means and SDs for the fluorescence intensities at # each DPX concentration in here: #dpx_intensity_avgs = np.zeros(num_dilutions) #dpx_intensity_sds = np.zeros(num_dilutions) dpx_well_avgs = np.zeros((num_dilutions, num_wells)) dpx_well_sds = np.zeros((num_dilutions, num_wells)) # Iterate over the files containing the intensity data for dilution_index, std_file in enumerate(dpx_std_file_list): timecourse_wells = read_flexstation_kinetics(std_file) # Iterate over all the wells used in the standard curve, calculate # the read average for each one and add it to a list for well_index, well_name in enumerate(dpx_std_wells): dpx_well_avgs[dilution_index, well_index] = \ np.mean(timecourse_wells[well_name][VALUE]) dpx_well_sds[dilution_index, well_index] = \ np.std(timecourse_wells[well_name][VALUE]) # Plot the intensity values at each DPX concentration plt.figure() for well_index in range(num_wells): plt.errorbar(dpx_concs, dpx_well_avgs[:, well_index], yerr=dpx_well_sds[:, well_index]) plt.xlabel('[DPX] (M)') plt.ylabel('ANTS Fluorescence (RFU)') plt.title('ANTS Fluorescence vs. [DPX]') # Now calculate the intensity ratios, I / I_0, **for each well** i_avgs_by_well = np.zeros((num_dilutions, num_wells)) i_sds_by_well = np.zeros((num_dilutions, num_wells)) for well_index in range(num_wells): for dilution_index in range(num_dilutions): # To get the standard error of the ratio, we have to account for # the error in both the numerator and the denominator: (avg, sd) = calc_ratio_mean_sd( dpx_well_avgs[dilution_index, well_index], dpx_well_sds[dilution_index, well_index], dpx_well_avgs[0, well_index], dpx_well_sds[0, well_index]) i_avgs_by_well[dilution_index, well_index] = avg i_sds_by_well[dilution_index, well_index] = sd # Plot the individual I / I_0 curves plt.figure() for well_index in range(num_wells): plt.errorbar(dpx_concs, i_avgs_by_well[:, well_index], yerr=i_sds_by_well[:, well_index]) plt.xlabel('[DPX] (M)') plt.ylabel('$I / I_0$') plt.title('Quenching vs. [DPX]') # Now calculate the I / I_0 curve averaged over all replicates NOTE: we're # not taking into account the individual variances at each well (which are # relatively small) when we are calculate these means/sds. Doing so # could represent a slight improvement. i_avgs = np.mean(i_avgs_by_well, axis=1) i_sds = np.std(i_avgs_by_well, axis=1) fmax_avg = np.mean(dpx_well_avgs[0, :]) fmax_sd = np.std(dpx_well_avgs[0, :]) return (i_avgs, i_sds, fmax_avg, fmax_sd)