]> git.donarmstrong.com Git - mothur.git/blob - chimerapintailcommand.cpp
some changes while testing 1.9
[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=1/4 sequence length. \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                 chimera = new Pintail(fastafile, templatefile, filter, processors, maskfile, consfile, quanfile, window, increment, outputDir);
179                 
180                 //set user options
181                 if (maskfile == "default") { m->mothurOut("I am using the default 236627 EU009184.1 Shigella dysenteriae str. FBD013."); m->mothurOutEndLine();  }
182                 
183
184                 string outputFileName, accnosFileName;
185                 if (maskfile != "") {
186                         outputFileName = outputDir + getRootName(getSimpleName(fastafile)) + maskfile + ".pintail.chimeras";
187                         accnosFileName = outputDir + getRootName(getSimpleName(fastafile)) + maskfile + ".pintail.accnos";
188                 }else {
189                         outputFileName = outputDir + getRootName(getSimpleName(fastafile))  + "pintail.chimeras";
190                         accnosFileName = outputDir + getRootName(getSimpleName(fastafile))  + "pintail.accnos";
191                 }
192                 bool hasAccnos = true;
193                 
194                 if (m->control_pressed) { delete chimera;       return 0;       }
195                 
196                 if (chimera->getUnaligned()) { 
197                         m->mothurOut("Your template sequences are different lengths, please correct."); m->mothurOutEndLine(); 
198                         delete chimera;
199                         return 0; 
200                 }
201                 templateSeqsLength = chimera->getLength();
202         
203         #ifdef USE_MPI
204                 int pid, end, numSeqsPerProcessor; 
205                         int tag = 2001;
206                         vector<long> MPIPos;
207                         MPIWroteAccnos = false;
208                         
209                         MPI_Status status; 
210                         MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
211                         MPI_Comm_size(MPI_COMM_WORLD, &processors); 
212
213                         MPI_File inMPI;
214                         MPI_File outMPI;
215                         MPI_File outMPIAccnos;
216                         
217                         int outMode=MPI_MODE_CREATE|MPI_MODE_WRONLY; 
218                         int inMode=MPI_MODE_RDONLY; 
219                                                         
220                         char outFilename[outputFileName.length()];
221                         strcpy(outFilename, outputFileName.c_str());
222                         
223                         char outAccnosFilename[accnosFileName.length()];
224                         strcpy(outAccnosFilename, accnosFileName.c_str());
225                         
226                         char inFileName[fastafile.length()];
227                         strcpy(inFileName, fastafile.c_str());
228
229                         MPI_File_open(MPI_COMM_WORLD, inFileName, inMode, MPI_INFO_NULL, &inMPI);  //comm, filename, mode, info, filepointer
230                         MPI_File_open(MPI_COMM_WORLD, outFilename, outMode, MPI_INFO_NULL, &outMPI);
231                         MPI_File_open(MPI_COMM_WORLD, outAccnosFilename, outMode, MPI_INFO_NULL, &outMPIAccnos);
232                         
233                         if (m->control_pressed) {  MPI_File_close(&inMPI);  MPI_File_close(&outMPI);   MPI_File_close(&outMPIAccnos);  delete chimera; return 0;  }
234
235                         if (pid == 0) { //you are the root process 
236                                                         
237                                 MPIPos = setFilePosFasta(fastafile, numSeqs); //fills MPIPos, returns numSeqs
238                                 
239                                 //send file positions to all processes
240                                 MPI_Bcast(&numSeqs, 1, MPI_INT, 0, MPI_COMM_WORLD);  //send numSeqs
241                                 MPI_Bcast(&MPIPos[0], (numSeqs+1), MPI_LONG, 0, MPI_COMM_WORLD); //send file pos        
242                                 
243                                 //figure out how many sequences you have to align
244                                 numSeqsPerProcessor = numSeqs / processors;
245                                 if(pid == (processors - 1)){    numSeqsPerProcessor = numSeqs - pid * numSeqsPerProcessor;      }
246                                 int startIndex =  pid * numSeqsPerProcessor;
247                         
248                                 //align your part
249                                 driverMPI(startIndex, numSeqsPerProcessor, inMPI, outMPI, outMPIAccnos, MPIPos);
250                                 
251                                 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;  }
252                                 
253                                 for (int i = 1; i < processors; i++) {
254                                         bool tempResult;
255                                         MPI_Recv(&tempResult, 1, MPI_INT, i, tag, MPI_COMM_WORLD, &status);
256                                         if (tempResult != 0) { MPIWroteAccnos = true; }
257                                 }
258                         }else{ //you are a child process
259                                 MPI_Bcast(&numSeqs, 1, MPI_INT, 0, MPI_COMM_WORLD); //get numSeqs
260                                 MPIPos.resize(numSeqs+1);
261                                 MPI_Bcast(&MPIPos[0], (numSeqs+1), MPI_LONG, 0, MPI_COMM_WORLD); //get file positions
262                                 
263                                 //figure out how many sequences you have to align
264                                 numSeqsPerProcessor = numSeqs / processors;
265                                 if(pid == (processors - 1)){    numSeqsPerProcessor = numSeqs - pid * numSeqsPerProcessor;      }
266                                 int startIndex =  pid * numSeqsPerProcessor;
267                                 
268                                 //align your part
269                                 driverMPI(startIndex, numSeqsPerProcessor, inMPI, outMPI, outMPIAccnos, MPIPos);
270                                 
271                                 if (m->control_pressed) {  MPI_File_close(&inMPI);  MPI_File_close(&outMPI);   MPI_File_close(&outMPIAccnos);  delete chimera; return 0;  }
272
273                                 MPI_Send(&MPIWroteAccnos, 1, MPI_INT, 0, tag, MPI_COMM_WORLD); 
274                         }
275                         
276                         //close files 
277                         MPI_File_close(&inMPI);
278                         MPI_File_close(&outMPI);
279                         MPI_File_close(&outMPIAccnos);
280                         
281                         //delete accnos file if blank
282                         if (pid == 0) {
283                                 if (!MPIWroteAccnos) { 
284                                         //MPI_Info info;
285                                         //MPI_File_delete(outAccnosFilename, info);
286                                         hasAccnos = false;      
287                                         remove(accnosFileName.c_str()); 
288                                 }
289                         }
290
291         #else
292         
293                 //break up file
294                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
295                         if(processors == 1){
296                                 ifstream inFASTA;
297                                 openInputFile(fastafile, inFASTA);
298                                 numSeqs=count(istreambuf_iterator<char>(inFASTA),istreambuf_iterator<char>(), '>');
299                                 inFASTA.close();
300                                 
301                                 lines.push_back(new linePair(0, numSeqs));
302                                 
303                                 driver(lines[0], outputFileName, fastafile, accnosFileName);
304                                 
305                                 if (m->control_pressed) { 
306                                         remove(outputFileName.c_str()); 
307                                         remove(accnosFileName.c_str());
308                                         for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
309                                         delete chimera;
310                                         return 0;
311                                 }
312                                 
313                                 //delete accnos file if its blank 
314                                 if (isBlank(accnosFileName)) {  remove(accnosFileName.c_str());  hasAccnos = false; }
315                                                                 
316                         }else{
317                                 vector<int> positions;
318                                 processIDS.resize(0);
319                                 
320                                 ifstream inFASTA;
321                                 openInputFile(fastafile, inFASTA);
322                                 
323                                 string input;
324                                 while(!inFASTA.eof()){
325                                         input = getline(inFASTA);
326                                         if (input.length() != 0) {
327                                                 if(input[0] == '>'){    long int pos = inFASTA.tellg(); positions.push_back(pos - input.length() - 1);  }
328                                         }
329                                 }
330                                 inFASTA.close();
331                                 
332                                 numSeqs = positions.size();
333                                 
334                                 int numSeqsPerProcessor = numSeqs / processors;
335                                 
336                                 for (int i = 0; i < processors; i++) {
337                                         long int startPos = positions[ i * numSeqsPerProcessor ];
338                                         if(i == processors - 1){
339                                                 numSeqsPerProcessor = numSeqs - i * numSeqsPerProcessor;
340                                         }
341                                         lines.push_back(new linePair(startPos, numSeqsPerProcessor));
342                                 }
343                                 
344                                 
345                                 createProcesses(outputFileName, fastafile, accnosFileName); 
346                         
347                                 rename((outputFileName + toString(processIDS[0]) + ".temp").c_str(), outputFileName.c_str());
348                                         
349                                 //append output files
350                                 for(int i=1;i<processors;i++){
351                                         appendFiles((outputFileName + toString(processIDS[i]) + ".temp"), outputFileName);
352                                         remove((outputFileName + toString(processIDS[i]) + ".temp").c_str());
353                                 }
354                                 
355                                 vector<string> nonBlankAccnosFiles;
356                                 //delete blank accnos files generated with multiple processes
357                                 for(int i=0;i<processors;i++){  
358                                         if (!(isBlank(accnosFileName + toString(processIDS[i]) + ".temp"))) {
359                                                 nonBlankAccnosFiles.push_back(accnosFileName + toString(processIDS[i]) + ".temp");
360                                         }else { remove((accnosFileName + toString(processIDS[i]) + ".temp").c_str());  }
361                                 }
362                                 
363                                 //append accnos files
364                                 if (nonBlankAccnosFiles.size() != 0) { 
365                                         rename(nonBlankAccnosFiles[0].c_str(), accnosFileName.c_str());
366                                         
367                                         for (int h=1; h < nonBlankAccnosFiles.size(); h++) {
368                                                 appendFiles(nonBlankAccnosFiles[h], accnosFileName);
369                                                 remove(nonBlankAccnosFiles[h].c_str());
370                                         }
371                                 }else{ hasAccnos = false;  }
372                                 
373                                 if (m->control_pressed) { 
374                                         remove(outputFileName.c_str()); 
375                                         remove(accnosFileName.c_str());
376                                         for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
377                                         delete chimera;
378                                         return 0;
379                                 }
380                         }
381
382                 #else
383                         ifstream inFASTA;
384                         openInputFile(fastafile, inFASTA);
385                         numSeqs=count(istreambuf_iterator<char>(inFASTA),istreambuf_iterator<char>(), '>');
386                         inFASTA.close();
387                         lines.push_back(new linePair(0, numSeqs));
388                         
389                         driver(lines[0], outputFileName, fastafile, accnosFileName);
390                         
391                         if (m->control_pressed) { 
392                                         remove(outputFileName.c_str()); 
393                                         remove(accnosFileName.c_str());
394                                         for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
395                                         delete chimera;
396                                         return 0;
397                         }
398                         
399                         //delete accnos file if its blank 
400                         if (isBlank(accnosFileName)) {  remove(accnosFileName.c_str());  hasAccnos = false; }
401                 #endif
402                 
403         #endif  
404         
405                 delete chimera;
406                 for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
407                 
408                 m->mothurOutEndLine();
409                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
410                 m->mothurOut(outputFileName); m->mothurOutEndLine();    
411                 if (hasAccnos) {  m->mothurOut(accnosFileName); m->mothurOutEndLine();  }
412                 m->mothurOutEndLine();
413                 m->mothurOutEndLine(); m->mothurOut("It took " + toString(time(NULL) - start) + " secs to check " + toString(numSeqs) + " sequences."); m->mothurOutEndLine();
414                 
415                 return 0;
416                 
417         }
418         catch(exception& e) {
419                 m->errorOut(e, "ChimeraPintailCommand", "execute");
420                 exit(1);
421         }
422 }
423 //**********************************************************************************************************************
424
425 int ChimeraPintailCommand::driver(linePair* line, string outputFName, string filename, string accnos){
426         try {
427                 ofstream out;
428                 openOutputFile(outputFName, out);
429                 
430                 ofstream out2;
431                 openOutputFile(accnos, out2);
432                 
433                 ifstream inFASTA;
434                 openInputFile(filename, inFASTA);
435
436                 inFASTA.seekg(line->start);
437                 
438                 for(int i=0;i<line->numSeqs;i++){
439                 
440                         if (m->control_pressed) {       return 1;       }
441                 
442                         Sequence* candidateSeq = new Sequence(inFASTA);  gobble(inFASTA);
443                                 
444                         if (candidateSeq->getName() != "") { //incase there is a commented sequence at the end of a file
445                                 
446                                 if (candidateSeq->getAligned().length() != templateSeqsLength)  {  //chimeracheck does not require seqs to be aligned
447                                         m->mothurOut(candidateSeq->getName() + " is not the same length as the template sequences. Skipping."); m->mothurOutEndLine();
448                                 }else{
449                                         //find chimeras
450                                         chimera->getChimeras(candidateSeq);
451                                         
452                                         if (m->control_pressed) {       delete candidateSeq; return 1;  }
453                 
454                                         //print results
455                                         chimera->print(out, out2);
456                                 }
457                         }
458                         delete candidateSeq;
459                         
460                         //report progress
461                         if((i+1) % 100 == 0){   m->mothurOut("Processing sequence: " + toString(i+1)); m->mothurOutEndLine();           }
462                 }
463                 //report progress
464                 if((line->numSeqs) % 100 != 0){ m->mothurOut("Processing sequence: " + toString(line->numSeqs)); m->mothurOutEndLine();         }
465                 
466                 out.close();
467                 out2.close();
468                 inFASTA.close();
469                                 
470                 return 0;
471         }
472         catch(exception& e) {
473                 m->errorOut(e, "ChimeraPintailCommand", "driver");
474                 exit(1);
475         }
476 }
477 //**********************************************************************************************************************
478 #ifdef USE_MPI
479 int ChimeraPintailCommand::driverMPI(int start, int num, MPI_File& inMPI, MPI_File& outMPI, MPI_File& outAccMPI, vector<long>& MPIPos){
480         try {
481                                 
482                 MPI_Status status; 
483                 int pid;
484                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
485                 
486                 for(int i=0;i<num;i++){
487                         
488                         if (m->control_pressed) {       return 1;       }
489                         
490                         //read next sequence
491                         int length = MPIPos[start+i+1] - MPIPos[start+i];
492         
493                         char buf4[length];
494                         MPI_File_read_at(inMPI, MPIPos[start+i], buf4, length, MPI_CHAR, &status);
495                         
496                         string tempBuf = buf4;
497                         if (tempBuf.length() > length) { tempBuf = tempBuf.substr(0, length);  }
498                         istringstream iss (tempBuf,istringstream::in);
499
500                         Sequence* candidateSeq = new Sequence(iss);  gobble(iss);
501                                 
502                         if (candidateSeq->getName() != "") { //incase there is a commented sequence at the end of a file
503                                 
504                                 if      (candidateSeq->getAligned().length() != templateSeqsLength) {  //chimeracheck does not require seqs to be aligned
505                                         m->mothurOut(candidateSeq->getName() + " is not the same length as the template sequences. Skipping."); m->mothurOutEndLine();
506                                 }else{
507                                         //find chimeras
508                                         chimera->getChimeras(candidateSeq);
509                                         
510                                         if (m->control_pressed) {       delete candidateSeq; return 1;  }
511                 
512                                         //print results
513                                         bool isChimeric = chimera->print(outMPI, outAccMPI);
514                                         if (isChimeric) { MPIWroteAccnos = true;  }
515                                 }
516                         }
517                         delete candidateSeq;
518                         
519                         //report progress
520                         if((i+1) % 100 == 0){  cout << "Processing sequence: " << (i+1) << endl;        m->mothurOutJustToLog("Processing sequence: " + toString(i+1) + "\n");          }
521                 }
522                 //report progress
523                 if(num % 100 != 0){             cout << "Processing sequence: " << num << endl; m->mothurOutJustToLog("Processing sequence: " + toString(num) + "\n");  }
524                 
525                                 
526                 return 0;
527         }
528         catch(exception& e) {
529                 m->errorOut(e, "ChimeraPintailCommand", "driverMPI");
530                 exit(1);
531         }
532 }
533 #endif
534
535 /**************************************************************************************************/
536
537 int ChimeraPintailCommand::createProcesses(string outputFileName, string filename, string accnos) {
538         try {
539 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
540                 int process = 0;
541                 //              processIDS.resize(0);
542                 
543                 //loop through and create all the processes you want
544                 while (process != processors) {
545                         int pid = fork();
546                         
547                         if (pid > 0) {
548                                 processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
549                                 process++;
550                         }else if (pid == 0){
551                                 driver(lines[process], outputFileName + toString(getpid()) + ".temp", filename, accnos + toString(getpid()) + ".temp");
552                                 exit(0);
553                         }else { m->mothurOut("unable to spawn the necessary processes."); m->mothurOutEndLine(); exit(0); }
554                 }
555                 
556                 //force parent to wait until all the processes are done
557                 for (int i=0;i<processors;i++) { 
558                         int temp = processIDS[i];
559                         wait(&temp);
560                 }
561                 
562                 return 0;
563 #endif          
564         }
565         catch(exception& e) {
566                 m->errorOut(e, "ChimeraPintailCommand", "createProcesses");
567                 exit(1);
568         }
569 }
570
571 /**************************************************************************************************/
572
573