FM Figures about RNAseq Analaysis - Rachelle
Gene expression along the genome
#Set the "RNA_seq_data" directory as working directory.
setwd("~/Library/CloudStorage/OneDrive-UniversitéParis-Saclay/Fundamental Microbiology (2026-2027)/Functional Genomics/RNA_seq-20261022") #Replace by your path
RNA<-read.table("tables/MP48vsMP24.complete.txt", header=T) #We read the table
summary(RNA) #We have an quick overview of the content of this table## Id MP24a MP24b MP48a
## Length :7534 Min. : 0 Min. : 0 Min. : 0.0
## N.unique :7534 1st Qu.: 44 1st Qu.: 37 1st Qu.: 44.2
## N.blank : 0 Median : 290 Median : 242 Median : 211.0
## Min.nchar: 18 Mean : 3520 Mean : 3101 Mean : 2536.7
## Max.nchar: 21 3rd Qu.: 1534 3rd Qu.: 1343 3rd Qu.: 984.0
## Max. :3026484 Max. :3032883 Max. :3345901.0
##
## MP48b Ycongo24a Ycongo24b Y24a
## Min. : 0 Min. : 0.0 Min. : 0.0 Min. : 0
## 1st Qu.: 48 1st Qu.: 24.0 1st Qu.: 18.0 1st Qu.: 26
## Median : 235 Median : 159.5 Median : 123.0 Median : 187
## Mean : 2573 Mean : 2710.6 Mean : 1683.2 Mean : 2524
## 3rd Qu.: 1031 3rd Qu.: 851.8 3rd Qu.: 648.8 3rd Qu.: 1097
## Max. :5619211 Max. :6811646.0 Max. :3655746.0 Max. :3106591
##
## Y24b Y48a Y48b norm.MP24a
## Min. : 0.0 Min. : 0.0 Min. : 0 Min. : 0
## 1st Qu.: 36.0 1st Qu.: 37.0 1st Qu.: 54 1st Qu.: 29
## Median : 239.5 Median : 175.0 Median : 265 Median : 193
## Mean : 2474.0 Mean : 1608.3 Mean : 2233 Mean : 2340
## 3rd Qu.: 1262.0 3rd Qu.: 747.8 3rd Qu.: 1106 3rd Qu.: 1020
## Max. :2470345.0 Max. :2315818.0 Max. :3463663 Max. :2012191
##
## norm.MP24b norm.MP48a norm.MP48b norm.Ycongo24a
## Min. : 0 Min. : 0.0 Min. : 0 Min. : 0.0
## 1st Qu.: 29 1st Qu.: 47.2 1st Qu.: 50 1st Qu.: 29.0
## Median : 191 Median : 226.0 Median : 245 Median : 195.5
## Mean : 2447 Mean : 2721.9 Mean : 2681 Mean : 3321.9
## 3rd Qu.: 1060 3rd Qu.: 1056.0 3rd Qu.: 1074 3rd Qu.: 1043.8
## Max. :2393442 Max. :3590152.0 Max. :5855550 Max. :8347824.0
##
## norm.Ycongo24b norm.Y24a norm.Y24b norm.Y48a
## Min. : 0 Min. : 0 Min. : 0.0 Min. : 0.0
## 1st Qu.: 28 1st Qu.: 27 1st Qu.: 29.0 1st Qu.: 49.0
## Median : 194 Median : 194 Median : 195.5 Median : 232.0
## Mean : 2656 Mean : 2621 Mean : 2019.9 Mean : 2128.2
## 3rd Qu.: 1024 3rd Qu.: 1139 3rd Qu.: 1030.0 3rd Qu.: 989.5
## Max. :5767543 Max. :3225987 Max. :2016963.0 Max. :3064405.0
##
## norm.Y48b baseMean MP24 MP48
## Min. : 0.0 Min. : 0.0 Min. : 0 Min. : 0
## 1st Qu.: 49.0 1st Qu.: 60.1 1st Qu.: 30 1st Qu.: 50
## Median : 239.0 Median : 313.5 Median : 196 Median : 240
## Mean : 2017.6 Mean : 2495.5 Mean : 2394 Mean : 2702
## 3rd Qu.: 998.8 3rd Qu.: 1285.0 3rd Qu.: 1060 3rd Qu.: 1076
## Max. :3129447.0 Max. :3940350.5 Max. :2202816 Max. :4722851
##
## Ycongo24 Y24 Y48 FoldChange
## Min. : 0.0 Min. : 0 Min. : 0.0 Min. : 0.005
## 1st Qu.: 30.0 1st Qu.: 29 1st Qu.: 50.0 1st Qu.: 0.477
## Median : 197.5 Median : 198 Median : 236.0 Median : 1.013
## Mean : 2988.7 Mean : 2321 Mean : 2072.9 Mean : 12.858
## 3rd Qu.: 1048.0 3rd Qu.: 1094 3rd Qu.: 993.5 3rd Qu.: 2.654
## Max. :7057684.0 Max. :2621475 Max. :3096926.0 Max. :3130.961
## NAs :213
## log2FoldChange stat pvalue padj
## Min. :-7.6040 Min. :-22.5880 Min. :0.000000 Min. :0.000000
## 1st Qu.:-1.0690 1st Qu.: -3.1570 1st Qu.:0.000000 1st Qu.:0.000000
## Median : 0.0190 Median : 0.0420 Median :0.001212 Median :0.002424
## Mean : 0.3439 Mean : 0.6696 Mean :0.143914 Mean :0.162861
## 3rd Qu.: 1.4080 3rd Qu.: 3.3740 3rd Qu.:0.158841 3rd Qu.:0.211778
## Max. :11.6120 Max. : 40.6180 Max. :1.000000 Max. :1.000000
## NAs :213 NAs :213 NAs :213 NAs :213
## dispGeneEst dispFit dispMAP dispersion
## Min. : 0.00000 Min. : 0.0474 Min. : 0.0147 Min. : 0.0147
## 1st Qu.: 0.00000 1st Qu.: 0.0492 1st Qu.: 0.0335 1st Qu.: 0.0335
## Median : 0.02100 Median : 0.0544 Median : 0.0498 Median : 0.0498
## Mean : 0.05693 Mean : 0.1667 Mean : 0.1394 Mean : 0.1443
## 3rd Qu.: 0.05460 3rd Qu.: 0.0806 3rd Qu.: 0.0858 3rd Qu.: 0.0858
## Max. :10.00000 Max. :35.7365 Max. :10.0000 Max. :10.0000
## NAs :213 NAs :213 NAs :213 NAs :213
## betaConv maxCooks
## Mode:logical Mode:logical
## TRUE:7321 NAs :7534
## NAs :213
##
##
##
##
#We need to annotate the file to indicate the replicon and start-stop positions of each
#Set the "Counts" directory as working directory, because we need also this information that comes from another table
ANNOT<-read.table("Counts/WTMP5_24_1_counts_S.txt", header=T)
#We conserve only the 6 first columns
ANNOT<-ANNOT[,-c(7)]
#We rename the column (so that the "Id" will be present in the annotation file as well as our RNA file, that's the common column)
colnames(ANNOT)<-c("Id", "Replicon", "START","End", "Strand", "Length")
#We fuse the tables:
RNA<-merge(RNA, ANNOT, by="Id", all.x=T)
#If you want you can save this table with this command line
write.csv2(RNA, "RNA.csv", row.names = F)
# We will analyzed only the chromosomal genes (without genes from the plasmid). To do this, we can use the "subset" function like this:
RNA_CHR<-subset(RNA, RNA$Replicon=="NZ_CP012382.1")
#Order RNA_CHR by the start position, first one the lowest, latest the
RNA_CHR$START<-as.numeric(RNA_CHR$START)
RNA_CHR<-RNA_CHR[order(RNA_CHR$START),]#We order the rows depending on the start value
#If you want you can save this table with this command line
write.csv2(RNA_CHR, "RNA_CHR.csv", row.names = F)
# Calculation of the mean sense transcription in a window of 81 genes:
RNA_CHR$RNAseq_24h_WINDOW<-"NA" # This way, we create a new variable in which we will put the information concerning the mean persistence in a window centered at each gene position
RNA_CHR$RNAseq_48h_WINDOW<-"NA"
a<-20 #size of the window, before and after each gene position (changed to 20)
b<-a+1 #the calculation will start at this position in the genome of interest (this information will change automatically of we change the size of the window)
l<-length(RNA_CHR$Id)-a #last position analyzed in the genome (=> number of genes minus the half size of the windows, given that the windows are centered at each gene position)
for (i in b:l){
j = i - a
k = i + a
RNA_CHR$RNAseq_24h_WINDOW[i]<-mean(RNA_CHR$MP24[j:k], na.rm=TRUE)
RNA_CHR$RNAseq_48h_WINDOW[i]<-mean(RNA_CHR$MP48[j:k], na.rm=TRUE)
}
#I always convert the outcome of a loop as numeric values (since sometimes you can have troubles with values that could not be calculated, etc...)
RNA_CHR$RNAseq_24h_WINDOW<-as.numeric(RNA_CHR$RNAseq_24h_WINDOW)
RNA_CHR$RNAseq_48h_WINDOW<-as.numeric(RNA_CHR$RNAseq_48h_WINDOW)
# Plot #1 - sense transcription along the chromosome in exponential phase (type = "l" is indicated to represent a line instead of dots):
plot(RNA_CHR$START, RNA_CHR$RNAseq_24h_WINDOW, type = "l", xlab ="Position along the chromosome (bp)", ylab = "Mean transcription (in the window)")# Plot #2 - sense transcription along the chromosome in stationary phase:
plot(RNA_CHR$START, RNA_CHR$RNAseq_48h_WINDOW, type = "l", xlab ="Position along the chromosome (bp)", ylab = "Mean transcription (in the window)")# Plot #2 - sense transcription along the chromosome in stationary phase:
plot(RNA_CHR$START, RNA_CHR$RNAseq_48h_WINDOW, type = "l", xlab ="Position along the chromosome (bp)", ylab = "Mean transcription (in the window)")
# Plot #3 - overlay:
plot(RNA_CHR$START, RNA_CHR$RNAseq_24h_WINDOW, type = "l", xlab ="Position along the chromosome (bp)", ylab = "Mean transcription (in the window)")
lines(RNA_CHR$START, RNA_CHR$RNAseq_48h_WINDOW, col = "pink")
# We can also add information concerning the position of the origin of replication (in red), of the ribosomal RNA encoding operons (in blue) and of the TIR (terminal inverted repeats, in grey), like this:
abline(v=c(196959, 4023406, 1473191, 1920301, 3247066, 3784403, 4485769, 5802474), col=c("grey","red", "blue","blue","blue","blue","blue","blue"), lty=2, lwd=1)# Let's start by calculating the log2 values and redo like above. I have to be carefull with the 0... (that will induce a bug with the log2 function ;-))
RNA_CHR$RNAseq_24h_log2<-"NA"
RNA_CHR$RNAseq_48h_log2<-"NA"
#To avoid the "zero problem", we add "1" to the number of reads in each condition
RNA_CHR$RNAseq_24h_log2<-log2(RNA_CHR$MP24+1)
RNA_CHR$RNAseq_48h_log2<-log2(RNA_CHR$MP48+1)
RNA_CHR$RNAseq_24h_WINDOW_log2<-"NA"
RNA_CHR$RNAseq_48h_WINDOW_log2<-"NA"
a<-20
b<-a+1
l<-length(RNA_CHR$Id)-a
for (i in b:l){
j = i - a
k = i + a
RNA_CHR$RNAseq_24h_WINDOW_log2[i]<-mean(RNA_CHR$RNAseq_24h_log2[j:k], na.rm=TRUE)
RNA_CHR$RNAseq_48h_WINDOW_log2[i]<-mean(RNA_CHR$RNAseq_48h_log2[j:k], na.rm=TRUE)
}
RNA_CHR$RNAseq_24h_WINDOW_log2<-as.numeric(RNA_CHR$RNAseq_24h_WINDOW_log2)
RNA_CHR$RNAseq_48h_WINDOW_log2<-as.numeric(RNA_CHR$RNAseq_48h_WINDOW_log2)
plot(RNA_CHR$START, RNA_CHR$RNAseq_24h_WINDOW_log2, type = "l", xlab ="Position along the chromosome (bp)", ylab = "Mean transcription (in the window, log2)")
lines(RNA_CHR$START, RNA_CHR$RNAseq_48h_WINDOW_log2, col = "purple")
abline(v=c(196959, 4023406, 1473191, 1920301, 3247066, 3784403, 4485769, 5802474), col=c("grey","red", "blue","blue","blue","blue","blue","blue"), lty=2, lwd=1)
Analyze the figures. What biological phenomena do you observe? What is
the interest of representing logged values? R/ we can observe in the
last figure that Streptomyces has consistent high expression of genes
located in the central core of the genome, where the origin of
replication (Ori) is located. This shows active replication and
transcription. We also observe high expression of ribosomal genes. And
then at the peripheral regions the gene expression decrease due to the
presence of accesory gene clusters. The logged values help to visualize
the data in a clearer way.
Visualization of the data using heatmap representation
We will work with the same RNA_CHR table that we have previously generated. First, we will normalize the mean DESeq2 normalized counts on gene size. We will obtain normRPK (normalized reads per kb). Then we will perform a heatmap representation of the data using the function heatmap(). If you indicate, ‘?heatmap’ in the terminal you can have detailed information about this function. If you indicate just ‘heatmap’, you will have its code.
#Read the RNA_CHR tabvle that you have previously generated
RNA_CHR<-read.csv2("RNA_CHR.csv")
# First create new columns containing the normRPK value
RNA_CHR$RPK_MP24<-RNA_CHR$MP24/RNA_CHR$Length*1000
RNA_CHR$RPK_MP48<-RNA_CHR$MP48/RNA_CHR$Length*1000
RNA_CHR$RPK_Y24<-RNA_CHR$Y24/RNA_CHR$Length*1000
RNA_CHR$RPK_Ycongo24<-RNA_CHR$Ycongo24/RNA_CHR$Length*1000
RNA_CHR$RPK_Y48<-RNA_CHR$Y48/RNA_CHR$Length*1000
# Compile these five new columns into a matrix
mydata <- RNA_CHR[, 44:48]
mymatrix <- as.matrix(mydata)
# Scale the data by row (genes) for better visualization
scaled_data <- scale(mydata, center = TRUE, scale = TRUE)
# Create the heatmap with clustering only for columns (conditions)
heatmap(scaled_data,
Rowv = NA, # No clustering for rows (genes)
Colv = TRUE, # Cluster columns (conditions)
col = colorRampPalette(c("green", "white", "red"))(100), # Use diverging colors
margins = c(10, 10),
main = "RNA-seq Heatmap (Column Clustering, Row Scaled)",
cexCol = 1.2, # Adjust column label size
labRow = NA) # Remove row labels
# Calculate the min, mean, and max of the scaled data
scaled_min <- round(min(scaled_data, na.rm = TRUE), digits = 2)
scaled_mean <- round(mean(scaled_data, na.rm = TRUE), digits = 2)
scaled_max <- round(max(scaled_data, na.rm = TRUE), digits = 2)
# Add the legend with the scaled data range
legend("topright",
legend = c(scaled_min, scaled_mean, scaled_max), # Use scaled data range
fill = colorRampPalette(c("green", "white", "red"))(100)[c(1, 50, 100)], # Match heatmap colors
title = "Expression (normalized reads per kb)",
bty = "n")
In this heatmap we can observe that there is a marked global expression
shift as Streptomyces transition from 24h (exponential phase) to 48h
(stationary phase), turning many genes from green (low) to red (high).
And adding the congo Red at 24h induces a transcriptomic change that
resembles late-stage (48h) stationary growth rather than normal 24h
exponential growth.