19
|
1 # Name: region_motif_compare.r
|
|
2 # Description: Reads in two count files and determines enriched and depleted
|
|
3 # motifs (or any location based feature) based on poisson tests and gc
|
|
4 # corrections. All enrichment ratios relative to overall count / gc ratios.
|
|
5 # Author: Jeremy liu
|
|
6 # Email: jeremy.liu@yale.edu
|
31
|
7 # Date: 15/02/04
|
19
|
8 # Note: This script is meant to be invoked with the following command
|
|
9 # R --slave --vanilla -f ./region_motif_compare.r --args <workingdir> <db> <intab1> <intab2>
|
|
10 # <enriched_tab> <depleted_tab> <plots_png>
|
|
11 # <workingdir> is working directory of galaxy installation
|
|
12 # <db> types: "t" test, "p" pouya, "j" jaspar jolma, "m" mouse, "c" combined
|
|
13 # Dependencies: plotting.r
|
|
14
|
|
15 # Auxiliary function to concatenate multiple strings
|
|
16 concat <- function(...) {
|
|
17 input_list <- list(...)
|
|
18 return(paste(input_list, sep="", collapse=""))
|
|
19 }
|
|
20
|
|
21 # Supress all warning messages to prevent Galaxy treating warnings as errors
|
|
22 options(warn=-1)
|
|
23
|
|
24 # Set common and data directories
|
|
25 args <- commandArgs()
|
|
26 workingDir = args[7]
|
|
27 dbCode = args[8]
|
|
28 # dbCode "c" implemented when pwmFile is loaded
|
|
29 if (dbCode == "t" | dbCode == "p") {
|
31
|
30 pwmFile = concat(workingDir, "/pwms/pouya.pwms.from.seq.RData")
|
19
|
31 } else if (dbCode == "j") {
|
31
|
32 pwmFile = concat(workingDir, "/pwms/jaspar.jolma.pwms.from.seq.RData")
|
19
|
33 } else if (dbCode == "m") {
|
31
|
34 pwmFile = concat(workingDir, "/pwms/mm9.pwms.from.seq.RData")
|
19
|
35 } else if (dbCode == "c") { # rest of dbCode "c" implemeted when pwmFile loaded
|
31
|
36 pwmFile = concat(workingDir, "/pwms/pouya.pwms.from.seq.RData")
|
|
37 pwmFile2 = concat(workingDir, "/pwms/jaspar.jolma.pwms.from.seq.RData")
|
19
|
38 } else {
|
31
|
39 pwmFile = concat(workingDir, "/pwms/pouya.pwms.from.seq.RData")
|
19
|
40 }
|
|
41
|
|
42 # Set input and reference files
|
|
43 inTab1 = args[9]
|
|
44 inTab2 = args[10]
|
|
45 enrichTab = args[11]
|
|
46 depleteTab = args[12]
|
|
47 plotsPng = args[13]
|
|
48
|
|
49 # Load dependencies
|
31
|
50 source(concat(workingDir, "/plotting.r"))
|
19
|
51
|
|
52 # Auxiliary function to read in tab file and prepare the data
|
|
53 read_tsv <- function(file) {
|
|
54 data = read.table(file, sep="\t", stringsAsFactors=FALSE)
|
|
55 names(data)[names(data) == "V1"] = "motif"
|
|
56 names(data)[names(data) == "V2"] = "counts"
|
|
57 return(data)
|
|
58 }
|
|
59
|
|
60 startTime = Sys.time()
|
|
61 cat("Running ... Started at:", format(startTime, "%a %b %d %X %Y"), "...\n")
|
|
62
|
|
63 # Loading motif position weight matrix (pwm) file and input tab file
|
|
64 cat("Loading and reading input region motif count files...\n")
|
|
65 load(pwmFile) # pwms data structure
|
|
66 if (dbCode == "c") { # Remaining implementation of dbCode "c" combined
|
|
67 temp = pwms
|
|
68 load(pwmFile2)
|
|
69 pwms = append(temp, pwms)
|
|
70 }
|
|
71 region1DF = read_tsv(inTab1)
|
|
72 region2DF = read_tsv(inTab2)
|
|
73 region1Counts = region1DF$counts
|
|
74 region2Counts = region2DF$counts
|
|
75 names(region1Counts) = region1DF$motif
|
|
76 names(region2Counts) = region2DF$motif
|
|
77
|
|
78 # Processing count vectors to account for missing 0 count motifs, then sorting
|
|
79 cat("Performing 0 count correction and sorting...\n")
|
|
80 allNames = union(names(region1Counts), names(region2Counts))
|
|
81 region1Diff = setdiff(allNames, names(region1Counts))
|
|
82 region2Diff = setdiff(allNames, names(region2Counts))
|
|
83 addCounts1 = rep(0, length(region1Diff))
|
|
84 addCounts2 = rep(0, length(region2Diff))
|
|
85 names(addCounts1) = region1Diff
|
|
86 names(addCounts2) = region2Diff
|
|
87 newCounts1 = append(region1Counts, addCounts1)
|
|
88 newCounts2 = append(region2Counts, addCounts2)
|
|
89 region1Counts = newCounts1[sort.int(names(newCounts1), index.return=TRUE)$ix]
|
|
90 region2Counts = newCounts2[sort.int(names(newCounts2), index.return=TRUE)$ix]
|
|
91
|
|
92 # Generate gc content matrix
|
|
93 gc = sapply(pwms, function(i) mean(i[2:3,3:18]))
|
|
94
|
|
95 # Apply poisson test, calculate p and q values, and filter significant results
|
|
96 cat("Applying poisson test...\n")
|
|
97 rValue = sum(region2Counts) / sum(region1Counts)
|
|
98 pValue = sapply(seq(along=region1Counts), function(i) {
|
|
99 poisson.test(c(region1Counts[i], region2Counts[i]), r=1/rValue)$p.value
|
|
100 })
|
|
101 qValue = p.adjust(pValue, "fdr")
|
|
102 indices = which(qValue<0.1 & abs(log2(region1Counts/region2Counts/rValue))>log2(1.5))
|
|
103
|
|
104 # Setting up output diagnostic plots, 4 in 1 png image
|
|
105 png(plotsPng, width=800, height=800)
|
|
106 xlab = "region1_count"
|
|
107 ylab = "region2_count"
|
|
108 lim = c(0.5, 5000)
|
|
109 layout(matrix(1:4, ncol=2))
|
|
110 par(mar=c(5, 5, 5, 1))
|
|
111
|
|
112 # Plot all motif counts along the linear correlation coefficient
|
|
113 plot.scatter(region1Counts+0.5, region2Counts+0.5, log="xy", xlab=xlab, ylab=ylab,
|
|
114 cex.lab=2.2, cex.axis=1.8, xlim=lim, ylim=lim*rValue)
|
|
115 abline(0, rValue, untf=T)
|
|
116 abline(0, rValue*2, untf=T, lty=2)
|
|
117 abline(0, rValue/2, untf=T, lty=2)
|
|
118
|
|
119 # Plot enriched and depleted motifs in red, housed in second plot
|
|
120 plot.scatter(region1Counts+0.5, region2Counts+0.5, log="xy", xlab=xlab, ylab=ylab,
|
|
121 cex.lab=2.2, cex.axis=1.8, xlim=lim, ylim=lim*rValue)
|
|
122 points(region1Counts[indices]+0.5, region2Counts[indices]+0.5, col="red")
|
|
123 abline(0, rValue, untf=T)
|
|
124 abline(0, rValue*2, untf=T, lty=2)
|
|
125 abline(0, rValue/2, untf=T, lty=2)
|
|
126
|
|
127 # Apply and plot gc correction and loess curve
|
|
128 cat("Applying gc correction, rerunning poisson test...\n")
|
|
129 ind = which(region1Counts>5)
|
|
130 gc = gc[names(region2Counts)] # Reorder the indices of pwms to match input data
|
|
131 lo = plot.scatter(gc,log2(region2Counts/region1Counts),draw.loess=T,
|
|
132 xlab="gc content of motif",ylab=paste("log2(",ylab,"/",xlab,")"),
|
|
133 cex.lab=2.2,cex.axis=1.8,ind=ind) # This function is in plotting.r
|
|
134 gcCorrection = 2^approx(lo$loess,xout=gc,rule=2)$y
|
|
135
|
|
136 # Recalculate p and q values, and filter for significant entries
|
|
137 pValueGC = sapply(seq(along=region1Counts),function(i) {
|
|
138 poisson.test(c(region1Counts[i],region2Counts[i]),r=1/gcCorrection[i])$p.value
|
|
139 })
|
|
140 qValueGC=p.adjust(pValueGC,"fdr")
|
|
141 indicesGC = which(qValueGC<0.1 & abs(log2(region1Counts/region2Counts*gcCorrection))>log2(1.5))
|
|
142
|
|
143 # Plot gc corrected motif counts
|
|
144 plot.scatter(region1Counts+0.5, (region2Counts+0.5)/gcCorrection, log="xy",
|
|
145 xlab=xlab, ylab=paste(ylab,"(normalized)"), cex.lab=2.2, cex.axis=1.8,
|
|
146 xlim=lim, ylim=lim)
|
|
147 points(region1Counts[indicesGC]+0.5,
|
|
148 (region2Counts[indicesGC]+0.5)/gcCorrection[indicesGC], col="red")
|
|
149 abline(0,1)
|
|
150 abline(0,1*2,untf=T,lty=2)
|
|
151 abline(0,1/2,untf=T,lty=2)
|
|
152
|
|
153 # Trim results, compile statistics and output to file
|
|
154 # Only does so if significant results are computed
|
|
155 if(length(indicesGC) > 0) {
|
|
156 # Calculate expected counts and enrichment ratios
|
|
157 cat("Calculating statistics...\n")
|
|
158 nullExpect = region1Counts * gcCorrection
|
|
159 enrichment = region2Counts / nullExpect
|
|
160
|
|
161 # Reorder selected indices in ascending pvalue
|
|
162 cat("Reordering by ascending pvalue...\n")
|
|
163 indicesReorder = indicesGC[order(pValueGC[indicesGC])]
|
|
164
|
|
165 # Combine data into one data frame and output to two files
|
|
166 cat("Splitting and outputting data...\n")
|
|
167 outDF = data.frame(motif=names(pValueGC), p=as.numeric(pValueGC), q=qValueGC,
|
|
168 stringsAsFactors=F, region_1_count=region1Counts,
|
|
169 null_expectation=round(nullExpect,2), region_2_count=region2Counts,
|
|
170 enrichment=enrichment)[indicesReorder,]
|
|
171 names(outDF)[which(names(outDF)=="region_1_count")]=xlab
|
|
172 names(outDF)[which(names(outDF)=="region_2_count")]=ylab
|
|
173 indicesEnrich = which(outDF$enrichment>1)
|
|
174 indicesDeplete = which(outDF$enrichment<1)
|
|
175 outDF$enrichment = ifelse(outDF$enrichment>1,
|
|
176 round(outDF$enrichment,3),
|
|
177 paste("1/",round(1/outDF$enrichment,3)))
|
|
178 write.table(outDF[indicesEnrich,], file=enrichTab, quote=FALSE,
|
|
179 sep="\t", append=FALSE, row.names=FALSE, col.names=TRUE)
|
|
180 write.table(outDF[indicesDeplete,], file=depleteTab, quote=FALSE,
|
|
181 sep="\t", append=FALSE, row.names=FALSE, col.names=TRUE)
|
|
182 }
|
|
183
|
|
184 # Catch display messages and output timing information
|
|
185 catchMessage = dev.off()
|
|
186 cat("Done. Job started at:", format(startTime, "%a %b %d %X %Y."),
|
|
187 "Job ended at:", format(Sys.time(), "%a %b %d %X %Y."), "\n")
|