]> git.donarmstrong.com Git - mothur.git/blob - bayesian.cpp
latest version
[mothur.git] / bayesian.cpp
1 /*
2  *  bayesian.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 11/3/09.
6  *  Copyright 2009 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "bayesian.h"
11 #include "kmer.hpp"
12 #include "phylosummary.h"
13
14 /**************************************************************************************************/
15 Bayesian::Bayesian(string tfile, string tempFile, string method, int ksize, int cutoff, int i) : 
16 Classify(), kmerSize(ksize), confidenceThreshold(cutoff), iters(i)  {
17         try {
18                                         
19                 /************calculate the probablity that each word will be in a specific taxonomy*************/
20                 string tfileroot = tfile.substr(0,tfile.find_last_of(".")+1);
21                 string tempfileroot = getRootName(getSimpleName(tempFile));
22                 string phyloTreeName = tfileroot + "tree.train";
23                 string probFileName = tfileroot + tempfileroot + char('0'+ kmerSize) + "mer.prob";
24                 string probFileName2 = tfileroot + tempfileroot + char('0'+ kmerSize) + "mer.numNonZero";
25                 
26                 ofstream out;
27                 ofstream out2;
28                 
29                 ifstream phyloTreeTest(phyloTreeName.c_str());
30                 ifstream probFileTest2(probFileName2.c_str());
31                 ifstream probFileTest(probFileName.c_str());
32                 
33                 int start = time(NULL);
34                 
35                 if(probFileTest && probFileTest2 && phyloTreeTest){     
36                         m->mothurOut("Reading template taxonomy...     "); cout.flush();
37                         
38                         phyloTree = new PhyloTree(phyloTreeTest, phyloTreeName);
39                         
40                         m->mothurOut("DONE."); m->mothurOutEndLine();
41                         
42                         genusNodes = phyloTree->getGenusNodes(); 
43                         genusTotals = phyloTree->getGenusTotals();
44                 
45                         m->mothurOut("Reading template probabilities...     "); cout.flush();
46                         readProbFile(probFileTest, probFileTest2, probFileName, probFileName2); 
47                         
48                 }else{
49                 
50                         //create search database and names vector
51                         generateDatabaseAndNames(tfile, tempFile, method, ksize, 0.0, 0.0, 0.0, 0.0);
52                         
53                         genusNodes = phyloTree->getGenusNodes(); 
54                         genusTotals = phyloTree->getGenusTotals();
55                         
56                         m->mothurOut("Calculating template taxonomy tree...     "); cout.flush();
57                         
58                         phyloTree->printTreeNodes(phyloTreeName);
59                                                 
60                         m->mothurOut("DONE."); m->mothurOutEndLine();
61                         
62                         m->mothurOut("Calculating template probabilities...     "); cout.flush();
63                         
64                         numKmers = database->getMaxKmer() + 1;
65                 
66                         //initialze probabilities
67                         wordGenusProb.resize(numKmers);
68                 
69                         for (int j = 0; j < wordGenusProb.size(); j++) {        wordGenusProb[j].resize(genusNodes.size());             }
70                         
71                         
72                         #ifdef USE_MPI
73                                 int pid;
74                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
75
76                                 if (pid == 0) {  
77                         #endif
78
79                         ofstream out;
80                         openOutputFile(probFileName, out);
81                         
82                         out << numKmers << endl;
83                         
84                         ofstream out2;
85                         openOutputFile(probFileName2, out2);
86                         
87                         #ifdef USE_MPI
88                                 }
89                         #endif
90
91                         
92                         //for each word
93                         for (int i = 0; i < numKmers; i++) {
94                                 if (m->control_pressed) { break; }
95                                 
96                                 #ifdef USE_MPI
97                                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
98
99                                         if (pid == 0) {  
100                                 #endif
101
102                                 out << i << '\t';
103                                 
104                                 #ifdef USE_MPI
105                                         }
106                                 #endif
107                                 
108                                 vector<int> seqsWithWordi = database->getSequencesWithKmer(i);
109                                 
110                                 map<int, int> count;
111                                 for (int k = 0; k < genusNodes.size(); k++) {  count[genusNodes[k]] = 0;  }                     
112                                                 
113                                 //for each sequence with that word
114                                 for (int j = 0; j < seqsWithWordi.size(); j++) {
115                                         int temp = phyloTree->getIndex(names[seqsWithWordi[j]]);
116                                         count[temp]++;  //increment count of seq in this genus who have this word
117                                 }
118                                 
119                                 //probabilityInTemplate = (# of seqs with that word in template + 0.05) / (total number of seqs in template + 1);
120                                 float probabilityInTemplate = (seqsWithWordi.size() + 0.50) / (float) (names.size() + 1);
121                                 
122                                 int numNotZero = 0;
123                                 for (int k = 0; k < genusNodes.size(); k++) {
124                                         //probabilityInThisTaxonomy = (# of seqs with that word in this taxonomy + probabilityInTemplate) / (total number of seqs in this taxonomy + 1);
125                                         wordGenusProb[i][k] = log((count[genusNodes[k]] + probabilityInTemplate) / (float) (genusTotals[k] + 1));  
126                                         if (count[genusNodes[k]] != 0) { 
127                                                 #ifdef USE_MPI
128                                                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
129                                                         if (pid == 0) {  
130                                                 #endif
131
132                                                 out << k << '\t' << wordGenusProb[i][k] << '\t'; 
133                                                 
134                                                 #ifdef USE_MPI
135                                                         }
136                                                 #endif
137
138                                                 numNotZero++;  
139                                         }
140                                 }
141                                 
142                                 #ifdef USE_MPI
143                                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
144                                         if (pid == 0) {  
145                                 #endif
146                                 
147                                 out << endl;
148                                 out2 << probabilityInTemplate << '\t' << numNotZero << endl;
149                                 
150                                 #ifdef USE_MPI
151                                         }
152                                 #endif
153                         }
154                         
155                         #ifdef USE_MPI
156                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
157                                 if (pid == 0) {  
158                         #endif
159                         
160                         out.close();
161                         out2.close();
162                         
163                         #ifdef USE_MPI
164                                 }
165                         #endif
166                         
167                         //read in new phylotree with less info. - its faster
168                         ifstream phyloTreeTest(phyloTreeName.c_str());
169                         delete phyloTree;
170                         
171                         phyloTree = new PhyloTree(phyloTreeTest, phyloTreeName);
172                 }
173         
174                 m->mothurOut("DONE."); m->mothurOutEndLine();
175                 m->mothurOut("It took " + toString(time(NULL) - start) + " seconds get probabilities. "); m->mothurOutEndLine();
176         }
177         catch(exception& e) {
178                 m->errorOut(e, "Bayesian", "Bayesian");
179                 exit(1);
180         }
181 }
182 /**************************************************************************************************/
183 Bayesian::~Bayesian() {
184         try {
185                  delete phyloTree; 
186                  if (database != NULL) {  delete database; }
187         }
188         catch(exception& e) {
189                 m->errorOut(e, "Bayesian", "~Bayesian");
190                 exit(1);
191         }
192 }
193
194 /**************************************************************************************************/
195 string Bayesian::getTaxonomy(Sequence* seq) {
196         try {
197                 string tax = "";
198                 Kmer kmer(kmerSize);
199                 
200                 //get words contained in query
201                 //getKmerString returns a string where the index in the string is hte kmer number 
202                 //and the character at that index can be converted to be the number of times that kmer was seen
203
204                 string queryKmerString = kmer.getKmerString(seq->getUnaligned()); 
205
206                 vector<int> queryKmers;
207                 for (int i = 0; i < queryKmerString.length(); i++) {
208                         if (queryKmerString[i] != '!') { //this kmer is in the query
209                                 queryKmers.push_back(i);
210                         }
211                 }
212                 
213                 if (queryKmers.size() == 0) {  m->mothurOut(seq->getName() + "is bad."); m->mothurOutEndLine(); return "bad seq"; }
214                 
215                 int index = getMostProbableTaxonomy(queryKmers);
216                 
217                 if (m->control_pressed) { return tax; }
218 //cout << seq->getName() << '\t' << index << endl;                                      
219                 //bootstrap - to set confidenceScore
220                 int numToSelect = queryKmers.size() / 8;
221                 tax = bootstrapResults(queryKmers, index, numToSelect);
222                                                 
223                 return tax;     
224         }
225         catch(exception& e) {
226                 m->errorOut(e, "Bayesian", "getTaxonomy");
227                 exit(1);
228         }
229 }
230 /**************************************************************************************************/
231 string Bayesian::bootstrapResults(vector<int> kmers, int tax, int numToSelect) {
232         try {
233                                 
234                 map<int, int> confidenceScores; 
235                                 
236                 map<int, int>::iterator itBoot;
237                 map<int, int>::iterator itBoot2;
238                 map<int, int>::iterator itConvert;
239                 
240                 for (int i = 0; i < iters; i++) {
241                         if (m->control_pressed) { return "control"; }
242                         
243                         vector<int> temp;
244                                                 
245                         for (int j = 0; j < numToSelect; j++) {
246                                 int index = int(rand() % kmers.size());
247                                 
248                                 //add word to temp
249                                 temp.push_back(kmers[index]);
250                         }
251                         
252                         //get taxonomy
253                         int newTax = getMostProbableTaxonomy(temp);
254                         TaxNode taxonomyTemp = phyloTree->get(newTax);
255         
256                         //add to confidence results
257                         while (taxonomyTemp.level != 0) { //while you are not at the root
258                                 
259                                 itBoot2 = confidenceScores.find(newTax); //is this a classification we already have a count on
260                                 
261                                 if (itBoot2 == confidenceScores.end()) { //not already in confidence scores
262                                         confidenceScores[newTax] = 1;
263                                 }else{
264                                         confidenceScores[newTax]++;
265                                 }
266                                 
267                                 newTax = taxonomyTemp.parent;
268                                 taxonomyTemp = phyloTree->get(newTax);
269                         }
270         
271                 }
272                 
273                 string confidenceTax = "";
274                 simpleTax = "";
275                 
276                 int seqTaxIndex = tax;
277                 TaxNode seqTax = phyloTree->get(tax);
278                 
279                 while (seqTax.level != 0) { //while you are not at the root
280                                         
281                                 itBoot2 = confidenceScores.find(seqTaxIndex); //is this a classification we already have a count on
282                                 
283                                 int confidence = 0;
284                                 if (itBoot2 != confidenceScores.end()) { //already in confidence scores
285                                         confidence = confidenceScores[seqTaxIndex];
286                                 }
287                                 
288                                 if (((confidence/(float)iters) * 100) >= confidenceThreshold) {
289                                         confidenceTax = seqTax.name + "(" + toString(((confidence/(float)iters) * 100)) + ");" + confidenceTax;
290                                         simpleTax = seqTax.name + ";" + simpleTax;
291                                 }
292                                 
293                                 seqTaxIndex = seqTax.parent;
294                                 seqTax = phyloTree->get(seqTax.parent);
295                 }
296                 
297                 if (confidenceTax == "") { confidenceTax = "unclassified;"; simpleTax = "unclassified;"; }
298                 return confidenceTax;
299                 
300         }
301         catch(exception& e) {
302                 m->errorOut(e, "Bayesian", "bootstrapResults");
303                 exit(1);
304         }
305 }
306 /**************************************************************************************************/
307 int Bayesian::getMostProbableTaxonomy(vector<int> queryKmer) {
308         try {
309                 int indexofGenus = 0;
310                 
311                 double maxProbability = -1000000.0;
312                 //find taxonomy with highest probability that this sequence is from it
313                 for (int k = 0; k < genusNodes.size(); k++) {
314                         //for each taxonomy calc its probability
315                         double prob = 1.0;
316                         for (int i = 0; i < queryKmer.size(); i++) {
317                                 prob += wordGenusProb[queryKmer[i]][k];
318                         }
319                 
320                         //is this the taxonomy with the greatest probability?
321                         if (prob > maxProbability) { 
322                                 indexofGenus = genusNodes[k];
323                                 maxProbability = prob;
324                         }
325                 }
326
327                 return indexofGenus;
328         }
329         catch(exception& e) {
330                 m->errorOut(e, "Bayesian", "getMostProbableTaxonomy");
331                 exit(1);
332         }
333 }
334 /*************************************************************************************************
335 map<string, int> Bayesian::parseTaxMap(string newTax) {
336         try{
337         
338                 map<string, int> parsed;
339                 
340                 newTax = newTax.substr(0, newTax.length()-1);  //get rid of last ';'
341         
342                 //parse taxonomy
343                 string individual;
344                 while (newTax.find_first_of(';') != -1) {
345                         individual = newTax.substr(0,newTax.find_first_of(';'));
346                         newTax = newTax.substr(newTax.find_first_of(';')+1, newTax.length());
347                         parsed[individual] = 1;
348                 }
349                 
350                 //get last one
351                 parsed[newTax] = 1;
352
353                 return parsed;
354                 
355         }
356         catch(exception& e) {
357                 m->errorOut(e, "Bayesian", "parseTax");
358                 exit(1);
359         }
360 }
361 /**************************************************************************************************/
362 void Bayesian::readProbFile(ifstream& in, ifstream& inNum, string inName, string inNumName) {
363         try{
364                 
365                 #ifdef USE_MPI
366                         
367                         int pid, num, num2, processors;
368                         vector<long> positions;
369                         vector<long> positions2;
370                         
371                         MPI_Status status; 
372                         MPI_File inMPI;
373                         MPI_File inMPI2;
374                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
375                         MPI_Comm_size(MPI_COMM_WORLD, &processors);
376                         int tag = 2001;
377
378                         char inFileName[1024];
379                         strcpy(inFileName, inNumName.c_str());
380                         
381                         char inFileName2[1024];
382                         strcpy(inFileName2, inName.c_str());
383
384                         MPI_File_open(MPI_COMM_WORLD, inFileName, MPI_MODE_RDONLY, MPI_INFO_NULL, &inMPI);  //comm, filename, mode, info, filepointer
385                         MPI_File_open(MPI_COMM_WORLD, inFileName2, MPI_MODE_RDONLY, MPI_INFO_NULL, &inMPI2);  //comm, filename, mode, info, filepointer
386
387                         if (pid == 0) {
388                                 positions = setFilePosEachLine(inNumName, num);
389                                 positions2 = setFilePosEachLine(inName, num2);
390                                 
391                                 for(int i = 1; i < processors; i++) { 
392                                         MPI_Send(&num, 1, MPI_INT, i, tag, MPI_COMM_WORLD);
393                                         MPI_Send(&positions[0], (num+1), MPI_LONG, i, tag, MPI_COMM_WORLD);
394                                         
395                                         MPI_Send(&num2, 1, MPI_INT, i, tag, MPI_COMM_WORLD);
396                                         MPI_Send(&positions2[0], (num2+1), MPI_LONG, i, tag, MPI_COMM_WORLD);
397                                 }
398
399                         }else{
400                                 MPI_Recv(&num, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &status);
401                                 positions.resize(num+1);
402                                 MPI_Recv(&positions[0], (num+1), MPI_LONG, 0, tag, MPI_COMM_WORLD, &status);
403                                 
404                                 MPI_Recv(&num2, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &status);
405                                 positions2.resize(num2+1);
406                                 MPI_Recv(&positions2[0], (num2+1), MPI_LONG, 0, tag, MPI_COMM_WORLD, &status);
407                         }
408                 
409                         //read numKmers
410                         int length = positions2[1] - positions2[0];
411                         char* buf = new char[length];
412
413                         MPI_File_read_at(inMPI2, positions2[0], buf, length, MPI_CHAR, &status);
414
415                         string tempBuf = buf;
416                         if (tempBuf.length() > length) { tempBuf = tempBuf.substr(0, length); }
417                         delete buf;
418
419                         istringstream iss (tempBuf,istringstream::in);
420                         iss >> numKmers;  
421                         
422                         //initialze probabilities
423                         wordGenusProb.resize(numKmers);
424                         
425                         for (int j = 0; j < wordGenusProb.size(); j++) {        wordGenusProb[j].resize(genusNodes.size());             }
426                         
427                         int kmer, name;  
428                         vector<int> numbers; numbers.resize(numKmers);
429                         float prob;
430                         vector<float> zeroCountProb; zeroCountProb.resize(numKmers);            
431
432                         //read file 
433                         for(int i=0;i<num;i++){
434                                 //read next sequence
435                                 length = positions[i+1] - positions[i];
436                                 char* buf4 = new char[length];
437
438                                 MPI_File_read_at(inMPI, positions[i], buf4, length, MPI_CHAR, &status);
439
440                                 tempBuf = buf4;
441                                 if (tempBuf.length() > length) { tempBuf = tempBuf.substr(0, length); }
442                                 delete buf4;
443
444                                 istringstream iss (tempBuf,istringstream::in);
445                                 iss >> zeroCountProb[i] >> numbers[i];  
446                         }
447                         
448                         MPI_File_close(&inMPI);
449                         
450                         for(int i=1;i<num2;i++){
451                                 //read next sequence
452                                 length = positions2[i+1] - positions2[i];
453                                 char* buf4 = new char[length];
454
455                                 MPI_File_read_at(inMPI2, positions2[i], buf4, length, MPI_CHAR, &status);
456
457                                 tempBuf = buf4;
458                                 if (tempBuf.length() > length) { tempBuf = tempBuf.substr(0, length); }
459                                 delete buf4;
460
461                                 istringstream iss (tempBuf,istringstream::in);
462                                 
463                                 iss >> kmer;
464                                 
465                                 //set them all to zero value
466                                 for (int i = 0; i < genusNodes.size(); i++) {
467                                         wordGenusProb[kmer][i] = log(zeroCountProb[kmer] / (float) (genusTotals[i]+1));
468                                 }
469                                 
470                                 //get probs for nonzero values
471                                 for (int i = 0; i < numbers[kmer]; i++) {
472                                         iss >> name >> prob;
473                                         wordGenusProb[kmer][name] = prob;
474                                 }
475                                 
476                         }
477                         MPI_File_close(&inMPI2);
478                         MPI_Barrier(MPI_COMM_WORLD); //make everyone wait - just in case
479                 #else
480                 
481                         in >> numKmers; gobble(in);
482                         
483                         //initialze probabilities
484                         wordGenusProb.resize(numKmers);
485                         
486                         for (int j = 0; j < wordGenusProb.size(); j++) {        wordGenusProb[j].resize(genusNodes.size());             }
487                         
488                         int kmer, name, count;  count = 0;
489                         vector<int> num; num.resize(numKmers);
490                         float prob;
491                         vector<float> zeroCountProb; zeroCountProb.resize(numKmers);            
492                 
493                         while (inNum) {
494                                 inNum >> zeroCountProb[count] >> num[count];  
495                                 count++;
496                                 gobble(inNum);
497                         }
498                         inNum.close();
499                 
500                         while(in) {
501                                 in >> kmer;
502                                 
503                                 //set them all to zero value
504                                 for (int i = 0; i < genusNodes.size(); i++) {
505                                         wordGenusProb[kmer][i] = log(zeroCountProb[kmer] / (float) (genusTotals[i]+1));
506                                 }
507                                 
508                                 //get probs for nonzero values
509                                 for (int i = 0; i < num[kmer]; i++) {
510                                         in >> name >> prob;
511                                         wordGenusProb[kmer][name] = prob;
512                                 }
513                                 
514                                 gobble(in);
515                         }
516                         in.close();
517                         
518                 #endif
519         }
520         catch(exception& e) {
521                 m->errorOut(e, "Bayesian", "readProbFile");
522                 exit(1);
523         }
524 }
525 /**************************************************************************************************/
526
527
528
529
530
531