Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
victor-gourain authored Sep 16, 2021
0 parents commit 78fac5c
Show file tree
Hide file tree
Showing 14 changed files with 1,252 additions and 0 deletions.
590 changes: 590 additions & 0 deletions code/R_scripts/Annotation_Rfunctions.R

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions code/R_scripts/Cambuli_DifferentialExpression.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
###
suppressMessages(library('DESeq2'))
#
ES_E14<-read.csv("ES_E14.count",header=FALSE,sep="\t")
ES_E14<-ES_E14[grep('ENSMUS',ES_E14$V1),]
colnames(ES_E14)<-c('ensGeneID','ES_E14')
##
ES_J1<-read.csv("ES_J1.count",header=FALSE,sep="\t")
ES_J1<-ES_J1[grep('ENSMUS',ES_J1$V1),]
colnames(ES_J1)<-c('ensGeneID','ES_J1')
##
iCDX2_ES_MEF<-read.csv("iCdx2_ES_MEF.count",header=FALSE,sep="\t")
iCDX2_ES_MEF<-iCDX2_ES_MEF[grep('ENSMUS',iCDX2_ES_MEF$V1),]
colnames(iCDX2_ES_MEF)<-c('ensGeneID','iCDX2_ES_MEF')
##
iCDX2_ES_TC<-read.csv("iCdx2_ES_TC_plastic.count",header=FALSE,sep="\t")
iCDX2_ES_TC<-iCDX2_ES_TC[grep('ENSMUS',iCDX2_ES_TC$V1),]
colnames(iCDX2_ES_TC)<-c('ensGeneID','iCDX2_ES_TC')
##
TS_EGFP<-read.csv("TS_EGFP.count",header=FALSE,sep="\t")
TS_EGFP<-TS_EGFP[grep('ENSMUS',TS_EGFP$V1),]
colnames(TS_EGFP)<-c('ensGeneID','TS_EGFP')
##
TS_Rs26<-read.csv("TS_Rs26.count",header=FALSE,sep="\t")
TS_Rs26<-TS_Rs26[grep('ENSMUS',TS_Rs26$V1),]
colnames(TS_Rs26)<-c('ensGeneID','TS_Rs26')
##iCDX2-MEF vs ES-E14
ESCdx2MEF_cambuli.data<-merge(ES_E14,iCDX2_ES_MEF,by='ensGeneID')
rownames(ESCdx2MEF_cambuli.data)<-ESCdx2MEF_cambuli.data$ensGeneID
ESCdx2MEF_cambuli.data<-ESCdx2MEF_cambuli.data[,-1]
ESCdx2MEF_info.df<-data.frame('condition'=c('ES_E14','iCDX2_ES_MEF'),'type'=c('SR','SR'))
rownames(ESCdx2MEF_info.df)<-colnames(ESCdx2MEF_cambuli.data)[c(1,2)]
ESCdx2MEF_dds<-DESeqDataSetFromMatrix(countData=ESCdx2MEF_cambuli.data,colData=ESCdx2MEF_info.df,design = ~ condition)
ESCdx2MEF_rld<-rlogTransformation(ESCdx2MEF_dds)
ESCdx2MEF_res<-data.frame(assay(ESCdx2MEF_rld),avgLogExpr=(assay(ESCdx2MEF_rld)[,2]+assay(ESCdx2MEF_rld)[,1])/2,rLogFC=assay(ESCdx2MEF_rld)[,2]-assay(ESCdx2MEF_rld)[,1])
ESCdx2MEF_res<-ESCdx2MEF_res[order(ESCdx2MEF_res$rLogFC,decreasing=TRUE),]
colnames(ESCdx2MEF_res)<-paste('ESCdx2MEF',colnames(ESCdx2MEF_res),sep="_")
#iCDX2-TC vs ES-J1
ESCdx2TC_cambuli.data<-merge(ES_J1,iCDX2_ES_TC,by='ensGeneID')
rownames(ESCdx2TC_cambuli.data)<-ESCdx2TC_cambuli.data$ensGeneID
ESCdx2TC_cambuli.data<-ESCdx2TC_cambuli.data[,-1]
ESCdx2TC_info.df<-data.frame('condition'=c('ES_J1','iCDX2_ES_TC'),'type'=c('SR','SR'))
rownames(ESCdx2TC_info.df)<-colnames(ESCdx2TC_cambuli.data)[c(1,2)]
ESCdx2TC_dds<-DESeqDataSetFromMatrix(countData=ESCdx2TC_cambuli.data,colData=ESCdx2TC_info.df,design = ~ condition)
ESCdx2TC_rld<-rlogTransformation(ESCdx2TC_dds)
ESCdx2TC_res<-data.frame(assay(ESCdx2TC_rld),avgLogExpr=(assay(ESCdx2TC_rld)[,2]+assay(ESCdx2TC_rld)[,1])/2,rLogFC=assay(ESCdx2TC_rld)[,2]-assay(ESCdx2TC_rld)[,1])
ESCdx2TC_res<-ESCdx2TC_res[order(ESCdx2TC_res$rLogFC,decreasing=TRUE),]
colnames(ESCdx2TC_res)<-paste('ESCdx2TC',colnames(ESCdx2TC_res),sep="_")
#TS-eGFP vs ES-J1
TS_cambuli.data<-merge(TS_EGFP,ES_J1,by='ensGeneID')
rownames(TS_cambuli.data)<-TS_cambuli.data$ensGeneID
TS_cambuli.data<-TS_cambuli.data[,-1]
TS_info.df<-data.frame('condition'=c('ES_J1','TS_EGFP'),'type'=c('SR','SR'))
rownames(TS_info.df)<-colnames(TS_cambuli.data)[c(1,2)]
TS_dds<-DESeqDataSetFromMatrix(countData=TS_cambuli.data,colData=TS_info.df,design = ~ condition)
TS_rld<-rlogTransformation(TS_dds)
TS_res<-data.frame(assay(TS_rld),avgLogExpr=(assay(TS_rld)[,2]+assay(TS_rld)[,1])/2,rLogFC=assay(TS_rld)[,2]-assay(TS_rld)[,1])
TS_res<-TS_res[order(TS_res$rLogFC,decreasing=TRUE),]
colnames(TS_res)<-paste('TS',colnames(TS_res),sep="_")
cambuli.res<-merge(ESCdx2MEF_res,ESCdx2TC_res,by="row.names")
rownames(cambuli.res)<-cambuli.res$Row.names
cambuli.res<-cambuli.res[,-1]
cambuli.res<-merge(cambuli.res,TS_res,by="row.names")
source("Annotation_Rfunctions.R")
cambuli.res.anno<-AddAnnotation.FUN(df=cambuli.res,byEnsemblID=TRUE,EnsemblIDc=1,martID="mmusculus_gene_ensembl")
cambuli.res.anno.su<-subset(cambuli.res.anno,
cambuli.res.anno$ESCdx2MEF_ES_E14 >= 0 &
cambuli.res.anno$ESCdx2MEF_iCDX2_ES_MEF >= 0 &
cambuli.res.anno$ESCdx2TC_ES_J1 >= 0 &
cambuli.res.anno$ESCdx2TC_iCDX2_ES_TC >= 0 &
cambuli.res.anno$TS_TS_EGFP >= 0 &
cambuli.res.anno$TS_ES_J1 >= 0
)
95 changes: 95 additions & 0 deletions code/R_scripts/Generic_DifferentialExpression.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env Rscript
####################################
#############PARAMETERS#############
####################################
annotation.file=""#two columns (Ensembl ID and gene symbol) tsv file
wd=""#with count files from HTseq
conditions=c("")
comparison=c("condition","","")
prefix=''
Number.Samples=
Number.Conditions=
Qt.CutOff=
minReplicates=
pAdjustMethod=""#e.g. fdr, BH, ...
GLM=#TRUE or FALSE
####################################
####################################
suppressMessages(library('DESeq2'))
suppressMessages(library("gplots"))
suppressMessages(library("ggplot2"))
AddGeneName<-function(l){
a<-gDE$symbol[gDE$id %in% l[1]];
if(length(a) == 0){
return("NA")
}else{
(return(as.character(a[1])))
}
}
####################################
####################################
sampleTable<-as.data.frame(cbind('sampleName'=c(as.vector(sapply(as.vector(grep(".count",list.files(wd),value=TRUE)),function(x) unlist(strsplit(x,"[.]"))[1]))),'fileName'=grep(".count",list.files(wd),value=TRUE),'condition'=conditions))
print(sampleTable)
ddsHTSeq<-DESeqDataSetFromHTSeqCount(sampleTable=sampleTable,directory=wd,design = ~condition)
if(GLM == TRUE){
ddsHTSeq<-DESeq(ddsHTSeq)
}else{
cat("No GLM\n")
ddsHTSeq<-DESeq(ddsHTSeq,betaPrior=FALSE)
}
cat("Size factors\n")
print(sizeFactors(ddsHTSeq))
normCount<-counts(ddsHTSeq,normalized=TRUE)
colnames(normCount)<-paste(colnames(normCount),'_nCOUNT',sep="")
rawCount<-counts(ddsHTSeq)
colnames(rawCount)<-paste(colnames(rawCount),'_rCOUNT',sep="")
vsd<-assay(varianceStabilizingTransformation(ddsHTSeq))
colnames(vsd)<-paste(colnames(vsd),'_vsd',sep="")
rld<-assay(rlog(ddsHTSeq))
colnames(rld)<-paste(colnames(rld),'_rld',sep="")
diff.exp<-results(ddsHTSeq,contrast=comparison,pAdjustMethod=pAdjustMethod,cooksCutoff=FALSE)
flag<-c()
if(minReplicates >= 3){
cat("Flaging outliers\n")
ddsHTSeq.outliers<-replaceOutliers(ddsHTSeq, minReplicates = minReplicates,cooksCutoff=qf(Qt.CutOff,Number.Conditions,Number.Samples-Number.Conditions))
flag<-as.data.frame(mcols(ddsHTSeq.outliers)$replace)
rownames(flag)<-rownames(normCount)
colnames(flag)<-'FLAG'
}else{
flag<-as.data.frame(rep(NA,times=nrow(diff.exp)))
rownames(flag)<-rownames(normCount)
colnames(flag)<-'FLAG'
}
merged.df<-merge(diff.exp,normCount,by="row.names",all=TRUE)
rownames(merged.df)<-merged.df[,1]
merged.df<-merged.df[,-1]
merged.df<-merge(merged.df,vsd,by="row.names",all=TRUE)
rownames(merged.df)<-merged.df[,1]
merged.df<-merged.df[,-1]
merged.df<-merge(merged.df,rld,by="row.names",all=TRUE)
rownames(merged.df)<-merged.df[,1]
merged.df<-merged.df[,-1]
merged.df<-merge(merged.df,rawCount,by="row.names",all=TRUE)
rownames(merged.df)<-merged.df[,1]
merged.df<-merged.df[,-1]
merged.df<-merge(merged.df,flag,by="row.names",all=TRUE)
colnames(merged.df)[1]<-'GeneID'
if(file.exists(annotation.file)){
cat("Adding Gene Names\n")
gDE<-read.csv(annotation.file,header=TRUE,sep="\t")
colnames(gDE)<-c('GeneID','symbol','name')
merged.df<-merge(merged.df,gDE[,c(1,2)],by="GeneID",all.x=TRUE)
#merged.df<-cbind(merged.df,apply(merged.df,1,function(l) AddGeneName(l)))
}
merged.df<-merged.df[order(merged.df$padj,decreasing=FALSE),]
cat("Significant DEG: ",nrow(subset(merged.df,merged.df$padj <= 0.05)),"\n")
write.table(merged.df,file=paste(wd,"/",prefix,"_All_MisRegulated_Genes.csv",sep=""),quote=FALSE,sep="\t",row.names=FALSE,col.names=TRUE)
dists<-dist(t(as.matrix(vsd)))
tm<-as.matrix(dists)
colnames(tm)<-sampleTable$sampleName
rownames(tm)<-sampleTable$sampleName
pdf(paste(wd,"/",prefix,"_Expression_Heatmap.pdf", sep = ""))
heatmap.2(tm,margins=c(15,15),trace="none",density.info="none")
dev.off()
cat("Done\n")
save.image(file=paste(wd, "/env.RData", sep = ""),safe=TRUE)
65 changes: 65 additions & 0 deletions code/R_scripts/Generic_Rfunctions.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
##R functions
####
##Find overlapp between genomic coordinates
####
suppressMessages(library('GenomicRanges'))
suppressMessages(library('IRanges'))
suppressMessages(library('GenomicFeatures'))
oCT=10
ByOverlap.FUN<-function(
gr.object=NA,
gr.annotation=NA,
st=NA
){
tmp.0<-as.data.frame(gr.annotation,row.names=NULL)
gr.df<-as.data.frame(gr.object)
gr.df<-cbind(gr.df,'id'=paste("tagid_",1:nrow(gr.df),sep=""))
annotation.df<-as.data.frame(gr.annotation)
annotation.df<-as.data.frame(findOverlaps(gr.object,gr.annotation,ignore.strand=st,type="any",select="arbitrary",minoverlap=oCT))
annotation.df<-cbind(annotation.df,'id'=paste("tagid_",1:nrow(annotation.df),sep=""))
tmp.1<-subset(tmp.0,rownames(tmp.0) %in% annotation.df[,1])
tmp.2<-cbind(rownames(tmp.1),tmp.1)
colnames(tmp.2)[1]<-colnames(annotation.df)[1]
M.0<-merge(annotation.df,tmp.2,by=colnames(annotation.df)[1],all.x=TRUE)
colnames(M.0)<-c('annoRoW',colnames(M.0)[2],paste('Annotation',colnames(M.0)[-c(1,2)],sep="_"))
M.1<-merge(gr.df,M.0[,-1],by='id',all.x=TRUE)
return(M.1[,-1])
}
##Annotate feature directly before genomic coordinates
precede.FUN<-function(
gr.object=NA,
gr.annotation=NA
){
tmp.0<-as.data.frame(gr.annotation,row.names=NULL)
gr.df<-as.data.frame(gr.object)
gr.df<-cbind(gr.df,'id'=paste("tagid_",1:nrow(gr.df),sep=""))
annotation.df<-as.data.frame(gr.annotation)
annotation.df<-as.data.frame(precede(gr.object,gr.annotation,ignore.strand=TRUE))
annotation.df<-cbind(annotation.df,'id'=paste("tagid_",1:nrow(annotation.df),sep=""))
tmp.1<-subset(tmp.0,rownames(tmp.0) %in% annotation.df[,1])
tmp.2<-cbind(rownames(tmp.1),tmp.1)
colnames(tmp.2)[1]<-colnames(annotation.df)[1]
M.0<-merge(annotation.df,tmp.2,by=colnames(annotation.df)[1],all.x=TRUE)
colnames(M.0)<-c('annoRoW',colnames(M.0)[2],paste('Annotation_following',colnames(M.0)[-c(1,2)],sep="_"))
M.1<-merge(gr.df,M.0[,-1],by='id',all.x=TRUE)
return(M.1)
}
##follow.FUN: to find the annotation feature righ after an intergenic query, MUST BE STRANDED!!!
follow.FUN<-function(
gr.object=NA,
gr.annotation=NA
){
tmp.0<-as.data.frame(gr.annotation,row.names=NULL)
gr.df<-as.data.frame(gr.object)
gr.df<-cbind(gr.df,'id'=paste("tagid_",1:nrow(gr.df),sep=""))
annotation.df<-as.data.frame(gr.annotation)
annotation.df<-as.data.frame(follow(gr.object,gr.annotation,ignore.strand=TRUE))
annotation.df<-cbind(annotation.df,'id'=paste("tagid_",1:nrow(annotation.df),sep=""))
tmp.1<-subset(tmp.0,rownames(tmp.0) %in% annotation.df[,1])
tmp.2<-cbind(rownames(tmp.1),tmp.1)
colnames(tmp.2)[1]<-colnames(annotation.df)[1]
M.0<-merge(annotation.df,tmp.2,by=colnames(annotation.df)[1],all.x=TRUE)
colnames(M.0)<-c('annoRoW',colnames(M.0)[2],paste('Annotation_preceding',colnames(M.0)[-c(1,2)],sep="_"))
M.1<-merge(gr.df,M.0[,-1],by='id',all.x=TRUE)
return(M.1)
}
85 changes: 85 additions & 0 deletions code/R_scripts/Rhee_DifferentialExpression.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
###
suppressMessages(library(DESeq2))
#
ES_cells<-read.csv("ES_cells.count",header=FALSE,sep="\t")
ES_cells<-ES_cells[grep('ENSMUS',ES_cells$V1),]
colnames(ES_cells)<-c('ensGeneID','ES')
OECdx2_ES<-read.csv("OECdx2_ES.count",header=FALSE,sep="\t")
OECdx2_ES<-OECdx2_ES[grep('ENSMUS',OECdx2_ES$V1),]
colnames(OECdx2_ES)<-c('ensGeneID','OECdx2')
TS_cells<-read.csv("TS_cells.count",header=FALSE,sep="\t")
TS_cells<-TS_cells[grep('ENSMUS',TS_cells$V1),]
colnames(TS_cells)<-c('ensGeneID','TS')
OECdx2_TS<-read.csv("OECdx2_TS.count",header=FALSE,sep="\t")
OECdx2_TS<-OECdx2_TS[grep('ENSMUS',OECdx2_TS$V1),]
colnames(OECdx2_TS)<-c('ensGeneID','OECdx2')
#ESCdx2 vs ES
ESCdx2_rhee.data<-merge(ES_cells,OECdx2_ES,by='ensGeneID')
rownames(ESCdx2_rhee.data)<-ESCdx2_rhee.data$ensGeneID
ESCdx2_rhee.data<-ESCdx2_rhee.data[,-1]
ESCdx2_info.df<-data.frame('condition'=c('ES','ESCdx2'),'type'=c('SR','SR'))
rownames(ESCdx2_info.df)<-colnames(ESCdx2_rhee.data)[c(1,2)]
ESCdx2_dds<-DESeqDataSetFromMatrix(countData=ESCdx2_rhee.data,colData=ESCdx2_info.df,design = ~ condition)
ESCdx2_rld<-rlogTransformation(ESCdx2_dds)
ESCdx2_res<-data.frame(assay(ESCdx2_rld),avgLogExpr=(assay(ESCdx2_rld)[,2]+assay(ESCdx2_rld)[,1])/2,rLogFC=assay(ESCdx2_rld)[,2]-assay(ESCdx2_rld)[,1])
ESCdx2_res<-ESCdx2_res[order(ESCdx2_res$rLogFC,decreasing=TRUE),]
colnames(ESCdx2_res)<-paste('ESCdx2',colnames(ESCdx2_res),sep="_")
#TSCdx2 vs ES
TSCdx2_rhee.data<-merge(ES_cells,OECdx2_TS,by='ensGeneID')
rownames(TSCdx2_rhee.data)<-TSCdx2_rhee.data$ensGeneID
TSCdx2_rhee.data<-TSCdx2_rhee.data[,-1]
TSCdx2_info.df<-data.frame('condition'=c('ES','TSCdx2'),'type'=c('SR','SR'))
rownames(TSCdx2_info.df)<-colnames(TSCdx2_rhee.data)[c(1,2)]
TSCdx2_dds<-DESeqDataSetFromMatrix(countData=TSCdx2_rhee.data,colData=TSCdx2_info.df,design = ~ condition)
TSCdx2_rld<-rlogTransformation(TSCdx2_dds)
TSCdx2_res<-data.frame(assay(TSCdx2_rld),avgLogExpr=(assay(TSCdx2_rld)[,2]+assay(TSCdx2_rld)[,1])/2,rLogFC=assay(TSCdx2_rld)[,2]-assay(TSCdx2_rld)[,1])
TSCdx2_res<-TSCdx2_res[order(TSCdx2_res$rLogFC,decreasing=TRUE),]
colnames(TSCdx2_res)<-paste('TSCdx2',colnames(TSCdx2_res),sep="_")
#TS vs ES
TS_rhee.data<-merge(ES_cells,TS_cells,by='ensGeneID')
rownames(TS_rhee.data)<-TS_rhee.data$ensGeneID
TS_rhee.data<-TS_rhee.data[,-1]
TS_info.df<-data.frame('condition'=c('ES','TS'),'type'=c('SR','SR'))
rownames(TS_info.df)<-colnames(TS_rhee.data)[c(1,2)]
TS_dds<-DESeqDataSetFromMatrix(countData=TS_rhee.data,colData=TS_info.df,design = ~ condition)
TS_rld<-rlogTransformation(TS_dds)
TS_res<-data.frame(assay(TS_rld),avgLogExpr=(assay(TS_rld)[,2]+assay(TS_rld)[,1])/2,rLogFC=assay(TS_rld)[,2]-assay(TS_rld)[,1])
TS_res<-TS_res[order(TS_res$rLogFC,decreasing=TRUE),]
colnames(TS_res)<-paste('TS',colnames(TS_res),sep="_")
Rhee.res<-merge(ESCdx2_res,TSCdx2_res,by="row.names")
rownames(Rhee.res)<-Rhee.res$Row.names
Rhee.res<-Rhee.res[,-1]
Rhee.res<-merge(Rhee.res,TS_res,by="row.names")
Rhee.res.anno<-AddAnnotation.FUN(df=Rhee.res,byEnsemblID=TRUE,EnsemblIDc=1,martID="mmusculus_gene_ensembl")
Rhee.res.anno.su<-subset(Rhee.res.anno,
Rhee.res.anno$ESCdx2_ES >=0 &
Rhee.res.anno$ESCdx2_OECdx2 >=0 &
Rhee.res.anno$TSCdx2_ES >=0 &
Rhee.res.anno$TSCdx2_OECdx2 >=0 &
Rhee.res.anno$TS_ES >=0 &
Rhee.res.anno$TS_TS >=0
)
############################
############################
#ESCdx2 vs TS
ESCdx2_rhee.data<-merge(TS_cells,OECdx2_ES,by='ensGeneID')
rownames(ESCdx2_rhee.data)<-ESCdx2_rhee.data$ensGeneID
ESCdx2_rhee.data<-ESCdx2_rhee.data[,-1]
ESCdx2_info.df<-data.frame('condition'=c('TS','ESCdx2'),'type'=c('SR','SR'))
rownames(ESCdx2_info.df)<-colnames(ESCdx2_rhee.data)[c(1,2)]
ESCdx2_dds<-DESeqDataSetFromMatrix(countData=ESCdx2_rhee.data,colData=ESCdx2_info.df,design = ~ condition)
ESCdx2_rld<-rlogTransformation(ESCdx2_dds)
ESCdx2_res<-data.frame(assay(ESCdx2_rld),avgLogExpr=(assay(ESCdx2_rld)[,2]+assay(ESCdx2_rld)[,1])/2,rLogFC=assay(ESCdx2_rld)[,2]-assay(ESCdx2_rld)[,1])
ESCdx2_res<-ESCdx2_res[order(ESCdx2_res$rLogFC,decreasing=TRUE),]
colnames(ESCdx2_res)<-paste('ESCdx2',colnames(ESCdx2_res),sep="_")
#TSCdx2 vs TS
TSCdx2_rhee.data<-merge(TS_cells,OECdx2_TS,by='ensGeneID')
rownames(TSCdx2_rhee.data)<-TSCdx2_rhee.data$ensGeneID
TSCdx2_rhee.data<-TSCdx2_rhee.data[,-1]
TSCdx2_info.df<-data.frame('condition'=c('TS','TSCdx2'),'type'=c('SR','SR'))
rownames(TSCdx2_info.df)<-colnames(TSCdx2_rhee.data)[c(1,2)]
TSCdx2_dds<-DESeqDataSetFromMatrix(countData=TSCdx2_rhee.data,colData=TSCdx2_info.df,design = ~ condition)
TSCdx2_rld<-rlogTransformation(TSCdx2_dds)
TSCdx2_res<-data.frame(assay(TSCdx2_rld),avgLogExpr=(assay(TSCdx2_rld)[,2]+assay(TSCdx2_rld)[,1])/2,rLogFC=assay(TSCdx2_rld)[,2]-assay(TSCdx2_rld)[,1])
TSCdx2_res<-TSCdx2_res[order(TSCdx2_res$rLogFC,decreasing=TRUE),]
colnames(TSCdx2_res)<-paste('TSCdx2',colnames(TSCdx2_res),sep="_")
Loading

0 comments on commit 78fac5c

Please sign in to comment.