This document explains how to use the functions provided by the rfret
package to analyze FRET binding data from titration experiments, and determine
the binding constant (Kd) of a macromolecular interaction. An example using a
real-life dataset is presented and discussed.
Analysis of FRET data can be broken down into the following steps, each of
which rfret
provides functions for:
inspect_raw_data()
);fret_average_replicates()
);fret_correct_signal()
);fit_binding_model()
).The fit_binding_model()
function is independent of the others. It can accept
any data from other types of experiments, as long as this data comes as two
columns called concentration
and signal
.
On the other hand, all the FRET data processing functions (named with a common
fret_
prefix) are designed to work together: each function produces an output
that can be directly used as input for the next one, making the whole analysis
free of any need for more data reformatting as long as input files are properly
formatted in the first place. These functions work ideally with the pipe
operator (%>%
) from the magrittr
package.
rfret
is designed such that the user doesn't have to manually do any
calculation or any edit to the numbers obtained from a plate reader instrument:
such manipulations in spreadsheet programs are time-consuming and error-prone,
and doing calculations in a spreadsheet can accidentally alter the raw data.
The raw data must be formatted like the following example. This first table shows the first 6 rows of a real-life dataset:
knitr::kable(head(rfret::fret_binding_data))
And this second table shows the last 6 rows of the same dataset:
knitr::kable(tail(rfret::fret_binding_data))
Most (if not all) plate reader instruments have an "export to CSV" feature,
which is best suited to save raw data in a format usable by rfret
. If offered
a choice between "plate layout" and "table view", choose "table view": this will
export the data in a format similar to the previous table.
The Well Row
and Well Col
columns present in this example dataset were
created by the plate reader software used to produce this dataset, but rfret
will simply ignore them and any other column except the following ones:
Content
fret_channel
acceptor_channel
donor_channel
concentration
Your own datasets don't have to use the same column names, because rfret
uses
a mechanism to map the names found in the actual data files to the names it uses
internally. This is achieved by providing a file in the JSON format indicating
these mappings. Note that the names mapped by this file are case-sensitive.
Using this method, you won't ever need to edit column names manually in each file
when you save your data (which is tedious and error-prone). However, you might
need to add the concentration
column manually if your plate reader software is
not aware of your titration series, and to fill the content
column manually as
well if your plate reader software doesn't allow you to describe the contents of
your plate before performing the measurements. The content
column should contain,
for each row, a name indicating what part of the experiment and what replicate
this row belongs to, with the format type.replicate
where type
can be any
word, and replicate
must be a number. They must be separated by a dot, and
there can be only one dot in the entire resulting character string. The example
dataset contains the following contents:
levels(as.factor(rfret::fret_binding_data$Content))
Here is an example of a JSON file mapping column names and contents description
to rfret
's internal names. In such a file, you would simply have to indicate
the names found in your data files in the rigth-hand side of the key-value pairs
(the left-hand side being the name used internally by rfret
):
{ // Only change the right-hand side of the pairs delimited by ':'. // Map internal column names to the corresponding column names in data files. "content": "Content", "concentration": "concentration", "fret_channel": "Raw Data (488-20/680-50 1)", "acceptor_channel": "Raw Data (620-30/680-50 2)", "donor_channel": "Raw Data (488-20/535-30 3)", // Map internal sample types to the corresponding factors in data files. "titration": "my_titration", "acceptor_only": "my_acceptor_only_series", "donor_only": "my_donor_only_series", "buffer_only": "my_buffer_only_series" }
This data preparation step is the only one for which you will need to use a spreadsheet program (you can also edit the CSV files in a simple text editor, but a spreadsheet displays this sort of data in a way that is much easier to navigate). This step can probably be automated in most plate reader softwares as well.
We first need to load the rfret
and magrittr
packages:
library(magrittr) library(rfret)
All fret_
functions in this package work by first concatenating together any
number of datasets, to perform all subsequent data processing and analysis steps
on a single, large internal dataframe. Any analysis must start by using the
format_data()
function to prepare the raw data.
The function format_data()
takes either:
It also needs a parameter data_type = "fret"
to indicate that we want to
pre-process FRET data (because rfret
can also handle FP data, and can be
extended to support more data types).
It will format the data properly for subsequent processing by the other functions.
A FRET experiment provides built-in controls for the correct preparation of the titration samples. In a typical experiment, the donor-labeled molecule is kept constant at a low concentration, and the acceptor-labeled molecule is titrated across a wide concentration series prepared by serial dilutions. Fluorescence detection is sensitive enough to detect very small pipetting errors, therefore, inspecting the fluorescence intensities in the donor and acceptor channels provides an easy way to check for outliers in the series.
The function inspect_raw_data()
takes the output of format_data()
and outputs, for each experiment, plots of the fluorescence intensity across the
titration series for the donor, acceptor and FRET channels.
Let's look at an example:
fret_binding_data %>% format_data(data_type = "fret") %>% inspect_raw_data(data_type = "fret")
In the donor channel plot, all fluorescence intensities should be equal, since the donor-labeled molecule is present at the same concentration in all samples. In the titration experiment, it is expected that the fluorescence intensity of the donor channel will decrease at high concentration of acceptor if FRET happens (because part of the donor fluorescence is transferred to the acceptor instead of being emitted).
In the acceptor channel plot, the fluorescence intensity should increase linearly with the acceptor-labeled molecule concentration across the titrations series. If the serial dilution was performed with good precision, all data points should cluster around a straight line, as in this example.
The FRET channel plot quickly tells if the data contains useful signal: the titration and acceptor_only experiments should have visible differences in fluorescence intensity at some point in the titration series. If their data points perfectly overlap, it means the data doesn't contain any useful signal.
Automatic processing of any number of data files can be achieved using the pipe
operator %>%
from the magrittr
package, and the three functions
fret_format_data()
, fret_average_replicates()
and fret_correct_signal()
:
library(magrittr) library(rfret) fret_binding_data %>% format_data(data_type = "fret") %>% fret_average_replicates() %>% fret_correct_signal(output_directory = "./my_results")
The pipe operator allows to write this code in a natural way, one step after the other in the order of execution.
The function fret_average_replicates()
takes the output of fret_format_data()
and returns a dataset where the fluorescence intensity values have been averaged
over the technical replicates.
The function fret_correct_signal()
applies the correction described in the
following references:
It takes a reduced dataset from fret_average_replicates()
, or the output of
format_data()
in case there are no replicates, and outputs the corrected
FRET signal. Given a directory name, it will write out the corrected datasets to
CSV files. These output files will have the same names as the input files,
appended with _corrected
. These files can be used to plot the corrected data
using a different software, for example.
The last step involves the function fit_binding_model()
. It takes a corrected
dataset (output of fret_correct_signal()
) and a binding model. Currently available
binding models are: "hyperbolic"
, "hill"
and "quadratic"
. To use the
quadratic model, the function also needs the fixed concentration of probe molecule.
It returns an nls
object that can be further examined with standard functions
(like summary()
) or used as input for make_figure()
.
Fitting the example dataset with the quadratic model can be achieved as follows:
fret_binding_data %>% format_data(data_type = "fret") %>% fret_average_replicates() %>% fret_correct_signal() %>% fit_binding_model(binding_model = "quadratic", probe_concentration = 5)
Given a directory name, fit_binding_model()
will write its results to CSV files.
The function make_figure()
takes the output of fit_binding_model()
and returns
figures with a plot of the binding curve and a residual plot. Given a directory
name, it will write the figures in files named like the original input files.
Figure are written as PNG files by default, but the function can also write
PDF and SVG files.
fret_binding_data %>% format_data(data_type = "fret") %>% fret_average_replicates() %>% fret_correct_signal() %>% fit_binding_model(binding_model = "quadratic", probe_concentration = 5) %>% make_figure(probe_concentration = 5)
The entire data inspection, processing and analysis can be performed by a single script run from the directory containing raw data files in CSV format. Here is an example script:
# Load required packages library(magrittr) library(rfret) # List data files my_files <- list.files(path = ".", pattern = ".csv") # Generate raw data plots and save them in a directory called 'data_inspection' my_files %>% format_data(data_type = "fret", skip_lines = 4, metadata_json = "column_names.json") %>% inspect_raw_data(data_type = "fret", output_directory = "./data_inspection", plot_format = "png") # The following commands will: # 1. process raw data and save corrected data in CSV files in a # directory 'corrected_data' # 2. fit each dataset with a quadratic model equation, and save fit results # in CSV files in a directory 'fit_results' # 3. generate binding curve figures and save them as PNG files in a # directory 'final_figures' my_files %>% format_data(data_type = "fret", skip_lines = 4, metadata_json = "column_names.json") %>% fret_average_replicates() %>% fret_correct_signal(output_directory = "./corrected_data") %>% fit_binding_model(binding_model = "quadratic", probe_concentration = 5, output_directory = "./fit_results") %>% make_figure(probe_concentration = 5, output_directory = "./final_figures", plot_format = "png")
Used in combination with R Markdown, rfret
can make the process of
data analysis fully integrated with lab notebook record keeping.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.