9 Single experiment
9.1 Plate map
To dive a bit deeper into a single seahtrue
experiment, we will first generate an overview of what the experimental set-up was.
Let’s load the data first
Next, we make a theme that we can use for the heatmap
Then we make a nice default heatmap with the geom_tile
function.
The default ggplot colors are quite colorfull, but might hurt your eyes… If we want colors that are different than the default ggplot colors, and we want the legend to be nicely in order we need to add some additional code.
Another option would be to manually arrange the factors in a way that suits you best.
9.2 Background
In Seahorse experiments the corners of the plate are by default assigned as Background
wells, meaning that in these wells there is no sample but does have the same conditions and culture medium as your sample wells. Background wells need to be checked for outliers. This is not obvious from the Wave software interface, because the backgroung is by default substracted and users will never see the actual background data, unless they really select for it in the point-and-click software Wave. So let’s make some plots of the raw background O2 data.
We will now use the raw_data
table for plotting, and we assume you allready loaded the data file above in this session.
This is a nice plot of the background O2 readings. It does look weird, especailly beause there is one well H01
which has a comppletely different trend then the other wells. This might be suspected as a technical outlier. Possibly in this well there was not enough culture medium or the sensor was damaged. The lab details and observations should be aligned with the outlier calling to make sure to not erroneously flag a well as an outlier.
To make an even better visual representation of the background and to account for the different aspects how the background well data behaves we can plot only the first ticks of each measurement. We will also shift here now to the fluorescence readings of the Seahorse. Since the O2 is derived from fluorescence values in our experiments it would be good to really look at the most raw data that we get out of our experiment. The fluorescence is given as the parameter O2_em_corr
We have a plotting function that automates this.
We can use this function when we provide the right arguments. The argument option for the var
are: O2_em_corr
, pH_em_corr
and O2_mmHg
.
To calculate O2 from emission, Seahorse uses the Stern-Volmer equation. Find out (using google or chatGPT) what the stern-volmer equation is and write it in the form of a function. Use the arguments x
, KSV
, and F0
.
You can also use the Gerenscer et al. paper that describes the calculations. The method and algorithms described in this Analytical Chemistry paper from 2009 are still used today. Gerencser et al. Anal Chem 2009
Where x
is the emission (O2_em_corr
), KSV
is a constant, the stern-volmer konstant, and F0
is the emission at zero oxygen. The values of these two constants is are unique to the cartridge that you used during your experiment. Seahorse provides these numbers when updating your Wave software and matches them via a barcode read on the cartridge each run.
The KSV
and F0
are provided in the assay configuration sheet of the excel output. Seahtrue puts that information in the assay_info
table. You can access it using the pluck
function. In this case you have to use pluck
two times, first to get to the assay_info
and next to the KSV
or F0
Now use the two constants KSV
and F0
, and the function stern_volmer
to calculate the O2
from O2_em_corr
. Also use select(well, measurement, tick, O2_mmHg, O2)
to compare the O2
with the O2_mmHg
in the output.
Plot the O2
background values that you just calculated using the plot_raw_BKGD
function. Compare the plot to when plotting the O2_mmHg
that was derived from the Seahorse output xlsx.
Apparently the O2_mmHg
is different from our own calculated O2
concentrations. When looking at the O2_mmHg
background plot it looks like that these O2 values are also corrected for a background. Let’s see if that is indeed the case.
Seahorse Wave substracts the mean background from all samples. So the mean O2_mmHg
of the “Background
group is substracted from all samples wells (and background wells apparently). We can also do that with our seahtrue
data. We should take care of what we need to summarize
here, each tick
is a unique measurement in the raw_data
, do let’s take tick
as the .by
parameter
Now we need to substract the background O2 from all other wells and the backgrounds wells themselves.
The way this is done in the Seahorse algorithm is to take into account the ambient O2 levels. Basically what Seahorse calculates is the following:
Now compare the O2_corrected
with the original O2_mmHg
. Do this in two ways. 1) make a ggplot with the O2_corrected
on x-axis and O2_mmHg
on the y-axis. and 2) use the plot_raw_BKGD
function with O2_corrected
and compare with the output from the O2_mmHg
plot_raw_BKGD
plot
Although the values are not identical, they are pretty close. Indicating that the O2_mmHg background data is likely also corrected for background in this dataset.
9.3 Low signals
Sometimes we don’t have much sample. In most cases the sample is cells, and with low cell number the O2 consumption and extracellular acidification can be low. Seahorse defines an pretty arbitrary cut-off for basal respiration at 20 pmol/min. Below this value OCR becomes less reliable.
In the loaded experiment seahtrue_output_donor_A
, we have a group labeled with 50.000
. In these wells we only have 50.000 cells in each well, which makes its signal difficult to detect.
Please notice that the OCR signal for the 50.000
group is definitely below 20 pmol/min.
What if we want to investigate in more detail how our signals are for our samples with this low respiration?
We can make use of the raw_data
again and plot the background
O2 signal with the sample
O2 signal in one plot. Since in the previous section we saw that O2 signals for the background wells were also corrected for background (?!), we will work with our own calculated O2 levels using the stern_volmer
function we wrote in the previous section.
Also, we will use quite a big plotting function for this. It offers some flexibility on whether we want to plot means and/or scale the data. Also we can select specific wells and which measurements.
Let’s explore this huge function (with not so tidy coding in it….), by using it:
You can see in this plot that background O2 levels rise in each measurment. This drift is consistently seen in all instruments and experimental condtions. The upward drift in O2, is also why OCRs for background wells are often negative in your Seahorse software Wave graphs (when you point-and-click to have the background not substracted). The explanation that Gerenscer et al. gave for the drift was that either 1) temperature is not stable during a measurement and the fluorescent sensors are temperature sensitive or 2) that O2 levels in the microchamber that is formed when probe is at its measuring position is entering from the plastic or culture medium above. Both reasons are debatable I think.
Although the O2 levels of backgrounds increase, it can be seen that the O2 levels of well D02
increase less. Meaning that there oxygen consumption is higher than the background.
Change the inputs for the plot_raw_whichGroup_dots
(in a meaningful way), to plot the 1) O2_em_corr
, 2) plot another well D04
(please note that you also have change the group name because it is from the 100.000
group)
9.4 Plotting basal and maximal respiration
Pluck the injection_info
table from the seahtrue_output_donor_A
dataset to see what how the injections were defined in the experimental set-up before running the seahorse.
This is not a typical mito-stress test experiment, where we inject oligomycin, FCCP and antimycinA/rotenone sequentially. Instead we inject only FCCP and antimycinA/rotenone.
To get the maximal and basal respiration out of the ocr rate table, we need to do some calculations. We first make some assumptions and defintions:
We call each interval between two injections or between start and an injection or between an injection and the end a
phase
Each phase has a unique name that is named after the injection that was last. The first phase after the start is called
init_ocr
and we also typically have the phasesom_ocr
,fccp_ocr
andamrot_ocr
. Phases are marked with either_ocr
or_ecar
, because these are distinct parameters.To calculate respiration parameters, like basal respiration (= basal_ocr), we define the following:
- basal_ocr = init_ocr - amrot_ocr.
- max_ocr = fccp_ocr - amrot_ocr
- spare_ocr = fccp_ocr - init_ocr
- proton_leak = om_ocr = amrot_ocr
- atp_linked = init_ocr - om_ocr
We also use indices to have relative parameters:
- spare_ocr_index = (spare_ocr / basal_ocr)*100
- basal_ocr_index = (basal_ocr / max_ocr)*100
- leak_index = (proton_leak / basal_ocr)*100
- coupling_index = (atp_linked / basal_ocr)*100) %>%
Another important assumption is that we are not using average values to represent each phase, but intead we use a specific measurement. The reason for this is that we assume that for all phases, except FCCP, three measurements are needed in time to get to steady-state. For FCCP injection, we assume that it reaches steady-state fast, or at least its maximal ocr, so we take the first measurement after injection as the measurement representing the FCCP phase.
Let’s now put that into R code. We call the type of experiment we did in this dataset a maximal capacity
(maxcap
) test.
We also injected monensin, which can maximize ECAR, but we don’t need it for OCR calculations.
Now for each well we have the parameters related to the phases that we defined in the parameter set.
Next we want to calculate the respiration parameters and indices.
With this data we can plot our typical basal and maximal bar/scatter plots that we see in our lovely papers, presentations and theses.
The plot above shows maximal ocr
. Now make your own plot with 1) basal_ocr
and 2) all groups except background. Make sure to order the group legend tidyly and have reable x-axis labels.