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