]> git.donarmstrong.com Git - mothur.git/blob - chimeraccodecommand.cpp
fixes while testing 1.33.0
[mothur.git] / chimeraccodecommand.cpp
1 /*
2  *  chimeraccodecommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 3/30/10.
6  *  Copyright 2010 Schloss Lab. All rights reserved.
7  *
8  */
9
10 #include "chimeraccodecommand.h"
11 #include "ccode.h"
12 #include "referencedb.h"
13 //**********************************************************************************************************************
14 vector<string> ChimeraCcodeCommand::setParameters(){    
15         try {
16                 CommandParameter ptemplate("reference", "InputTypes", "", "", "none", "none", "none","",false,true,true); parameters.push_back(ptemplate);
17                 CommandParameter pfasta("fasta", "InputTypes", "", "", "none", "none", "none","chimera-mapinfo-accnos",false,true,true); parameters.push_back(pfasta);
18                 CommandParameter pfilter("filter", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(pfilter);
19                 CommandParameter pwindow("window", "Number", "", "0", "", "", "","",false,false); parameters.push_back(pwindow);
20                 CommandParameter pnumwanted("numwanted", "Number", "", "20", "", "", "","",false,false); parameters.push_back(pnumwanted);
21                 CommandParameter pmask("mask", "String", "", "", "", "", "","",false,false); parameters.push_back(pmask);
22                 CommandParameter pprocessors("processors", "Number", "", "1", "", "", "","",false,false,true); parameters.push_back(pprocessors);
23                 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
24                 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
25                 CommandParameter psave("save", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(psave);
26                 
27                 vector<string> myArray;
28                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
29                 return myArray;
30         }
31         catch(exception& e) {
32                 m->errorOut(e, "ChimeraCcodeCommand", "setParameters");
33                 exit(1);
34         }
35 }
36 //**********************************************************************************************************************
37 string ChimeraCcodeCommand::getHelpString(){    
38         try {
39                 string helpString = "";
40                 helpString += "The chimera.ccode command reads a fastafile and referencefile and outputs potentially chimeric sequences.\n";
41                 helpString += "This command was created using the algorithms described in the 'Evaluating putative chimeric sequences from PCR-amplified products' paper by Juan M. Gonzalez, Johannes Zimmerman and Cesareo Saiz-Jimenez.\n";
42                 helpString += "The chimera.ccode command parameters are fasta, reference, filter, mask, processors, window and numwanted.\n";
43                 helpString += "The fasta parameter allows you to enter the fasta file containing your potentially chimeric sequences, and is required unless you have a valid current fasta file. \n";
44                 helpString += "You may enter multiple fasta files by separating their names with dashes. ie. fasta=abrecovery.fasta-amzon.fasta \n";
45                 helpString += "The reference parameter allows you to enter a reference file containing known non-chimeric sequences, and is required. \n";
46                 helpString += "The filter parameter allows you to specify if you would like to apply a vertical and 50% soft filter. \n";
47                 helpString += "The processors parameter allows you to specify how many processors you would like to use.  The default is 1. \n";
48 #ifdef USE_MPI
49                 helpString += "When using MPI, the processors parameter is set to the number of MPI processes running. \n";
50 #endif
51                 helpString += "The mask parameter allows you to specify a file containing one sequence you wish to use as a mask for the your sequences. \n";
52                 helpString += "The window parameter allows you to specify the window size for searching for chimeras. \n";
53                 helpString += "The numwanted parameter allows you to specify how many sequences you would each query sequence compared with.\n";
54                 helpString += "If the save parameter is set to true the reference sequences will be saved in memory, to clear them later you can use the clear.memory command. Default=f.";
55                 helpString += "The chimera.ccode command should be in the following format: \n";
56                 helpString += "chimera.ccode(fasta=yourFastaFile, reference=yourTemplate) \n";
57                 helpString += "Example: chimera.ccode(fasta=AD.align, reference=core_set_aligned.imputed.fasta) \n";
58                 helpString += "Note: No spaces between parameter labels (i.e. fasta), '=' and parameters (i.e.yourFastaFile).\n";       
59                 return helpString;
60         }
61         catch(exception& e) {
62                 m->errorOut(e, "ChimeraCcodeCommand", "getHelpString");
63                 exit(1);
64         }
65 }
66 //**********************************************************************************************************************
67 string ChimeraCcodeCommand::getOutputPattern(string type) {
68     try {
69         string pattern = "";
70         
71         if (type == "chimera") {  pattern = "[filename],[tag],ccode.chimeras-[filename],ccode.chimeras"; } 
72         else if (type == "accnos") {  pattern = "[filename],[tag],ccode.accnos-[filename],ccode.accnos"; } 
73         else if (type == "mapinfo") {  pattern =  "[filename],mapinfo"; }
74         else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true;  }
75         
76         return pattern;
77     }
78     catch(exception& e) {
79         m->errorOut(e, "ChimeraCcodeCommand", "getOutputPattern");
80         exit(1);
81     }
82 }
83 //**********************************************************************************************************************
84 ChimeraCcodeCommand::ChimeraCcodeCommand(){     
85         try {
86                 abort = true; calledHelp = true;
87                 setParameters();
88                 vector<string> tempOutNames;
89                 outputTypes["chimera"] = tempOutNames;
90                 outputTypes["mapinfo"] = tempOutNames;
91                 outputTypes["accnos"] = tempOutNames;
92         
93         }
94         catch(exception& e) {
95                 m->errorOut(e, "ChimeraCcodeCommand", "ChimeraCcodeCommand");
96                 exit(1);
97         }
98 }
99 //***************************************************************************************************************
100 ChimeraCcodeCommand::ChimeraCcodeCommand(string option)  {
101         try {
102                 abort = false; calledHelp = false;   
103                 ReferenceDB* rdb = ReferenceDB::getInstance();
104                 
105                 //allow user to run help
106                 if(option == "help") { help(); abort = true; calledHelp = true; }
107                 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
108                 
109                 else {
110                         vector<string> myArray = setParameters();
111                         
112                         OptionParser parser(option);
113                         map<string,string> parameters = parser.getParameters();
114                         
115                         ValidParameters validParameter("chimera.ccode");
116                         map<string,string>::iterator it;
117                         
118                         //check to make sure all parameters are valid for command
119                         for (it = parameters.begin(); it != parameters.end(); it++) { 
120                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
121                         }
122                         
123                         vector<string> tempOutNames;
124                         outputTypes["chimera"] = tempOutNames;
125                         outputTypes["mapinfo"] = tempOutNames;
126                         outputTypes["accnos"] = tempOutNames;
127             
128                         
129                         //if the user changes the input directory command factory will send this info to us in the output parameter 
130                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
131                         if (inputDir == "not found"){   inputDir = "";          }
132                         else {
133                                 string path;
134                                 it = parameters.find("reference");
135                                 //user has given a template file
136                                 if(it != parameters.end()){ 
137                                         path = m->hasPath(it->second);
138                                         //if the user has not given a path then, add inputdir. else leave path alone.
139                                         if (path == "") {       parameters["reference"] = inputDir + it->second;                }
140                                 }
141                         }
142
143                         //check for required parameters
144                         fastafile = validParameter.validFile(parameters, "fasta", false);
145                         if (fastafile == "not found") {                                 //if there is a current fasta file, use it
146                                 string filename = m->getFastaFile(); 
147                                 if (filename != "") { fastaFileNames.push_back(filename); m->mothurOut("Using " + filename + " as input file for the fasta parameter."); m->mothurOutEndLine(); }
148                                 else {  m->mothurOut("You have no current fastafile and the fasta parameter is required."); m->mothurOutEndLine(); abort = true; }
149                         }else { 
150                                 m->splitAtDash(fastafile, fastaFileNames);
151                                 
152                                 //go through files and make sure they are good, if not, then disregard them
153                                 for (int i = 0; i < fastaFileNames.size(); i++) {
154                                         
155                                         bool ignore = false;
156                                         if (fastaFileNames[i] == "current") { 
157                                                 fastaFileNames[i] = m->getFastaFile(); 
158                                                 if (fastaFileNames[i] != "") {  m->mothurOut("Using " + fastaFileNames[i] + " as input file for the fasta parameter where you had given current."); m->mothurOutEndLine(); }
159                                                 else {  
160                                                         m->mothurOut("You have no current fastafile, ignoring current."); m->mothurOutEndLine(); ignore=true; 
161                                                         //erase from file list
162                                                         fastaFileNames.erase(fastaFileNames.begin()+i);
163                                                         i--;
164                                                 }
165                                         }
166                                         
167                                         if (!ignore) {
168                                         
169                                                 if (inputDir != "") {
170                                                         string path = m->hasPath(fastaFileNames[i]);
171                                                         //if the user has not given a path then, add inputdir. else leave path alone.
172                                                         if (path == "") {       fastaFileNames[i] = inputDir + fastaFileNames[i];               }
173                                                 }
174                 
175                                                 int ableToOpen;
176                                                 ifstream in;
177                                                 
178                                                 ableToOpen = m->openInputFile(fastaFileNames[i], in, "noerror");
179                                         
180                                                 //if you can't open it, try default location
181                                                 if (ableToOpen == 1) {
182                                                         if (m->getDefaultPath() != "") { //default path is set
183                                                                 string tryPath = m->getDefaultPath() + m->getSimpleName(fastaFileNames[i]);
184                                                                 m->mothurOut("Unable to open " + fastaFileNames[i] + ". Trying default " + tryPath); m->mothurOutEndLine();
185                                                                 ifstream in2;
186                                                                 ableToOpen = m->openInputFile(tryPath, in2, "noerror");
187                                                                 in2.close();
188                                                                 fastaFileNames[i] = tryPath;
189                                                         }
190                                                 }
191                                                 
192                                                 //if you can't open it, try default location
193                                                 if (ableToOpen == 1) {
194                                                         if (m->getOutputDir() != "") { //default path is set
195                                                                 string tryPath = m->getOutputDir() + m->getSimpleName(fastaFileNames[i]);
196                                                                 m->mothurOut("Unable to open " + fastaFileNames[i] + ". Trying output directory " + tryPath); m->mothurOutEndLine();
197                                                                 ifstream in2;
198                                                                 ableToOpen = m->openInputFile(tryPath, in2, "noerror");
199                                                                 in2.close();
200                                                                 fastaFileNames[i] = tryPath;
201                                                         }
202                                                 }
203                                                 
204                                                 in.close();
205                                                 
206                                                 if (ableToOpen == 1) { 
207                                                         m->mothurOut("Unable to open " + fastaFileNames[i] + ". It will be disregarded."); m->mothurOutEndLine(); 
208                                                         //erase from file list
209                                                         fastaFileNames.erase(fastaFileNames.begin()+i);
210                                                         i--;
211                                                 }else {
212                                                         m->setFastaFile(fastaFileNames[i]);
213                                                 }
214                                         }
215                                 }
216                                 
217                                 //make sure there is at least one valid file left
218                                 if (fastaFileNames.size() == 0) { m->mothurOut("no valid files."); m->mothurOutEndLine(); abort = true; }
219                         }
220                         
221                         //if the user changes the output directory command factory will send this info to us in the output parameter 
222                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = ""; }
223                         
224                         maskfile = validParameter.validFile(parameters, "mask", false);
225                         if (maskfile == "not found") { maskfile = "";  }        
226                         else if (maskfile != "default")  { 
227                                 if (inputDir != "") {
228                                         string path = m->hasPath(maskfile);
229                                         //if the user has not given a path then, add inputdir. else leave path alone.
230                                         if (path == "") {       maskfile = inputDir + maskfile;         }
231                                 }
232
233                                 ifstream in;
234                                 int     ableToOpen = m->openInputFile(maskfile, in);
235                                 if (ableToOpen == 1) { abort = true; }
236                                 in.close();
237                         }
238                         
239                         string temp;
240                         temp = validParameter.validFile(parameters, "filter", false);                   if (temp == "not found") { temp = "F"; }
241                         filter = m->isTrue(temp);
242                         
243                         temp = validParameter.validFile(parameters, "processors", false);       if (temp == "not found"){       temp = m->getProcessors();      }
244                         m->setProcessors(temp);
245                         m->mothurConvert(temp, processors);
246                         
247                         temp = validParameter.validFile(parameters, "window", false);                   if (temp == "not found") { temp = "0"; }
248                         m->mothurConvert(temp, window);
249                         
250                         temp = validParameter.validFile(parameters, "numwanted", false);                if (temp == "not found") { temp = "20"; }
251                         m->mothurConvert(temp, numwanted);
252                         
253                         temp = validParameter.validFile(parameters, "save", false);                     if (temp == "not found"){       temp = "f";                             }
254                         save = m->isTrue(temp); 
255                         rdb->save = save; 
256                         if (save) { //clear out old references
257                                 rdb->clearMemory();     
258                         }
259                         
260                         //this has to go after save so that if the user sets save=t and provides no reference we abort
261                         templatefile = validParameter.validFile(parameters, "reference", true);
262                         if (templatefile == "not found") { 
263                                 //check for saved reference sequences
264                                 if (rdb->referenceSeqs.size() != 0) {
265                                         templatefile = "saved";
266                                 }else {
267                                         m->mothurOut("[ERROR]: You don't have any saved reference sequences and the reference parameter is a required."); 
268                                         m->mothurOutEndLine();
269                                         abort = true; 
270                                 }
271                         }else if (templatefile == "not open") { abort = true; } 
272                         else {  if (save) {     rdb->setSavedReference(templatefile);   }       }
273                         
274
275                 }
276         }
277         catch(exception& e) {
278                 m->errorOut(e, "ChimeraCcodeCommand", "ChimeraCcodeCommand");
279                 exit(1);
280         }
281 }
282 //***************************************************************************************************************
283 int ChimeraCcodeCommand::execute(){
284         try{
285                 
286                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
287                 
288                 for (int s = 0; s < fastaFileNames.size(); s++) {
289                                 
290                         m->mothurOut("Checking sequences from " + fastaFileNames[s] + " ..." ); m->mothurOutEndLine();
291                 
292                         int start = time(NULL); 
293                         
294                         //set user options
295                         if (maskfile == "default") { m->mothurOut("I am using the default 236627 EU009184.1 Shigella dysenteriae str. FBD013."); m->mothurOutEndLine();  }
296
297                         chimera = new Ccode(fastaFileNames[s], templatefile, filter, maskfile, window, numwanted, outputDir);   
298                         
299                         //is your template aligned?
300                         if (chimera->getUnaligned()) { m->mothurOut("Your template sequences are different lengths, please correct."); m->mothurOutEndLine(); delete chimera; return 0; }
301                         templateSeqsLength = chimera->getLength();
302                         
303                         if (outputDir == "") { outputDir = m->hasPath(fastaFileNames[s]);  }//if user entered a file with a path then preserve it
304                         string outputFileName, accnosFileName;
305             map<string, string> variables; 
306             variables["[filename]"] = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s]));
307             string mapInfo = getOutputFileName("mapinfo", variables);
308                         if (maskfile != "") { variables["[tag]"] = maskfile; }
309             outputFileName = getOutputFileName("chimera", variables);
310             accnosFileName = getOutputFileName("accnos", variables);
311                                                 
312                         if (m->control_pressed) { delete chimera;  for (int j = 0; j < outputNames.size(); j++) {       m->mothurRemove(outputNames[j]);        } outputTypes.clear(); return 0;        }
313                         
314                 #ifdef USE_MPI
315                 
316                                 int pid, numSeqsPerProcessor; 
317                                 int tag = 2001;
318                                 vector<unsigned long long> MPIPos;
319                                                                 
320                                 MPI_Status status; 
321                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
322                                 MPI_Comm_size(MPI_COMM_WORLD, &processors); 
323
324                                 MPI_File inMPI;
325                                 MPI_File outMPI;
326                                 MPI_File outMPIAccnos;
327                                 
328                                 int outMode=MPI_MODE_CREATE|MPI_MODE_WRONLY; 
329                                 int inMode=MPI_MODE_RDONLY; 
330                                 
331                                 char outFilename[1024];
332                                 strcpy(outFilename, outputFileName.c_str());
333                                 
334                                 char outAccnosFilename[1024];
335                                 strcpy(outAccnosFilename, accnosFileName.c_str());
336                                 
337                                 char inFileName[1024];
338                                 strcpy(inFileName, fastaFileNames[s].c_str());
339
340                                 MPI_File_open(MPI_COMM_WORLD, inFileName, inMode, MPI_INFO_NULL, &inMPI);  //comm, filename, mode, info, filepointer
341                                 MPI_File_open(MPI_COMM_WORLD, outFilename, outMode, MPI_INFO_NULL, &outMPI);
342                                 MPI_File_open(MPI_COMM_WORLD, outAccnosFilename, outMode, MPI_INFO_NULL, &outMPIAccnos);
343
344                                 if (m->control_pressed) {  MPI_File_close(&inMPI);  MPI_File_close(&outMPI);   MPI_File_close(&outMPIAccnos);  for (int j = 0; j < outputNames.size(); j++) {   m->mothurRemove(outputNames[j]);        } outputTypes.clear();  delete chimera; return 0;  }
345                         
346                                 if (pid == 0) { //you are the root process 
347                                         string outTemp = "For full window mapping info refer to " + mapInfo + "\n";
348                                         
349                                         //print header
350                                         int length = outTemp.length();
351                                         char* buf2 = new char[length];
352                                         memcpy(buf2, outTemp.c_str(), length);
353
354                                         MPI_File_write_shared(outMPI, buf2, length, MPI_CHAR, &status);
355                                         delete buf2;
356
357                                         MPIPos = m->setFilePosFasta(fastaFileNames[s], numSeqs); //fills MPIPos, returns numSeqs
358                                         
359                                         //send file positions to all processes
360                                         for(int i = 1; i < processors; i++) { 
361                                                 MPI_Send(&numSeqs, 1, MPI_INT, i, tag, MPI_COMM_WORLD);
362                                                 MPI_Send(&MPIPos[0], (numSeqs+1), MPI_LONG, i, tag, MPI_COMM_WORLD);
363                                         }
364                                         
365                                         //figure out how many sequences you have to align
366                                         numSeqsPerProcessor = numSeqs / processors;
367                                         int startIndex =  pid * numSeqsPerProcessor;
368                                         if(pid == (processors - 1)){    numSeqsPerProcessor = numSeqs - pid * numSeqsPerProcessor;      }
369                                         
370                                 
371                                         //align your part
372                                         driverMPI(startIndex, numSeqsPerProcessor, inMPI, outMPI, outMPIAccnos, MPIPos);
373                                         
374                                         if (m->control_pressed) {  MPI_File_close(&inMPI);  MPI_File_close(&outMPI);   MPI_File_close(&outMPIAccnos);  m->mothurRemove(outputFileName);  m->mothurRemove(accnosFileName);  for (int j = 0; j < outputNames.size(); j++) {       m->mothurRemove(outputNames[j]);        } outputTypes.clear();  delete chimera; return 0;  }
375
376                                 }else{ //you are a child process
377                                         MPI_Recv(&numSeqs, 1, MPI_INT, 0, tag, MPI_COMM_WORLD, &status);
378                                         MPIPos.resize(numSeqs+1);
379                                         MPI_Recv(&MPIPos[0], (numSeqs+1), MPI_LONG, 0, tag, MPI_COMM_WORLD, &status);
380                                         
381                                         //figure out how many sequences you have to align
382                                         numSeqsPerProcessor = numSeqs / processors;
383                                         int startIndex =  pid * numSeqsPerProcessor;
384                                         if(pid == (processors - 1)){    numSeqsPerProcessor = numSeqs - pid * numSeqsPerProcessor;      }
385                                         
386                                         
387                                         //align your part
388                                         driverMPI(startIndex, numSeqsPerProcessor, inMPI, outMPI, outMPIAccnos, MPIPos);
389                                         
390                                         if (m->control_pressed) {  MPI_File_close(&inMPI);  MPI_File_close(&outMPI);   MPI_File_close(&outMPIAccnos);  for (int j = 0; j < outputNames.size(); j++) {   m->mothurRemove(outputNames[j]);        }  outputTypes.clear(); delete chimera; return 0;  }
391                                 }
392                                 
393                                 //close files 
394                                 MPI_File_close(&inMPI);
395                                 MPI_File_close(&outMPI);
396                                 MPI_File_close(&outMPIAccnos);
397                                 
398                                 MPI_Barrier(MPI_COMM_WORLD); //make everyone wait - just in case
399                                         
400                 #else
401                         ofstream outHeader;
402                         string tempHeader = outputDir + m->getRootName(m->getSimpleName(fastaFileNames[s])) + maskfile + "ccode.chimeras.tempHeader";
403                         m->openOutputFile(tempHeader, outHeader);
404                         
405                         outHeader << "For full window mapping info refer to " << mapInfo << endl << endl;
406
407                         outHeader.close();
408                         
409                         
410                         
411                         //break up file
412                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
413                                 vector<unsigned long long> positions = m->divideFile(fastaFileNames[s], processors);
414                         
415                                 for (int i = 0; i < (positions.size()-1); i++) {
416                                         lines.push_back(new linePair(positions[i], positions[(i+1)]));
417                                 }       
418                         
419                                 if(processors == 1){
420                                                                                 
421                                         numSeqs = driver(lines[0], outputFileName, fastaFileNames[s], accnosFileName);
422                                         
423                                         if (m->control_pressed) { m->mothurRemove(outputFileName); m->mothurRemove(tempHeader); m->mothurRemove(accnosFileName); for (int j = 0; j < outputNames.size(); j++) { m->mothurRemove(outputNames[j]);        } for (int i = 0; i < lines.size(); i++) {  delete lines[i];  } outputTypes.clear();  lines.clear(); delete chimera; return 0; }
424                                         
425                                 }else{
426                                         processIDS.resize(0);
427                                         
428                                         numSeqs = createProcesses(outputFileName, fastaFileNames[s], accnosFileName); 
429                                 
430                                         rename((outputFileName + toString(processIDS[0]) + ".temp").c_str(), outputFileName.c_str());
431                                         rename((accnosFileName + toString(processIDS[0]) + ".temp").c_str(), accnosFileName.c_str());
432                                                 
433                                         //append output files
434                                         for(int i=1;i<processors;i++){
435                                                 m->appendFiles((outputFileName + toString(processIDS[i]) + ".temp"), outputFileName);
436                                                 m->mothurRemove((outputFileName + toString(processIDS[i]) + ".temp"));
437                                         }
438                                         
439                                         //append output files
440                                         for(int i=1;i<processors;i++){
441                                                 m->appendFiles((accnosFileName + toString(processIDS[i]) + ".temp"), accnosFileName);
442                                                 m->mothurRemove((accnosFileName + toString(processIDS[i]) + ".temp"));
443                                         }
444                                         
445                                         if (m->control_pressed) { 
446                                                 m->mothurRemove(outputFileName); 
447                                                 m->mothurRemove(accnosFileName);
448                                                 for (int j = 0; j < outputNames.size(); j++) {  m->mothurRemove(outputNames[j]);        } outputTypes.clear();
449                                                 for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
450                                                 delete chimera;
451                                                 return 0;
452                                         }
453
454                                 }
455
456                         #else
457                                 lines.push_back(new linePair(0, 1000));
458                                 numSeqs = driver(lines[0], outputFileName, fastaFileNames[s], accnosFileName);
459                                 
460                                 if (m->control_pressed) { m->mothurRemove(outputFileName); m->mothurRemove(tempHeader); m->mothurRemove(accnosFileName); for (int j = 0; j < outputNames.size(); j++) { m->mothurRemove(outputNames[j]);        } for (int i = 0; i < lines.size(); i++) {  delete lines[i];  } outputTypes.clear();  lines.clear(); delete chimera; return 0; }
461                                 
462                         #endif
463         
464                         m->appendFiles(outputFileName, tempHeader);
465                 
466                         m->mothurRemove(outputFileName);
467                         rename(tempHeader.c_str(), outputFileName.c_str());
468                 #endif
469                 
470                         delete chimera;
471                         
472                         outputNames.push_back(outputFileName); outputTypes["chimera"].push_back(outputFileName);
473                         outputNames.push_back(mapInfo); outputTypes["mapinfo"].push_back(mapInfo);
474                         outputNames.push_back(accnosFileName); outputTypes["accnos"].push_back(accnosFileName);
475                          
476                         for (int i = 0; i < lines.size(); i++) {  delete lines[i];  }  lines.clear();
477                         
478                         m->mothurOutEndLine(); m->mothurOut("It took " + toString(time(NULL) - start) + " secs to check " + toString(numSeqs) + " sequences."); m->mothurOutEndLine();
479                 }
480                 
481                 
482                 //set accnos file as new current accnosfile
483                 string current = "";
484                 itTypes = outputTypes.find("accnos");
485                 if (itTypes != outputTypes.end()) {
486                         if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setAccnosFile(current); }
487                 }
488                 
489                 m->mothurOutEndLine();
490                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
491                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }       
492                 m->mothurOutEndLine();
493                 
494                 return 0;
495                 
496         }
497         catch(exception& e) {
498                 m->errorOut(e, "ChimeraCcodeCommand", "execute");
499                 exit(1);
500         }
501 }
502 //**********************************************************************************************************************
503
504 int ChimeraCcodeCommand::driver(linePair* filePos, string outputFName, string filename, string accnos){
505         try {
506                 ofstream out;
507                 m->openOutputFile(outputFName, out);
508                 
509                 ofstream out2;
510                 m->openOutputFile(accnos, out2);
511                 
512                 ifstream inFASTA;
513                 m->openInputFile(filename, inFASTA);
514
515                 inFASTA.seekg(filePos->start);
516
517                 bool done = false;
518                 int count = 0;
519         
520                 while (!done) {
521                 
522                         if (m->control_pressed) {       return 1;       }
523                 
524                         Sequence* candidateSeq = new Sequence(inFASTA);  m->gobble(inFASTA);
525                                 
526                         if (candidateSeq->getName() != "") { //incase there is a commented sequence at the end of a file
527                                 
528                                 if (candidateSeq->getAligned().length() != templateSeqsLength) {  
529                                         m->mothurOut(candidateSeq->getName() + " is not the same length as the template sequences. Skipping."); m->mothurOutEndLine();
530                                 }else{
531                                         //find chimeras
532                                         chimera->getChimeras(candidateSeq);
533                                         
534                                         if (m->control_pressed) {       delete candidateSeq; return 1;  }
535                 
536                                         //print results
537                                         chimera->print(out, out2);
538                                 }
539                                 count++;
540                         }
541                         delete candidateSeq;
542                         
543                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
544                                 unsigned long long pos = inFASTA.tellg();
545                                 if ((pos == -1) || (pos >= filePos->end)) { break; }
546                         #else
547                                 if (inFASTA.eof()) { break; }
548                         #endif
549                         
550                         //report progress
551                         if((count) % 100 == 0){ m->mothurOutJustToScreen("Processing sequence: " + toString(count) + "\n");             }
552                 }
553                 //report progress
554                 if((count) % 100 != 0){ m->mothurOutJustToScreen("Processing sequence: " + toString(count) + "\n");     }
555                 
556                 out.close();
557                 out2.close();
558                 inFASTA.close();
559                                 
560                 return count;
561         }
562         catch(exception& e) {
563                 m->errorOut(e, "ChimeraCcodeCommand", "driver");
564                 exit(1);
565         }
566 }
567 //**********************************************************************************************************************
568 #ifdef USE_MPI
569 int ChimeraCcodeCommand::driverMPI(int start, int num, MPI_File& inMPI, MPI_File& outMPI, MPI_File& outAccMPI, vector<unsigned long long>& MPIPos){
570         try {
571                                 
572                 MPI_Status status; 
573                 int pid;
574                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); //find out who we are
575                 
576                 for(int i=0;i<num;i++){
577                 
578                         if (m->control_pressed) { return 0; }
579                         
580                         //read next sequence
581                         int length = MPIPos[start+i+1] - MPIPos[start+i];
582         
583                         char* buf4 = new char[length];
584                                 
585                         MPI_File_read_at(inMPI, MPIPos[start+i], buf4, length, MPI_CHAR, &status);
586                         
587                         string tempBuf = buf4;
588                         if (tempBuf.length() > length) { tempBuf = tempBuf.substr(0, length);  }
589                         istringstream iss (tempBuf,istringstream::in);
590                         delete buf4;
591
592                         Sequence* candidateSeq = new Sequence(iss);  m->gobble(iss);
593                                 
594                         if (candidateSeq->getName() != "") { //incase there is a commented sequence at the end of a file
595                                 
596                                 if (candidateSeq->getAligned().length() != templateSeqsLength) {  
597                                         m->mothurOut(candidateSeq->getName() + " is not the same length as the template sequences. Skipping."); m->mothurOutEndLine();
598                                 }else{
599                                         //find chimeras
600                                         chimera->getChimeras(candidateSeq);
601                                         
602                                         if (m->control_pressed) {       delete candidateSeq; return 1;  }
603                 
604                                         //print results
605                                         chimera->print(outMPI, outAccMPI);
606                                 }
607                         }
608                         delete candidateSeq;
609                         
610                         //report progress
611                         if((i+1) % 100 == 0){  cout << "Processing sequence: " << (i+1) << endl;        m->mothurOutJustToLog("Processing sequence: " + toString(i+1) + "\n");          }
612                 }
613                 //report progress
614                 if(num % 100 != 0){             cout << "Processing sequence: " << num << endl; m->mothurOutJustToLog("Processing sequence: " + toString(num) + "\n");  }
615                 
616                                 
617                 return 0;
618         }
619         catch(exception& e) {
620                 m->errorOut(e, "ChimeraCcodeCommand", "driverMPI");
621                 exit(1);
622         }
623 }
624 #endif
625
626 /**************************************************************************************************/
627
628 int ChimeraCcodeCommand::createProcesses(string outputFileName, string filename, string accnos) {
629         try {
630 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
631                 int process = 0;
632                 int num = 0;
633                 
634                 //loop through and create all the processes you want
635                 while (process != processors) {
636                         int pid = fork();
637                         
638                         if (pid > 0) {
639                                 processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
640                                 process++;
641                         }else if (pid == 0){
642                                 num = driver(lines[process], outputFileName + toString(getpid()) + ".temp", filename, accnos + toString(getpid()) + ".temp");
643                                 
644                                 //pass numSeqs to parent
645                                 ofstream out;
646                                 string tempFile = outputFileName + toString(getpid()) + ".num.temp";
647                                 m->openOutputFile(tempFile, out);
648                                 out << num << endl;
649                                 out.close();
650
651                                 exit(0);
652                         }else { 
653                                 m->mothurOut("[ERROR]: unable to spawn the necessary processes."); m->mothurOutEndLine(); 
654                                 for (int i = 0; i < processIDS.size(); i++) { kill (processIDS[i], SIGINT); }
655                                 exit(0);
656                         }
657                 }
658                 
659                 //force parent to wait until all the processes are done
660                 for (int i=0;i<processors;i++) { 
661                         int temp = processIDS[i];
662                         wait(&temp);
663                 }
664                 
665                 for (int i = 0; i < processIDS.size(); i++) {
666                         ifstream in;
667                         string tempFile =  outputFileName + toString(processIDS[i]) + ".num.temp";
668                         m->openInputFile(tempFile, in);
669                         if (!in.eof()) { int tempNum = 0; in >> tempNum; num += tempNum; }
670                         in.close(); m->mothurRemove(tempFile);
671                 }
672                 
673                 return num;
674 #endif          
675         }
676         catch(exception& e) {
677                 m->errorOut(e, "ChimeraCcodeCommand", "createProcesses");
678                 exit(1);
679         }
680 }
681 //**********************************************************************************************************************
682