This notebook uses the rOMERO-gateway and EBImage to process an Image associated to the paper 'Timing of gene expression in a cell-fate decision system'.
The Image "Pos22" is taken from the dataset idr0040-aymoz-singlecell/experimentA/YDA306_AGA1y_PRM1r_Mating. It is a timelapse Image with 42 timepoints separated by 5 minutes. This Image is used to fit a model for the growth of the yeast cells. The notebook does not replicate any of the analysis of the above mentioned paper.
library(romero.gateway)
library(EBImage)
Loading required package: rJava Loading required package: jpeg Loading required package: httr *** Welcome to rOMERO 0.4.8 *** Attaching package: ‘EBImage’ The following object is masked from ‘package:romero.gateway’: Image
server <- OMEROServer(host = 'wss://idr.openmicroscopy.org/omero-ws', port = 443L, username='public', password='public')
server <- connect(server)
paste('Successfully logged in as', server@user$getUserName())
# YDA306_AGA1y_PRM1r_Mating - Pos22
imageId <- 3491334
image <- loadObject(server, "ImageData", imageId)
Found more than one class "Image" in cache; using the first, from namespace 'romero.gateway' Also defined by ‘EBImage’
Just set some information about the image:
tmax <- 42 # number of timepoints
tInMinutes <- 5 # separation between timepoints in minutes
Get the raw pixel values of the image. We use only the second (CFP labelled) channel, because that nicely shows the single, separated cells. Use an image from the middle of the timelapse, which hopefully provides a representative image of the whole timelapse.
t <- as.integer(tmax / 2)
pixels <- getPixelValues(image, 1, t, 2)
ebi <- EBImage::Image(data = pixels, colormode = 'Grayscale')
img <- normalize(ebi)
EBImage::display(img)
Now threshold the image in order to separate the cells from the background and from each other. Play around a bit with the parameters to get a good result.
threshImg <- thresh(img, w=20, h=20, offset=0.05)
threshImg <- medianFilter(threshImg, 3)
threshImg <- fillHull(threshImg)
threshImg <- bwlabel(threshImg)
EBImage::display(colorLabels(threshImg))
Count the cells on that image:
count <- range(threshImg)
count[2]
Wrap it all up in a function:
countCells <- function (t) {
pixels <- getPixelValues(image, 1, t, 2)
ebi <- EBImage::Image(data = pixels, colormode = 'Grayscale')
img <- normalize(ebi)
threshImg <- thresh(img, w=20, h=20, offset=0.05)
threshImg <- medianFilter(threshImg, 3)
threshImg <- fillHull(threshImg)
threshImg <- bwlabel(threshImg)
count <- range(threshImg)
as.integer(count[2])
}
Iterate through the timepoints and store the cell count in a dataframe (warning: this can take up to 20 min, use 'seq(1,tmax,7)' to only analyse every seventh image for a quick run):
timepoints <- (1:tmax) # analyze every time point
# timepoints <- seq(1,tmax,7) # only use every seventh time point (faster)
df <- data.frame(TimePoint=timepoints)
df$CellCount <- sapply(df$TimePoint, countCells)
df$TimePoint <- sapply(df$TimePoint, function(x) x * tInMinutes)
df
Plot the cell counts:
plot(df$TimePoint, df$CellCount, ylab = "Number of cells", xlab = "Time (in min)")
Fit an exponential model:
model <- lm(log(df$CellCount)~ df$TimePoint)
print(summary(model))
Call: lm(formula = log(df$CellCount) ~ df$TimePoint) Residuals: Min 1Q Median 3Q Max -0.07017 -0.03106 -0.01024 0.02787 0.08196 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) 4.7270953 0.0128543 367.7 <2e-16 *** df$TimePoint 0.0037388 0.0001042 35.9 <2e-16 *** --- Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 Residual standard error: 0.04091 on 40 degrees of freedom Multiple R-squared: 0.9699, Adjusted R-squared: 0.9691 F-statistic: 1288 on 1 and 40 DF, p-value: < 2.2e-16
Very good fit: p-Values < 2e-16, and 97% of the variation is explained by the model!
Lets show that on the plot
plotTime <- as.list(df[,1])
predCounts <- exp(predict(model,plotTime))
plot(df$TimePoint, df$CellCount, ylab = "Number of cells", xlab = "Time (in min)")
lines(plotTime, predCounts,lwd=2, col = "red")
Finally disconnect from the server again:
disconnect(server)
Copyright (c) 2018-2021, University of Dundee All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.