67
|
1 args <- commandArgs(trailingOnly = TRUE)
|
|
2
|
|
3
|
|
4 summaryfile = args[1]
|
|
5 sequencesfile = args[2]
|
|
6 mutationanalysisfile = args[3]
|
|
7 mutationstatsfile = args[4]
|
|
8 hotspotsfile = args[5]
|
|
9 aafile = args[6]
|
|
10 gene_identification_file= args[7]
|
|
11 output = args[8]
|
|
12 before.unique.file = args[9]
|
|
13 unmatchedfile = args[10]
|
|
14 method=args[11]
|
|
15 functionality=args[12]
|
|
16 unique.type=args[13]
|
|
17 filter.unique=args[14]
|
|
18 filter.unique.count=as.numeric(args[15])
|
|
19 class.filter=args[16]
|
|
20 empty.region.filter=args[17]
|
|
21
|
|
22 print(paste("filter.unique.count:", filter.unique.count))
|
|
23
|
|
24 summ = read.table(summaryfile, header=T, sep="\t", fill=T, stringsAsFactors=F, quote="")
|
|
25 sequences = read.table(sequencesfile, header=T, sep="\t", fill=T, stringsAsFactors=F, quote="")
|
|
26 mutationanalysis = read.table(mutationanalysisfile, header=T, sep="\t", fill=T, stringsAsFactors=F, quote="")
|
|
27 mutationstats = read.table(mutationstatsfile, header=T, sep="\t", fill=T, stringsAsFactors=F, quote="")
|
|
28 hotspots = read.table(hotspotsfile, header=T, sep="\t", fill=T, stringsAsFactors=F, quote="")
|
|
29 AAs = read.table(aafile, header=T, sep="\t", fill=T, stringsAsFactors=F, quote="")
|
|
30 gene_identification = read.table(gene_identification_file, header=T, sep="\t", fill=T, stringsAsFactors=F, quote="")
|
|
31
|
|
32 fix_column_names = function(df){
|
|
33 if("V.DOMAIN.Functionality" %in% names(df)){
|
|
34 names(df)[names(df) == "V.DOMAIN.Functionality"] = "Functionality"
|
|
35 print("found V.DOMAIN.Functionality, changed")
|
|
36 }
|
|
37 if("V.DOMAIN.Functionality.comment" %in% names(df)){
|
|
38 names(df)[names(df) == "V.DOMAIN.Functionality.comment"] = "Functionality.comment"
|
|
39 print("found V.DOMAIN.Functionality.comment, changed")
|
|
40 }
|
|
41 return(df)
|
|
42 }
|
|
43
|
|
44 fix_non_unique_ids = function(df){
|
|
45 df$Sequence.ID = paste(df$Sequence.ID, 1:nrow(df))
|
|
46 return(df)
|
|
47 }
|
|
48
|
|
49 summ = fix_column_names(summ)
|
|
50 sequences = fix_column_names(sequences)
|
|
51 mutationanalysis = fix_column_names(mutationanalysis)
|
|
52 mutationstats = fix_column_names(mutationstats)
|
|
53 hotspots = fix_column_names(hotspots)
|
|
54 AAs = fix_column_names(AAs)
|
|
55
|
|
56 if(method == "blastn"){
|
|
57 #"qseqid\tsseqid\tpident\tlength\tmismatch\tgapopen\tqstart\tqend\tsstart\tsend\tevalue\tbitscore"
|
|
58 gene_identification = gene_identification[!duplicated(gene_identification$qseqid),]
|
|
59 ref_length = data.frame(sseqid=c("ca1", "ca2", "cg1", "cg2", "cg3", "cg4", "cm"), ref.length=c(81,81,141,141,141,141,52))
|
|
60 gene_identification = merge(gene_identification, ref_length, by="sseqid", all.x=T)
|
|
61 gene_identification$chunk_hit_percentage = (gene_identification$length / gene_identification$ref.length) * 100
|
|
62 gene_identification = gene_identification[,c("qseqid", "chunk_hit_percentage", "pident", "qstart", "sseqid")]
|
|
63 colnames(gene_identification) = c("Sequence.ID", "chunk_hit_percentage", "nt_hit_percentage", "start_locations", "best_match")
|
|
64 }
|
|
65
|
|
66 #print("Summary analysis files columns")
|
|
67 #print(names(summ))
|
|
68
|
|
69
|
|
70
|
|
71 input.sequence.count = nrow(summ)
|
|
72 print(paste("Number of sequences in summary file:", input.sequence.count))
|
|
73
|
|
74 filtering.steps = data.frame(character(0), numeric(0))
|
|
75
|
|
76 filtering.steps = rbind(filtering.steps, c("Input", input.sequence.count))
|
|
77
|
|
78 filtering.steps[,1] = as.character(filtering.steps[,1])
|
|
79 filtering.steps[,2] = as.character(filtering.steps[,2])
|
|
80 #filtering.steps[,3] = as.numeric(filtering.steps[,3])
|
|
81
|
|
82 #print("summary files columns")
|
|
83 #print(names(summ))
|
|
84
|
|
85 summ = merge(summ, gene_identification, by="Sequence.ID")
|
|
86
|
|
87 print(paste("Number of sequences after merging with gene identification:", nrow(summ)))
|
|
88
|
|
89 summ = summ[summ$Functionality != "No results",]
|
|
90
|
|
91 print(paste("Number of sequences after 'No results' filter:", nrow(summ)))
|
|
92
|
|
93 filtering.steps = rbind(filtering.steps, c("After 'No results' filter", nrow(summ)))
|
|
94
|
|
95 if(functionality == "productive"){
|
|
96 summ = summ[summ$Functionality == "productive (see comment)" | summ$Functionality == "productive",]
|
|
97 } else if (functionality == "unproductive"){
|
|
98 summ = summ[summ$Functionality == "unproductive (see comment)" | summ$Functionality == "unproductive",]
|
|
99 } else if (functionality == "remove_unknown"){
|
|
100 summ = summ[summ$Functionality != "No results" & summ$Functionality != "unknown (see comment)" & summ$Functionality != "unknown",]
|
|
101 }
|
|
102
|
|
103 print(paste("Number of sequences after functionality filter:", nrow(summ)))
|
|
104
|
|
105 filtering.steps = rbind(filtering.steps, c("After functionality filter", nrow(summ)))
|
|
106
|
|
107 if(F){ #to speed up debugging
|
|
108 set.seed(1)
|
|
109 summ = summ[sample(nrow(summ), floor(nrow(summ) * 0.03)),]
|
|
110 print(paste("Number of sequences after sampling 3%:", nrow(summ)))
|
|
111
|
|
112 filtering.steps = rbind(filtering.steps, c("Number of sequences after sampling 3%", nrow(summ)))
|
|
113 }
|
|
114
|
|
115 print("mutation analysis files columns")
|
|
116 print(names(mutationanalysis[,!(names(mutationanalysis) %in% names(summ)[-1])]))
|
|
117
|
|
118 result = merge(summ, mutationanalysis[,!(names(mutationanalysis) %in% names(summ)[-1])], by="Sequence.ID")
|
|
119
|
|
120 print(paste("Number of sequences after merging with mutation analysis file:", nrow(result)))
|
|
121
|
|
122 #print("mutation stats files columns")
|
|
123 #print(names(mutationstats[,!(names(mutationstats) %in% names(result)[-1])]))
|
|
124
|
|
125 result = merge(result, mutationstats[,!(names(mutationstats) %in% names(result)[-1])], by="Sequence.ID")
|
|
126
|
|
127 print(paste("Number of sequences after merging with mutation stats file:", nrow(result)))
|
|
128
|
|
129 print("hotspots files columns")
|
|
130 print(names(hotspots[,!(names(hotspots) %in% names(result)[-1])]))
|
|
131
|
|
132 result = merge(result, hotspots[,!(names(hotspots) %in% names(result)[-1])], by="Sequence.ID")
|
|
133
|
|
134 print(paste("Number of sequences after merging with hotspots file:", nrow(result)))
|
|
135
|
|
136 print("sequences files columns")
|
|
137 print(c("FR1.IMGT", "CDR1.IMGT", "FR2.IMGT", "CDR2.IMGT", "FR3.IMGT", "CDR3.IMGT"))
|
|
138
|
|
139 sequences = sequences[,c("Sequence.ID", "FR1.IMGT", "CDR1.IMGT", "FR2.IMGT", "CDR2.IMGT", "FR3.IMGT", "CDR3.IMGT")]
|
|
140 names(sequences) = c("Sequence.ID", "FR1.IMGT.seq", "CDR1.IMGT.seq", "FR2.IMGT.seq", "CDR2.IMGT.seq", "FR3.IMGT.seq", "CDR3.IMGT.seq")
|
|
141 result = merge(result, sequences, by="Sequence.ID", all.x=T)
|
|
142
|
|
143 print("sequences files columns")
|
|
144 print("CDR3.IMGT")
|
|
145
|
|
146 AAs = AAs[,c("Sequence.ID", "CDR3.IMGT")]
|
|
147 names(AAs) = c("Sequence.ID", "CDR3.IMGT.AA")
|
|
148 result = merge(result, AAs, by="Sequence.ID", all.x=T)
|
|
149
|
|
150 print(paste("Number of sequences in result after merging with sequences:", nrow(result)))
|
|
151
|
|
152 result$VGene = gsub("^Homsap ", "", result$V.GENE.and.allele)
|
|
153 result$VGene = gsub("[*].*", "", result$VGene)
|
|
154 result$DGene = gsub("^Homsap ", "", result$D.GENE.and.allele)
|
|
155 result$DGene = gsub("[*].*", "", result$DGene)
|
|
156 result$JGene = gsub("^Homsap ", "", result$J.GENE.and.allele)
|
|
157 result$JGene = gsub("[*].*", "", result$JGene)
|
|
158
|
|
159 splt = strsplit(class.filter, "_")[[1]]
|
|
160 chunk_hit_threshold = as.numeric(splt[1])
|
|
161 nt_hit_threshold = as.numeric(splt[2])
|
|
162
|
|
163 higher_than=(result$chunk_hit_percentage >= chunk_hit_threshold & result$nt_hit_percentage >= nt_hit_threshold)
|
|
164
|
|
165 if(!all(higher_than, na.rm=T)){ #check for no unmatched
|
|
166 result[!higher_than,"best_match"] = paste("unmatched,", result[!higher_than,"best_match"])
|
|
167 }
|
|
168
|
|
169 if(class.filter == "101_101"){
|
|
170 result$best_match = "all"
|
|
171 }
|
|
172
|
|
173 write.table(x=result, file=gsub("merged.txt$", "before_filters.txt", output), sep="\t",quote=F,row.names=F,col.names=T)
|
|
174
|
|
175 print(paste("Number of empty CDR1 sequences:", sum(result$CDR1.IMGT.seq == "", na.rm=T)))
|
|
176 print(paste("Number of empty FR2 sequences:", sum(result$FR2.IMGT.seq == "", na.rm=T)))
|
|
177 print(paste("Number of empty CDR2 sequences:", sum(result$CDR2.IMGT.seq == "", na.rm=T)))
|
|
178 print(paste("Number of empty FR3 sequences:", sum(result$FR3.IMGT.seq == "", na.rm=T)))
|
|
179
|
|
180 if(empty.region.filter == "leader"){
|
|
181 result = result[result$FR1.IMGT.seq != "" & result$CDR1.IMGT.seq != "" & result$FR2.IMGT.seq != "" & result$CDR2.IMGT.seq != "" & result$FR3.IMGT.seq != "", ]
|
|
182 } else if(empty.region.filter == "FR1"){
|
|
183 result = result[result$CDR1.IMGT.seq != "" & result$FR2.IMGT.seq != "" & result$CDR2.IMGT.seq != "" & result$FR3.IMGT.seq != "", ]
|
|
184 } else if(empty.region.filter == "CDR1"){
|
|
185 result = result[result$FR2.IMGT.seq != "" & result$CDR2.IMGT.seq != "" & result$FR3.IMGT.seq != "", ]
|
|
186 } else if(empty.region.filter == "FR2"){
|
|
187 result = result[result$CDR2.IMGT.seq != "" & result$FR3.IMGT.seq != "", ]
|
|
188 }
|
|
189
|
|
190 print(paste("After removal sequences that are missing a gene region:", nrow(result)))
|
|
191 filtering.steps = rbind(filtering.steps, c("After removal sequences that are missing a gene region", nrow(result)))
|
|
192
|
|
193 if(empty.region.filter == "leader"){
|
|
194 result = result[!(grepl("n|N", result$FR1.IMGT.seq) | grepl("n|N", result$FR2.IMGT.seq) | grepl("n|N", result$FR3.IMGT.seq) | grepl("n|N", result$CDR1.IMGT.seq) | grepl("n|N", result$CDR2.IMGT.seq) | grepl("n|N", result$CDR3.IMGT.seq)),]
|
|
195 } else if(empty.region.filter == "FR1"){
|
|
196 result = result[!(grepl("n|N", result$FR2.IMGT.seq) | grepl("n|N", result$FR3.IMGT.seq) | grepl("n|N", result$CDR1.IMGT.seq) | grepl("n|N", result$CDR2.IMGT.seq) | grepl("n|N", result$CDR3.IMGT.seq)),]
|
|
197 } else if(empty.region.filter == "CDR1"){
|
|
198 result = result[!(grepl("n|N", result$FR2.IMGT.seq) | grepl("n|N", result$FR3.IMGT.seq) | grepl("n|N", result$CDR2.IMGT.seq) | grepl("n|N", result$CDR3.IMGT.seq)),]
|
|
199 } else if(empty.region.filter == "FR2"){
|
|
200 result = result[!(grepl("n|N", result$FR3.IMGT.seq) | grepl("n|N", result$CDR2.IMGT.seq) | grepl("n|N", result$CDR3.IMGT.seq)),]
|
|
201 }
|
|
202
|
|
203 print(paste("Number of sequences in result after n filtering:", nrow(result)))
|
|
204 filtering.steps = rbind(filtering.steps, c("After N filter", nrow(result)))
|
|
205
|
|
206 cleanup_columns = c("FR1.IMGT.Nb.of.mutations",
|
|
207 "CDR1.IMGT.Nb.of.mutations",
|
|
208 "FR2.IMGT.Nb.of.mutations",
|
|
209 "CDR2.IMGT.Nb.of.mutations",
|
|
210 "FR3.IMGT.Nb.of.mutations")
|
|
211
|
|
212 for(col in cleanup_columns){
|
|
213 result[,col] = gsub("\\(.*\\)", "", result[,col])
|
|
214 result[,col] = as.numeric(result[,col])
|
|
215 result[is.na(result[,col]),] = 0
|
|
216 }
|
|
217
|
|
218 write.table(result, before.unique.file, sep="\t", quote=F,row.names=F,col.names=T)
|
|
219
|
|
220 if(filter.unique != "no"){
|
|
221 clmns = names(result)
|
|
222 if(filter.unique == "remove_vjaa"){
|
|
223 result$unique.def = paste(result$VGene, result$JGene, result$CDR3.IMGT.AA)
|
|
224 } else if(empty.region.filter == "leader"){
|
|
225 result$unique.def = paste(result$FR1.IMGT.seq, result$CDR1.IMGT.seq, result$FR2.IMGT.seq, result$CDR2.IMGT.seq, result$FR3.IMGT.seq, result$CDR3.IMGT.seq)
|
|
226 } else if(empty.region.filter == "FR1"){
|
|
227 result$unique.def = paste(result$CDR1.IMGT.seq, result$FR2.IMGT.seq, result$CDR2.IMGT.seq, result$FR3.IMGT.seq, result$CDR3.IMGT.seq)
|
|
228 } else if(empty.region.filter == "CDR1"){
|
|
229 result$unique.def = paste(result$FR2.IMGT.seq, result$CDR2.IMGT.seq, result$FR3.IMGT.seq, result$CDR3.IMGT.seq)
|
|
230 } else if(empty.region.filter == "FR2"){
|
|
231 result$unique.def = paste(result$CDR2.IMGT.seq, result$FR3.IMGT.seq, result$CDR3.IMGT.seq)
|
|
232 }
|
|
233
|
|
234 if(grepl("remove", filter.unique)){
|
|
235 result = result[duplicated(result$unique.def) | duplicated(result$unique.def, fromLast=T),]
|
|
236 unique.defs = data.frame(table(result$unique.def))
|
|
237 unique.defs = unique.defs[unique.defs$Freq >= filter.unique.count,]
|
|
238 result = result[result$unique.def %in% unique.defs$Var1,]
|
|
239 }
|
|
240
|
|
241 if(filter.unique != "remove_vjaa"){
|
|
242 result$unique.def = paste(result$unique.def, gsub(",.*", "", result$best_match)) #keep the unique sequences that are in multiple classes, gsub so the unmatched don't have a class after it
|
|
243 }
|
|
244
|
|
245 result = result[!duplicated(result$unique.def),]
|
|
246 }
|
|
247
|
|
248 write.table(result, gsub("before_unique_filter.txt", "after_unique_filter.txt", before.unique.file), sep="\t", quote=F,row.names=F,col.names=T)
|
|
249
|
|
250 filtering.steps = rbind(filtering.steps, c("After filter unique sequences", nrow(result)))
|
|
251
|
|
252 print(paste("Number of sequences in result after unique filtering:", nrow(result)))
|
|
253
|
|
254 if(nrow(summ) == 0){
|
|
255 stop("No data remaining after filter")
|
|
256 }
|
|
257
|
|
258 result$best_match_class = gsub(",.*", "", result$best_match) #gsub so the unmatched don't have a class after it
|
|
259
|
|
260 #result$past = ""
|
|
261 #cls = unlist(strsplit(unique.type, ","))
|
|
262 #for (i in 1:nrow(result)){
|
|
263 # result[i,"past"] = paste(result[i,cls], collapse=":")
|
|
264 #}
|
|
265
|
|
266
|
|
267
|
|
268 result$past = do.call(paste, c(result[unlist(strsplit(unique.type, ","))], sep = ":"))
|
|
269
|
|
270 result.matched = result[!grepl("unmatched", result$best_match),]
|
|
271 result.unmatched = result[grepl("unmatched", result$best_match),]
|
|
272
|
|
273 result = rbind(result.matched, result.unmatched)
|
|
274
|
|
275 result = result[!(duplicated(result$past)), ]
|
|
276
|
|
277 result = result[,!(names(result) %in% c("past", "best_match_class"))]
|
|
278
|
|
279 print(paste("Number of sequences in result after", unique.type, "filtering:", nrow(result)))
|
|
280
|
|
281 filtering.steps = rbind(filtering.steps, c("After remove duplicates based on filter", nrow(result)))
|
|
282
|
|
283 unmatched = result[grepl("^unmatched", result$best_match),c("Sequence.ID", "chunk_hit_percentage", "nt_hit_percentage", "start_locations", "best_match")]
|
|
284
|
|
285 print(paste("Number of rows in result:", nrow(result)))
|
|
286 print(paste("Number of rows in unmatched:", nrow(unmatched)))
|
|
287
|
|
288 matched.sequences = result[!grepl("^unmatched", result$best_match),]
|
|
289
|
|
290 write.table(x=matched.sequences, file=gsub("merged.txt$", "filtered.txt", output), sep="\t",quote=F,row.names=F,col.names=T)
|
|
291
|
|
292 matched.sequences.count = nrow(matched.sequences)
|
|
293 unmatched.sequences.count = sum(grepl("^unmatched", result$best_match))
|
|
294
|
|
295 filtering.steps = rbind(filtering.steps, c("Number of matched sequences", matched.sequences.count))
|
|
296 filtering.steps = rbind(filtering.steps, c("Number of unmatched sequences", unmatched.sequences.count))
|
|
297 filtering.steps[,2] = as.numeric(filtering.steps[,2])
|
|
298 filtering.steps$perc = round(filtering.steps[,2] / input.sequence.count * 100, 2)
|
|
299
|
|
300 write.table(x=filtering.steps, file=gsub("unmatched", "filtering_steps", unmatchedfile), sep="\t",quote=F,row.names=F,col.names=F)
|
|
301
|
|
302 write.table(x=result, file=output, sep="\t",quote=F,row.names=F,col.names=T)
|
|
303 write.table(x=unmatched, file=unmatchedfile, sep="\t",quote=F,row.names=F,col.names=T)
|