]> git.donarmstrong.com Git - mothur.git/blob - chimeraslayercommand.cpp
added cluster.split command
[mothur.git] / chimeraslayercommand.cpp
1 /*
2  *  chimeraslayercommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 3/31/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "chimeraslayercommand.h"
11 #include "chimeraslayer.h"
12
13
14 //***************************************************************************************************************
15
16 ChimeraSlayerCommand::ChimeraSlayerCommand(string option)  {
17         try {
18                 abort = false;
19                 
20                 //allow user to run help
21                 if(option == "help") { help(); abort = true; }
22                 
23                 else {
24                         //valid paramters for this command
25                         string Array[] =  {"fasta", "processors", "window", "template","numwanted", "ksize", "match","mismatch", 
26                         "divergence", "minsim","mincov","minbs", "minsnp","parents", "iters","outputdir","inputdir", "search","realign" };
27                         vector<string> myArray (Array, Array+(sizeof(Array)/sizeof(string)));
28                         
29                         OptionParser parser(option);
30                         map<string,string> parameters = parser.getParameters();
31                         
32                         ValidParameters validParameter;
33                         map<string,string>::iterator it;
34                         
35                         //check to make sure all parameters are valid for command
36                         for (it = parameters.begin(); it != parameters.end(); it++) { 
37                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
38                         }
39                         
40                         //if the user changes the input directory command factory will send this info to us in the output parameter 
41                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
42                         if (inputDir == "not found"){   inputDir = "";          }
43                         else {
44                                 string path;
45                                 it = parameters.find("fasta");
46                                 //user has given a template file
47                                 if(it != parameters.end()){ 
48                                         path = hasPath(it->second);
49                                         //if the user has not given a path then, add inputdir. else leave path alone.
50                                         if (path == "") {       parameters["fasta"] = inputDir + it->second;            }
51                                 }
52                                 
53                                 it = parameters.find("template");
54                                 //user has given a template file
55                                 if(it != parameters.end()){ 
56                                         path = hasPath(it->second);
57                                         //if the user has not given a path then, add inputdir. else leave path alone.
58                                         if (path == "") {       parameters["template"] = inputDir + it->second;         }
59                                 }
60                         }
61
62                         
63                         //check for required parameters
64                         fastafile = validParameter.validFile(parameters, "fasta", true);
65                         if (fastafile == "not open") { abort = true; }
66                         else if (fastafile == "not found") { fastafile = ""; m->mothurOut("fasta is a required parameter for the chimera.slayer command."); m->mothurOutEndLine(); abort = true;  }     
67                         
68                         //if the user changes the output directory command factory will send this info to us in the output parameter 
69                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  
70                                 outputDir = ""; 
71                                 outputDir += hasPath(fastafile); //if user entered a file with a path then preserve it  
72                         }
73
74                         templatefile = validParameter.validFile(parameters, "template", true);
75                         if (templatefile == "not open") { abort = true; }
76                         else if (templatefile == "not found") { templatefile = "";  m->mothurOut("template is a required parameter for the chimera.slayer command."); m->mothurOutEndLine(); abort = true;  }   
77                                                 
78                         string temp = validParameter.validFile(parameters, "processors", false);                if (temp == "not found") { temp = "1"; }
79                         convert(temp, processors);
80                         
81                         temp = validParameter.validFile(parameters, "ksize", false);                    if (temp == "not found") { temp = "7"; }
82                         convert(temp, ksize);
83                                                 
84                         temp = validParameter.validFile(parameters, "window", false);                   if (temp == "not found") { temp = "50"; }                       
85                         convert(temp, window);
86                         
87                         temp = validParameter.validFile(parameters, "match", false);                    if (temp == "not found") { temp = "5"; }
88                         convert(temp, match);
89                         
90                         temp = validParameter.validFile(parameters, "mismatch", false);                 if (temp == "not found") { temp = "-4"; }
91                         convert(temp, mismatch);
92                         
93                         temp = validParameter.validFile(parameters, "divergence", false);               if (temp == "not found") { temp = "1.007"; }
94                         convert(temp, divR);
95                         
96                         temp = validParameter.validFile(parameters, "minsim", false);                   if (temp == "not found") { temp = "90"; }
97                         convert(temp, minSimilarity);
98                         
99                         temp = validParameter.validFile(parameters, "mincov", false);                   if (temp == "not found") { temp = "70"; }
100                         convert(temp, minCoverage);
101                         
102                         temp = validParameter.validFile(parameters, "minbs", false);                    if (temp == "not found") { temp = "90"; }
103                         convert(temp, minBS);
104                         
105                         temp = validParameter.validFile(parameters, "minsnp", false);                   if (temp == "not found") { temp = "10"; }
106                         convert(temp, minSNP);
107
108                         temp = validParameter.validFile(parameters, "parents", false);                  if (temp == "not found") { temp = "3"; }
109                         convert(temp, parents); 
110                         
111                         temp = validParameter.validFile(parameters, "realign", false);                  if (temp == "not found") { temp = "f"; }
112                         realign = isTrue(temp); 
113                         
114                         search = validParameter.validFile(parameters, "search", false);                 if (search == "not found") { search = "distance"; }
115                         
116                         temp = validParameter.validFile(parameters, "iters", false);                    if (temp == "not found") { temp = "100"; }              
117                         convert(temp, iters); 
118                          
119                         temp = validParameter.validFile(parameters, "increment", false);                if (temp == "not found") { temp = "5"; }
120                         convert(temp, increment);
121                         
122                         temp = validParameter.validFile(parameters, "numwanted", false);                if (temp == "not found") { temp = "15"; }               
123                         convert(temp, numwanted);
124
125                         if ((search != "distance") && (search != "blast") && (search != "kmer")) { m->mothurOut(search + " is not a valid search."); m->mothurOutEndLine(); abort = true;  }
126                 }
127         }
128         catch(exception& e) {
129                 m->errorOut(e, "ChimeraSlayerCommand", "ChimeraSlayerCommand");
130                 exit(1);
131         }
132 }
133 //**********************************************************************************************************************
134
135 void ChimeraSlayerCommand::help(){
136         try {
137         
138                 m->mothurOut("The chimera.slayer command reads a fastafile and templatefile and outputs potentially chimeric sequences.\n");
139                 m->mothurOut("This command was modeled after the chimeraSlayer written by the Broad Institute.\n");
140                 m->mothurOut("The chimera.slayer command parameters are fasta, template, processors, ksize, window, match, mismatch, divergence. minsim, mincov, minbs, minsnp, parents, search, iters, increment and numwanted.\n"); //realign,
141                 m->mothurOut("The fasta parameter allows you to enter the fasta file containing your potentially chimeric sequences, and is required. \n");
142                 m->mothurOut("The template parameter allows you to enter a template file containing known non-chimeric sequences, and is required. \n");
143                 m->mothurOut("The processors parameter allows you to specify how many processors you would like to use.  The default is 1. \n");
144                 #ifdef USE_MPI
145                 m->mothurOut("When using MPI, the processors parameter is set to the number of MPI processes running. \n");
146                 #endif
147                 m->mothurOut("The window parameter allows you to specify the window size for searching for chimeras, default=50. \n");
148                 m->mothurOut("The increment parameter allows you to specify how far you move each window while finding chimeric sequences, default=5.\n");
149                 m->mothurOut("The numwanted parameter allows you to specify how many sequences you would each query sequence compared with, default=15.\n");
150                 m->mothurOut("The ksize parameter allows you to input kmersize, default is 7, used if search is kmer. \n");
151                 m->mothurOut("The match parameter allows you to reward matched bases in blast search, default is 5. \n");
152                 m->mothurOut("The parents parameter allows you to select the number of potential parents to investigate from the numwanted best matches after rating them, default is 3. \n");
153                 m->mothurOut("The mismatch parameter allows you to penalize mismatched bases in blast search, default is -4. \n");
154                 m->mothurOut("The divergence parameter allows you to set a cutoff for chimera determination, default is 1.007. \n");
155                 m->mothurOut("The iters parameter allows you to specify the number of bootstrap iters to do with the chimeraslayer method, default=100.\n");
156                 m->mothurOut("The minsim parameter allows you to specify a minimum similarity with the parent fragments, default=90. \n");
157                 m->mothurOut("The mincov parameter allows you to specify minimum coverage by closest matches found in template. Default is 70, meaning 70%. \n");
158                 m->mothurOut("The minbs parameter allows you to specify minimum bootstrap support for calling a sequence chimeric. Default is 90, meaning 90%. \n");
159                 m->mothurOut("The minsnp parameter allows you to specify percent of SNPs to sample on each side of breakpoint for computing bootstrap support (default: 10) \n");
160                 m->mothurOut("The search parameter allows you to specify search method for finding the closest parent. Choices are distance, blast, and kmer, default distance. \n");
161                 //m->mothurOut("The realign parameter allows you to realign the query to the potential parents. Choices are true or false, default false. Found to make results worse. \n");
162                 m->mothurOut("The chimera.slayer command should be in the following format: \n");
163                 m->mothurOut("chimera.slayer(fasta=yourFastaFile, template=yourTemplate, search=yourSearch) \n");
164                 m->mothurOut("Example: chimera.slayer(fasta=AD.align, template=core_set_aligned.imputed.fasta, search=kmer) \n");
165                 m->mothurOut("Note: No spaces between parameter labels (i.e. fasta), '=' and parameters (i.e.yourFastaFile).\n\n");     
166         }
167         catch(exception& e) {
168                 m->errorOut(e, "ChimeraSlayerCommand", "help");
169                 exit(1);
170         }
171 }
172
173 //***************************************************************************************************************
174
175 ChimeraSlayerCommand::~ChimeraSlayerCommand(){  /*      do nothing      */      }
176
177 //***************************************************************************************************************
178
179 int ChimeraSlayerCommand::execute(){
180         try{
181                 
182                 if (abort == true) { return 0; }
183                 
184                 int start = time(NULL); 
185                 
186                 chimera = new ChimeraSlayer(fastafile, templatefile, search, ksize, match, mismatch, window, divR, minSimilarity, minCoverage, minBS, minSNP, parents, iters, increment, numwanted, realign);   
187                                                 
188                 string outputFileName = outputDir + getRootName(getSimpleName(fastafile)) + "slayer.chimeras";
189                 string accnosFileName = outputDir + getRootName(getSimpleName(fastafile))  + "slayer.accnos";
190                 bool hasAccnos = true;
191                 
192                 if (m->control_pressed) { delete chimera;       return 0;       }
193                 
194                 if (chimera->getUnaligned()) { 
195                         m->mothurOut("Your template sequences are different lengths, please correct."); m->mothurOutEndLine(); 
196                         delete chimera;
197                         return 0; 
198                 }
199                 templateSeqsLength = chimera->getLength();
200                 
201         #ifdef USE_MPI  
202                 int pid, end, numSeqsPerProcessor; 
203                         int tag = 2001;
204                         vector<long> MPIPos;
205                         MPIWroteAccnos = false;
206                         
207                         MPI_Status status; 
208                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
209                         MPI_Comm_size(MPI_COMM_WORLD, &processors); 
210
211                         MPI_File inMPI;
212                         MPI_File outMPI;
213                         MPI_File outMPIAccnos;
214                         
215                         int outMode=MPI_MODE_CREATE|MPI_MODE_WRONLY; 
216                         int inMode=MPI_MODE_RDONLY; 
217                         
218                         //char* outFilename = new char[outputFileName.length()];
219                         //memcpy(outFilename, outputFileName.c_str(), outputFileName.length());
220                         
221                         char outFilename[1024];
222                         strcpy(outFilename, outputFileName.c_str());
223                         
224                         //char* outAccnosFilename = new char[accnosFileName.length()];
225                         //memcpy(outAccnosFilename, accnosFileName.c_str(), accnosFileName.length());
226                         
227                         char outAccnosFilename[1024];
228                         strcpy(outAccnosFilename, accnosFileName.c_str());
229
230                         //char* inFileName = new char[fastafile.length()];
231                         //memcpy(inFileName, fastafile.c_str(), fastafile.length());
232                         
233                         char inFileName[1024];
234                         strcpy(inFileName, fastafile.c_str());
235
236                         MPI_File_open(MPI_COMM_WORLD, inFileName, inMode, MPI_INFO_NULL, &inMPI);  //comm, filename, mode, info, filepointer
237                         MPI_File_open(MPI_COMM_WORLD, outFilename, outMode, MPI_INFO_NULL, &outMPI);
238                         MPI_File_open(MPI_COMM_WORLD, outAccnosFilename, outMode, MPI_INFO_NULL, &outMPIAccnos);
239                         
240                         //delete inFileName;
241                         //delete outFilename;
242                         //delete outAccnosFilename;
243
244                         if (m->control_pressed) {  MPI_File_close(&inMPI);  MPI_File_close(&outMPI);   MPI_File_close(&outMPIAccnos);  delete chimera; return 0;  }
245                 
246                         if (pid == 0) { //you are the root process 
247                                 m->mothurOutEndLine();
248                                 m->mothurOut("Only reporting sequence supported by " + toString(minBS) + "% of bootstrapped results.");
249                                 m->mothurOutEndLine();
250         
251                                 string outTemp = "Name\tLeftParent\tRightParent\tDivQLAQRB\tPerIDQLAQRB\tBootStrapA\tDivQLBQRA\tPerIDQLBQRA\tBootStrapB\tFlag\tLeftWindow\tRightWindow\n";
252                                 
253                                 //print header
254                                 int length = outTemp.length();
255                                 char* buf2 = new char[length];
256                                 memcpy(buf2, outTemp.c_str(), length);
257
258                                 MPI_File_write_shared(outMPI, buf2, length, MPI_CHAR, &status);
259                                 delete buf2;
260
261                                 MPIPos = setFilePosFasta(fastafile, numSeqs); //fills MPIPos, returns numSeqs
262                                 
263                                 //send file positions to all processes
264                                 for(int i = 1; i < processors; i++) { 
265                                         MPI_Send(&numSeqs, 1, MPI_INT, i, tag, MPI_COMM_WORLD);
266                                         MPI_Send(&MPIPos[0], (numSeqs+1), MPI_LONG, i, tag, MPI_COMM_WORLD);
267                                 }
268                                 
269                                 //figure out how many sequences you have to align
270                                 numSeqsPerProcessor = numSeqs / processors;
271                                 int startIndex =  pid * numSeqsPerProcessor;
272                                 if(pid == (processors - 1)){    numSeqsPerProcessor = numSeqs - pid * numSeqsPerProcessor;      }
273                                 
274                         
275                                 //align your part
276                                 driverMPI(startIndex, numSeqsPerProcessor, inMPI, outMPI, outMPIAccnos, MPIPos);
277                                 
278                                 if (m->control_pressed) {  MPI_File_close(&inMPI);  MPI_File_close(&outMPI);   MPI_File_close(&outMPIAccnos);  remove(outputFileName.c_str());  remove(accnosFileName.c_str());  delete chimera; return 0;  }
279
280                                 for (int i = 1; i < processors; i++) {
281                                         bool tempResult;
282                                         MPI_Recv(&tempResult, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &status);
283                                         if (tempResult != 0) { MPIWroteAccnos = true; }
284                                 }
285                         }else{ //you are a child process
286                                 MPI_Recv(&numSeqs, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &status);
287                                 MPIPos.resize(numSeqs+1);
288                                 MPI_Recv(&MPIPos[0], (numSeqs+1), MPI_LONG, 0, tag, MPI_COMM_WORLD, &status);
289                                 
290                                 //figure out how many sequences you have to align
291                                 numSeqsPerProcessor = numSeqs / processors;
292                                 int startIndex =  pid * numSeqsPerProcessor;
293                                 if(pid == (processors - 1)){    numSeqsPerProcessor = numSeqs - pid * numSeqsPerProcessor;      }
294                                 
295                                 
296                                 //align your part
297                                 driverMPI(startIndex, numSeqsPerProcessor, inMPI, outMPI, outMPIAccnos, MPIPos);
298                                 
299                                 if (m->control_pressed) {  MPI_File_close(&inMPI);  MPI_File_close(&outMPI);   MPI_File_close(&outMPIAccnos);  delete chimera; return 0;  }
300
301                                 MPI_Send(&MPIWroteAccnos, 1, MPI_INT, 0, tag, MPI_COMM_WORLD); 
302                         }
303                         
304                         //close files 
305                         MPI_File_close(&inMPI);
306                         MPI_File_close(&outMPI);
307                         MPI_File_close(&outMPIAccnos);
308                         MPI_Barrier(MPI_COMM_WORLD); //make everyone wait - just in case
309                         
310                         //delete accnos file if blank
311                         if (pid == 0) {
312                                 if (!MPIWroteAccnos) { 
313                                         //MPI_Info info;
314                                         //MPI_File_delete(outAccnosFilename, info);
315                                         hasAccnos = false;      
316                                         remove(accnosFileName.c_str()); 
317                                 }
318                         }
319                 
320         #else
321                 ofstream outHeader;
322                 string tempHeader = outputDir + getRootName(getSimpleName(fastafile)) + "slayer.chimeras.tempHeader";
323                 openOutputFile(tempHeader, outHeader);
324                 
325                 chimera->printHeader(outHeader);
326                 outHeader.close();
327                 
328                 //break up file
329                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
330                         if(processors == 1){
331                                 ifstream inFASTA;
332                                 openInputFile(fastafile, inFASTA);
333                                 numSeqs=count(istreambuf_iterator<char>(inFASTA),istreambuf_iterator<char>(), '>');
334                                 inFASTA.close();
335                                 
336                                 lines.push_back(new linePair(0, numSeqs));
337                                 
338                                 driver(lines[0], outputFileName, fastafile, accnosFileName);
339                                 
340                                 if (m->control_pressed) { 
341                                         remove(outputFileName.c_str()); 
342                                         remove(tempHeader.c_str()); 
343                                         remove(accnosFileName.c_str());
344                                         for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
345                                         delete chimera;
346                                         return 0;
347                                 }
348                                 
349                                 //delete accnos file if its blank 
350                                 if (isBlank(accnosFileName)) {  remove(accnosFileName.c_str());  hasAccnos = false; }
351                                                                 
352                         }else{
353                                 vector<int> positions;
354                                 processIDS.resize(0);
355                                 
356                                 ifstream inFASTA;
357                                 openInputFile(fastafile, inFASTA);
358                                 
359                                 string input;
360                                 while(!inFASTA.eof()){
361                                         input = getline(inFASTA);
362                                         if (input.length() != 0) {
363                                                 if(input[0] == '>'){    long int pos = inFASTA.tellg(); positions.push_back(pos - input.length() - 1);  }
364                                         }
365                                 }
366                                 inFASTA.close();
367                                 
368                                 numSeqs = positions.size();
369                                 
370                                 int numSeqsPerProcessor = numSeqs / processors;
371                                 
372                                 for (int i = 0; i < processors; i++) {
373                                         long int startPos = positions[ i * numSeqsPerProcessor ];
374                                         if(i == processors - 1){
375                                                 numSeqsPerProcessor = numSeqs - i * numSeqsPerProcessor;
376                                         }
377                                         lines.push_back(new linePair(startPos, numSeqsPerProcessor));
378                                 }
379                                 
380                                 
381                                 createProcesses(outputFileName, fastafile, accnosFileName); 
382                         
383                                 rename((outputFileName + toString(processIDS[0]) + ".temp").c_str(), outputFileName.c_str());
384                                         
385                                 //append output files
386                                 for(int i=1;i<processors;i++){
387                                         appendFiles((outputFileName + toString(processIDS[i]) + ".temp"), outputFileName);
388                                         remove((outputFileName + toString(processIDS[i]) + ".temp").c_str());
389                                 }
390                                 
391                                 vector<string> nonBlankAccnosFiles;
392                                 //delete blank accnos files generated with multiple processes
393                                 for(int i=0;i<processors;i++){  
394                                         if (!(isBlank(accnosFileName + toString(processIDS[i]) + ".temp"))) {
395                                                 nonBlankAccnosFiles.push_back(accnosFileName + toString(processIDS[i]) + ".temp");
396                                         }else { remove((accnosFileName + toString(processIDS[i]) + ".temp").c_str());  }
397                                 }
398                                 
399                                 //append accnos files
400                                 if (nonBlankAccnosFiles.size() != 0) { 
401                                         rename(nonBlankAccnosFiles[0].c_str(), accnosFileName.c_str());
402                                         
403                                         for (int h=1; h < nonBlankAccnosFiles.size(); h++) {
404                                                 appendFiles(nonBlankAccnosFiles[h], accnosFileName);
405                                                 remove(nonBlankAccnosFiles[h].c_str());
406                                         }
407                                 }else{ hasAccnos = false;  }
408                                 
409                                 if (m->control_pressed) { 
410                                         remove(outputFileName.c_str()); 
411                                         remove(accnosFileName.c_str());
412                                         for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
413                                         delete chimera;
414                                         return 0;
415                                 }
416
417                         }
418
419                 #else
420                         ifstream inFASTA;
421                         openInputFile(fastafile, inFASTA);
422                         numSeqs=count(istreambuf_iterator<char>(inFASTA),istreambuf_iterator<char>(), '>');
423                         inFASTA.close();
424                         lines.push_back(new linePair(0, numSeqs));
425                         
426                         driver(lines[0], outputFileName, fastafile, accnosFileName);
427                         
428                         if (m->control_pressed) { 
429                                         remove(outputFileName.c_str()); 
430                                         remove(tempHeader.c_str()); 
431                                         remove(accnosFileName.c_str());
432                                         for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
433                                         delete chimera;
434                                         return 0;
435                         }
436                         
437                         //delete accnos file if its blank 
438                         if (isBlank(accnosFileName)) {  remove(accnosFileName.c_str());  hasAccnos = false; }
439                 #endif
440                 
441                 appendFiles(outputFileName, tempHeader);
442         
443                 remove(outputFileName.c_str());
444                 rename(tempHeader.c_str(), outputFileName.c_str());
445                 
446         #endif
447                 delete chimera;
448                 
449                 m->mothurOutEndLine();
450                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
451                 m->mothurOut(outputFileName); m->mothurOutEndLine();    
452                 if (hasAccnos) {  m->mothurOut(accnosFileName); m->mothurOutEndLine();  }
453                 m->mothurOutEndLine();
454
455                 for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
456                 
457                 m->mothurOutEndLine(); m->mothurOut("It took " + toString(time(NULL) - start) + " secs to check " + toString(numSeqs) + " sequences."); m->mothurOutEndLine();
458                 
459                 return 0;
460                 
461         }
462         catch(exception& e) {
463                 m->errorOut(e, "ChimeraSlayerCommand", "execute");
464                 exit(1);
465         }
466 }
467 //**********************************************************************************************************************
468
469 int ChimeraSlayerCommand::driver(linePair* line, string outputFName, string filename, string accnos){
470         try {
471                 ofstream out;
472                 openOutputFile(outputFName, out);
473                 
474                 ofstream out2;
475                 openOutputFile(accnos, out2);
476                 
477                 ifstream inFASTA;
478                 openInputFile(filename, inFASTA);
479
480                 inFASTA.seekg(line->start);
481                 
482                 for(int i=0;i<line->numSeqs;i++){
483                 
484                         if (m->control_pressed) {       return 1;       }
485                 
486                         Sequence* candidateSeq = new Sequence(inFASTA);  gobble(inFASTA);
487                                 
488                         if (candidateSeq->getName() != "") { //incase there is a commented sequence at the end of a file
489                                 
490                                 if (candidateSeq->getAligned().length() != templateSeqsLength) {  
491                                         m->mothurOut(candidateSeq->getName() + " is not the same length as the template sequences. Skipping."); m->mothurOutEndLine();
492                                 }else{
493                                         //find chimeras
494                                         chimera->getChimeras(candidateSeq);
495                                         
496                                         if (m->control_pressed) {       delete candidateSeq; return 1;  }
497                 
498                                         //print results
499                                         chimera->print(out, out2);
500                                 }
501                         }
502                         delete candidateSeq;
503                         
504                         //report progress
505                         if((i+1) % 100 == 0){   m->mothurOut("Processing sequence: " + toString(i+1)); m->mothurOutEndLine();           }
506                 }
507                 //report progress
508                 if((line->numSeqs) % 100 != 0){ m->mothurOut("Processing sequence: " + toString(line->numSeqs)); m->mothurOutEndLine();         }
509                 
510                 out.close();
511                 out2.close();
512                 inFASTA.close();
513                                 
514                 return 0;
515         }
516         catch(exception& e) {
517                 m->errorOut(e, "ChimeraSlayerCommand", "driver");
518                 exit(1);
519         }
520 }
521 //**********************************************************************************************************************
522 #ifdef USE_MPI
523 int ChimeraSlayerCommand::driverMPI(int start, int num, MPI_File& inMPI, MPI_File& outMPI, MPI_File& outAccMPI, vector<long>& MPIPos){
524         try {                           
525                 MPI_Status status; 
526                 int pid;
527                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
528                 
529                 for(int i=0;i<num;i++){
530                         
531                         if (m->control_pressed) {       return 1;       }
532                         
533                         //read next sequence
534                         int length = MPIPos[start+i+1] - MPIPos[start+i];
535
536                         char* buf4 = new char[length];
537                         MPI_File_read_at(inMPI, MPIPos[start+i], buf4, length, MPI_CHAR, &status);
538         
539                         string tempBuf = buf4;
540                         if (tempBuf.length() > length) { tempBuf = tempBuf.substr(0, length);  }
541                         istringstream iss (tempBuf,istringstream::in);
542
543                         delete buf4;
544
545                         Sequence* candidateSeq = new Sequence(iss);  gobble(iss);
546                 
547                         if (candidateSeq->getName() != "") { //incase there is a commented sequence at the end of a file
548                                 
549                                 if (candidateSeq->getAligned().length() != templateSeqsLength) {  
550                                         m->mothurOut(candidateSeq->getName() + " is not the same length as the template sequences. Skipping."); m->mothurOutEndLine();
551                                 }else{
552                 
553                                         //find chimeras
554                                         chimera->getChimeras(candidateSeq);
555                         
556                                         if (m->control_pressed) {       delete candidateSeq; return 1;  }
557                 //cout << "about to print" << endl;
558                                         //print results
559                                         bool isChimeric = chimera->print(outMPI, outAccMPI);
560                                         if (isChimeric) { MPIWroteAccnos = true;  }
561         
562                                 }
563                         }
564                         delete candidateSeq;
565                         
566                         //report progress
567                         if((i+1) % 100 == 0){  cout << "Processing sequence: " << (i+1) << endl;        m->mothurOutJustToLog("Processing sequence: " + toString(i+1) + "\n");          }
568                 }
569                 //report progress
570                 if(num % 100 != 0){             cout << "Processing sequence: " << num << endl; m->mothurOutJustToLog("Processing sequence: " + toString(num) + "\n");  }
571                 
572                                 
573                 return 0;
574         }
575         catch(exception& e) {
576                 m->errorOut(e, "ChimeraSlayerCommand", "driverMPI");
577                 exit(1);
578         }
579 }
580 #endif
581
582 /**************************************************************************************************/
583
584 int ChimeraSlayerCommand::createProcesses(string outputFileName, string filename, string accnos) {
585         try {
586 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
587                 int process = 0;
588                 //              processIDS.resize(0);
589                 
590                 //loop through and create all the processes you want
591                 while (process != processors) {
592                         int pid = fork();
593                         
594                         if (pid > 0) {
595                                 processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
596                                 process++;
597                         }else if (pid == 0){
598                                 driver(lines[process], outputFileName + toString(getpid()) + ".temp", filename, accnos + toString(getpid()) + ".temp");
599                                 exit(0);
600                         }else { m->mothurOut("unable to spawn the necessary processes."); m->mothurOutEndLine(); exit(0); }
601                 }
602                 
603                 //force parent to wait until all the processes are done
604                 for (int i=0;i<processors;i++) { 
605                         int temp = processIDS[i];
606                         wait(&temp);
607                 }
608                 
609                 return 0;
610 #endif          
611         }
612         catch(exception& e) {
613                 m->errorOut(e, "ChimeraSlayerCommand", "createProcesses");
614                 exit(1);
615         }
616 }
617
618 /**************************************************************************************************/
619
620