]> git.donarmstrong.com Git - mothur.git/blob - chimeraslayercommand.h
fixed bug in phylo.diversity rooting. added filename patterns and create filename...
[mothur.git] / chimeraslayercommand.h
1 #ifndef CHIMERASLAYERCOMMAND_H
2 #define CHIMERASLAYERCOMMAND_H
3
4 /*
5  *  chimeraslayercommand.h
6  *  Mothur
7  *
8  *  Created by westcott on 3/31/10.
9  *  Copyright 2010 Schloss Lab. All rights reserved.
10  *
11  */
12
13 #include "mothur.h"
14 #include "command.hpp"
15 #include "chimera.h"
16 #include "chimeraslayer.h"
17 #include "sequenceparser.h"
18 #include "sequencecountparser.h"
19
20 /***********************************************************/
21
22 class ChimeraSlayerCommand : public Command {
23 public:
24         ChimeraSlayerCommand(string);
25         ChimeraSlayerCommand();
26         ~ChimeraSlayerCommand() {}
27         
28         vector<string> setParameters();
29         string getCommandName()                 { return "chimera.slayer";              }
30         string getCommandCategory()             { return "Sequence Processing"; }
31         
32         string getHelpString(); 
33     string getOutputPattern(string);    
34         string getCitation() { return "Haas BJ, Gevers D, Earl A, Feldgarden M, Ward DV, Giannokous G, Ciulla D, Tabbaa D, Highlander SK, Sodergren E, Methe B, Desantis TZ, Petrosino JF, Knight R, Birren BW (2011). Chimeric 16S rRNA sequence formation and detection in Sanger and 454-pyrosequenced PCR amplicons. Genome Res  21:494.\nhttp://www.mothur.org/wiki/Chimera.slayer"; }
35         string getDescription()         { return "detect chimeric sequences"; }
36         
37         int execute(); 
38         void help() { m->mothurOut(getHelpString()); }          
39         
40 private:
41
42         struct linePair {
43                 unsigned long long start;
44                 unsigned long long end;
45                 linePair(unsigned long long i, unsigned long long j) : start(i), end(j) {}
46         };
47
48         vector<int> processIDS;   //processid
49         vector<linePair> lines;
50         
51         int driver(linePair, string, string, string, string, map<string, int>&);
52         int createProcesses(string, string, string, string, map<string, int>&);
53         int divideInHalf(Sequence, string&, string&);
54         map<string, int> sortFastaFile(string, string);
55         map<string, int> sortFastaFile(vector<Sequence>&, map<string, string>&, string newFile);
56     int sortFastaFile(vector<Sequence>&, map<string, int>&, string newFile);
57         string getNamesFile(string&);
58         //int setupChimera(string,);
59         int MPIExecute(string, string, string, string, map<string, int>&);
60         int deconvoluteResults(map<string, string>&, string, string, string);
61         map<string, int> priority;
62         int setUpForSelfReference(SequenceParser*&, map<string, string>&, map<string, map<string, int> >&, int);
63     int setUpForSelfReference(SequenceCountParser*&, map<string, string>&, map<string, map<string, int> >&, int);
64         int driverGroups(string, string, string, map<string, map<string, int> >&, map<string, string>&);
65         int createProcessesGroups(string, string, string, map<string, map<string, int> >&, map<string, string>&);
66         int MPIExecuteGroups(string, string, string, map<string, map<string, int> >&, map<string, string>&);
67
68                 
69         #ifdef USE_MPI
70         int driverMPI(int, int, MPI_File&, MPI_File&, MPI_File&, MPI_File&, vector<unsigned long long>&, string, map<string, int>&, bool);
71         #endif
72
73         bool abort, realign, trim, trimera, save, hasName, hasCount;
74         string fastafile, groupfile, templatefile, outputDir, search, namefile, countfile, blastlocation;
75         int processors, window, iters, increment, numwanted, ksize, match, mismatch, parents, minSimilarity, minCoverage, minBS, minSNP, numSeqs, templateSeqsLength;
76         float divR;
77         
78         vector<string> outputNames;
79         vector<string> fastaFileNames;
80         vector<string> nameFileNames;
81         vector<string> groupFileNames;
82         
83 };
84
85 /***********************************************************/
86
87 //custom data structure for threads to use.
88 // This is passed by void pointer so it can be any data type
89 // that can be passed using a single void pointer (LPVOID).
90 struct slayerData {
91         string outputFName; 
92         string fasta; 
93         string accnos;
94         string filename;
95         string templatefile;
96         string search;
97         string blastlocation;
98         bool trimera;
99         bool trim, realign;
100         unsigned long long start;
101         unsigned long long end;
102         int ksize, match, mismatch, window, minSimilarity, minCoverage, minBS, minSNP, parents, iters, increment, numwanted;
103         MothurOut* m;
104         float divR;
105         map<string, int> priority;
106         int count;
107         int numNoParents;
108         int threadId;
109         map<string, map<string, int> > fileToPriority;
110         map<string, string> fileGroup;
111         
112         slayerData(){}
113         slayerData(string o, string fa, string ac, string f, string te, string se, string bl, bool tri, bool trm, bool re, MothurOut* mout, unsigned long long st, unsigned long long en, int ks, int ma, int mis, int win, int minS, int minC, int miBS, int minSN, int par, int it, int inc, int numw, float div, map<string, int> prior, int tid) {
114                 outputFName = o;
115                 fasta = fa;
116                 accnos = ac;
117                 filename = f;
118                 templatefile = te;
119                 search = se;
120                 blastlocation = bl;
121                 trimera = tri;
122                 trim = trm;
123                 realign = re;
124                 m = mout;
125                 start = st;
126                 end = en;
127                 ksize = ks;
128                 match = ma; 
129                 mismatch = mis;
130                 window = win;
131                 minSimilarity = minS;
132                 minCoverage = minC;
133                 minBS = miBS;
134                 minSNP = minSN;
135                 parents = par;
136                 iters = it;
137                 increment = inc;
138                 numwanted = numw;
139                 divR = div;
140                 priority = prior;
141                 threadId = tid;
142                 count = 0;
143                 numNoParents = 0;
144         }
145         slayerData(string o, string fa, string ac, string te, string se, string bl, bool tri, bool trm, bool re, MothurOut* mout, map<string, map<string, int> >& fPriority, map<string, string>& fileG, int ks, int ma, int mis, int win, int minS, int minC, int miBS, int minSN, int par, int it, int inc, int numw, float div, map<string, int> prior, int tid) {
146                 outputFName = o;
147                 fasta = fa;
148                 accnos = ac;
149                 templatefile = te;
150                 search = se;
151                 blastlocation = bl;
152                 trimera = tri;
153                 trim = trm;
154                 realign = re;
155                 m = mout;
156                 fileGroup = fileG;
157                 fileToPriority = fPriority;
158                 ksize = ks;
159                 match = ma; 
160                 mismatch = mis;
161                 window = win;
162                 minSimilarity = minS;
163                 minCoverage = minC;
164                 minBS = miBS;
165                 minSNP = minSN;
166                 parents = par;
167                 iters = it;
168                 increment = inc;
169                 numwanted = numw;
170                 divR = div;
171                 priority = prior;
172                 threadId = tid;
173                 count = 0;
174                 numNoParents = 0;
175         }
176         
177 };
178
179 /**************************************************************************************************/
180 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
181 #else
182 static DWORD WINAPI MySlayerThreadFunction(LPVOID lpParam){ 
183         slayerData* pDataArray;
184         pDataArray = (slayerData*)lpParam;
185         
186         try {
187                 ofstream out;
188                 pDataArray->m->openOutputFile(pDataArray->outputFName, out);
189                 
190                 ofstream out2;
191                 pDataArray->m->openOutputFile(pDataArray->accnos, out2);
192                 
193                 ofstream out3;
194                 if (pDataArray->trim) {  pDataArray->m->openOutputFile(pDataArray->fasta, out3); }
195                 
196                 ifstream inFASTA;
197                 pDataArray->m->openInputFile(pDataArray->filename, inFASTA);
198                 
199                 
200                 
201                 Chimera* chimera;
202                 if (pDataArray->templatefile != "self") { //you want to run slayer with a reference template
203                         chimera = new ChimeraSlayer(pDataArray->filename, pDataArray->templatefile, pDataArray->trim, pDataArray->search, pDataArray->ksize, pDataArray->match, pDataArray->mismatch, pDataArray->window, pDataArray->divR, pDataArray->minSimilarity, pDataArray->minCoverage, pDataArray->minBS, pDataArray->minSNP, pDataArray->parents, pDataArray->iters, pDataArray->increment, pDataArray->numwanted, pDataArray->realign, pDataArray->blastlocation, pDataArray->threadId);     
204                 }else {
205                         chimera = new ChimeraSlayer(pDataArray->filename, pDataArray->templatefile, pDataArray->trim, pDataArray->priority, pDataArray->search, pDataArray->ksize, pDataArray->match, pDataArray->mismatch, pDataArray->window, pDataArray->divR, pDataArray->minSimilarity, pDataArray->minCoverage, pDataArray->minBS, pDataArray->minSNP, pDataArray->parents, pDataArray->iters, pDataArray->increment, pDataArray->numwanted, pDataArray->realign, pDataArray->blastlocation, pDataArray->threadId);       
206                 }
207                 
208                 //print header if you are process 0
209                 if ((pDataArray->start == 0) || (pDataArray->start == 1)) {
210                         chimera->printHeader(out); 
211                         inFASTA.seekg(0);
212                 }else { //this accounts for the difference in line endings. 
213                         inFASTA.seekg(pDataArray->start-1); pDataArray->m->gobble(inFASTA); 
214                 }
215                 
216                 pDataArray->count = pDataArray->end;
217                 
218                 if (pDataArray->m->control_pressed) { out.close(); out2.close(); if (pDataArray->trim) { out3.close(); } inFASTA.close(); delete chimera;  return 0;    }
219                 
220                 if (chimera->getUnaligned()) { 
221                         pDataArray->m->mothurOut("Your template sequences are different lengths, please correct."); pDataArray->m->mothurOutEndLine(); 
222                         out.close(); out2.close(); if (pDataArray->trim) { out3.close(); } inFASTA.close();
223                         delete chimera;
224                         return 0; 
225                 }
226                 int templateSeqsLength = chimera->getLength();
227                 
228                 if (pDataArray->start == 0) { chimera->printHeader(out); }
229                 
230                 int count = 0;
231                 for(int i = 0; i < pDataArray->end; i++){
232                         
233                         if (pDataArray->m->control_pressed) {   out.close(); out2.close(); if (pDataArray->trim) { out3.close(); } inFASTA.close(); delete chimera; return 1;   }
234                         
235                         Sequence* candidateSeq = new Sequence(inFASTA);  pDataArray->m->gobble(inFASTA);
236                         string candidateAligned = candidateSeq->getAligned();
237                         
238                         if (candidateSeq->getName() != "") { //incase there is a commented sequence at the end of a file
239                                 if (candidateSeq->getAligned().length() != templateSeqsLength) {  
240                                         pDataArray->m->mothurOut(candidateSeq->getName() + " is not the same length as the template sequences. Skipping."); pDataArray->m->mothurOutEndLine();
241                                 }else{
242                                         //find chimeras
243                                         chimera->getChimeras(candidateSeq);
244                                         
245                                         if (pDataArray->m->control_pressed) {   delete candidateSeq; delete chimera; return 1;  }
246                                         
247                                         //if you are not chimeric, then check each half
248                                         data_results wholeResults = chimera->getResults();
249                                         
250                                         //determine if we need to split
251                                         bool isChimeric = false;
252                                         
253                                         if (wholeResults.flag == "yes") {
254                                                 string chimeraFlag = "no";
255                                                 if(  (wholeResults.results[0].bsa >= pDataArray->minBS && wholeResults.results[0].divr_qla_qrb >= pDataArray->divR)
256                                                    ||
257                                                    (wholeResults.results[0].bsb >= pDataArray->minBS && wholeResults.results[0].divr_qlb_qra >= pDataArray->divR) ) { chimeraFlag = "yes"; }
258                                                 
259                                                 
260                                                 if (chimeraFlag == "yes") {     
261                                                         if ((wholeResults.results[0].bsa >= pDataArray->minBS) || (wholeResults.results[0].bsb >= pDataArray->minBS)) { isChimeric = true; }
262                                                 }
263                                         }
264                                         
265                                         if ((!isChimeric) && pDataArray->trimera) {
266                                                 
267                                                 //split sequence in half by bases
268                                                 string leftQuery, rightQuery;
269                                                 Sequence tempSeq(candidateSeq->getName(), candidateAligned);
270                                                 //divideInHalf(tempSeq, leftQuery, rightQuery);
271                                                 string queryUnAligned = tempSeq.getUnaligned();
272                                                 int numBases = int(queryUnAligned.length() * 0.5);
273                                                 
274                                                 string queryAligned = tempSeq.getAligned();
275                                                 leftQuery = tempSeq.getAligned();
276                                                 rightQuery = tempSeq.getAligned();
277                                                 
278                                                 int baseCount = 0;
279                                                 int leftSpot = 0;
280                                                 for (int i = 0; i < queryAligned.length(); i++) {
281                                                         //if you are a base
282                                                         if (isalpha(queryAligned[i])) {         
283                                                                 baseCount++; 
284                                                         }
285                                                         
286                                                         //if you have half
287                                                         if (baseCount >= numBases) {  leftSpot = i; break; } //first half
288                                                 }
289                                                 
290                                                 //blank out right side
291                                                 for (int i = leftSpot; i < leftQuery.length(); i++) { leftQuery[i] = '.'; }
292                                                 
293                                                 //blank out left side
294                                                 for (int i = 0; i < leftSpot; i++) { rightQuery[i] = '.'; }
295                                                 
296                                                 //run chimeraSlayer on each piece
297                                                 Sequence* left = new Sequence(candidateSeq->getName(), leftQuery);
298                                                 Sequence* right = new Sequence(candidateSeq->getName(), rightQuery);
299                                                 
300                                                 //find chimeras
301                                                 chimera->getChimeras(left);
302                                                 data_results leftResults = chimera->getResults();
303                                                 
304                                                 chimera->getChimeras(right);
305                                                 data_results rightResults = chimera->getResults();
306                                                 
307                                                 //if either piece is chimeric then report
308                                                 Sequence trimmed = chimera->print(out, out2, leftResults, rightResults);
309                                                 if (pDataArray->trim) { trimmed.printSequence(out3);  }
310                                                 
311                                                 delete left; delete right;
312                                                 
313                                         }else { //already chimeric
314                                                 //print results
315                                                 Sequence trimmed = chimera->print(out, out2);
316                                                 if (pDataArray->trim) { trimmed.printSequence(out3);  }
317                                         }
318                                         
319                                         
320                                 }
321                                 count++;
322                         }
323                         
324                         delete candidateSeq;
325                         //report progress
326                         if((count) % 100 == 0){ pDataArray->m->mothurOut("Processing sequence: " + toString(count)); pDataArray->m->mothurOutEndLine();         }
327                 }
328                 //report progress
329                 if((count) % 100 != 0){ pDataArray->m->mothurOut("Processing sequence: " + toString(count)); pDataArray->m->mothurOutEndLine();         }
330                 
331                 pDataArray->numNoParents = chimera->getNumNoParents();
332                 if (pDataArray->numNoParents == count) {        pDataArray->m->mothurOut("[WARNING]: megablast returned 0 potential parents for all your sequences. This could be due to formatdb.exe not being setup properly, please check formatdb.log for errors.\n"); }
333
334                 out.close();
335                 out2.close();
336                 if (pDataArray->trim) { out3.close(); }
337                 inFASTA.close();
338                 delete chimera;
339                 
340                 return 0;
341                 
342         }
343         catch(exception& e) {
344                 pDataArray->m->errorOut(e, "ChimeraSlayerCommand", "MySlayerThreadFunction");
345                 exit(1);
346         }
347
348
349 /**************************************************************************************************/
350
351 static DWORD WINAPI MySlayerGroupThreadFunction(LPVOID lpParam){ 
352         slayerData* pDataArray;
353         pDataArray = (slayerData*)lpParam;
354         
355         try {
356                 
357                 int totalSeqs = 0;
358                 
359                 for (map<string, map<string, int> >::iterator itFile = pDataArray->fileToPriority.begin(); itFile != pDataArray->fileToPriority.end(); itFile++) {
360                         
361                         if (pDataArray->m->control_pressed) {  return 0;  }
362                         
363                         int start = time(NULL);
364                         string thisFastaName = itFile->first;
365                         map<string, int> thisPriority = itFile->second;
366                         string thisoutputFileName = pDataArray->m->getRootName(pDataArray->m->getSimpleName(thisFastaName)) + pDataArray->fileGroup[thisFastaName] + "slayer.chimera";
367                         string thisaccnosFileName = pDataArray->m->getRootName(pDataArray->m->getSimpleName(thisFastaName)) + pDataArray->fileGroup[thisFastaName] + "slayer.accnos";
368                         string thistrimFastaFileName = pDataArray->m->getRootName(pDataArray->m->getSimpleName(thisFastaName)) + pDataArray->fileGroup[thisFastaName] + "slayer.fasta";
369                         
370                         pDataArray->m->mothurOutEndLine(); pDataArray->m->mothurOut("Checking sequences from group: " + pDataArray->fileGroup[thisFastaName] + "."); pDataArray->m->mothurOutEndLine(); 
371                 
372                         //int numSeqs = driver(lines[0], thisoutputFileName, thisFastaName, thisaccnosFileName, thistrimFastaFileName, thisPriority);
373                         ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
374                         
375                         ofstream out;
376                         pDataArray->m->openOutputFile(thisoutputFileName, out);
377                         
378                         ofstream out2;
379                         pDataArray->m->openOutputFile(thisaccnosFileName, out2);
380                         
381                         ofstream out3;
382                         if (pDataArray->trim) {  pDataArray->m->openOutputFile(thistrimFastaFileName, out3); }
383                         
384                         ifstream inFASTA;
385                         pDataArray->m->openInputFile(thisFastaName, inFASTA);
386                         
387                         Chimera* chimera;
388                         chimera = new ChimeraSlayer(thisFastaName, pDataArray->templatefile, pDataArray->trim, thisPriority, pDataArray->search, pDataArray->ksize, pDataArray->match, pDataArray->mismatch, pDataArray->window, pDataArray->divR, pDataArray->minSimilarity, pDataArray->minCoverage, pDataArray->minBS, pDataArray->minSNP, pDataArray->parents, pDataArray->iters, pDataArray->increment, pDataArray->numwanted, pDataArray->realign, pDataArray->blastlocation, pDataArray->threadId);      
389                         chimera->printHeader(out); 
390                         
391                         int numSeqs = 0;
392                         
393                         if (pDataArray->m->control_pressed) { out.close(); out2.close(); if (pDataArray->trim) { out3.close(); } inFASTA.close(); delete chimera;  return 0;    }
394                         
395                         if (chimera->getUnaligned()) { 
396                                 pDataArray->m->mothurOut("Your template sequences are different lengths, please correct."); pDataArray->m->mothurOutEndLine(); 
397                                 out.close(); out2.close(); if (pDataArray->trim) { out3.close(); } inFASTA.close();
398                                 delete chimera;
399                                 return 0; 
400                         }
401                         int templateSeqsLength = chimera->getLength();
402                         
403                         bool done = false;
404                         while (!done) {
405                                 
406                                 if (pDataArray->m->control_pressed) {   out.close(); out2.close(); if (pDataArray->trim) { out3.close(); } inFASTA.close(); delete chimera; return 1;   }
407                                 
408                                 Sequence* candidateSeq = new Sequence(inFASTA);  pDataArray->m->gobble(inFASTA);
409                                 string candidateAligned = candidateSeq->getAligned();
410                                 
411                                 if (candidateSeq->getName() != "") { //incase there is a commented sequence at the end of a file
412                                         if (candidateSeq->getAligned().length() != templateSeqsLength) {  
413                                                 pDataArray->m->mothurOut(candidateSeq->getName() + " is not the same length as the template sequences. Skipping."); pDataArray->m->mothurOutEndLine();
414                                         }else{
415                                                 //find chimeras
416                                                 chimera->getChimeras(candidateSeq);
417                                                 
418                                                 if (pDataArray->m->control_pressed) {   out.close(); out2.close(); if (pDataArray->trim) { out3.close(); } inFASTA.close(); delete candidateSeq; delete chimera; return 1;      }
419                                                 
420                                                 //if you are not chimeric, then check each half
421                                                 data_results wholeResults = chimera->getResults();
422                                                 
423                                                 //determine if we need to split
424                                                 bool isChimeric = false;
425                                                 
426                                                 if (wholeResults.flag == "yes") {
427                                                         string chimeraFlag = "no";
428                                                         if(  (wholeResults.results[0].bsa >= pDataArray->minBS && wholeResults.results[0].divr_qla_qrb >= pDataArray->divR)
429                                                            ||
430                                                            (wholeResults.results[0].bsb >= pDataArray->minBS && wholeResults.results[0].divr_qlb_qra >= pDataArray->divR) ) { chimeraFlag = "yes"; }
431                                                         
432                                                         
433                                                         if (chimeraFlag == "yes") {     
434                                                                 if ((wholeResults.results[0].bsa >= pDataArray->minBS) || (wholeResults.results[0].bsb >= pDataArray->minBS)) { isChimeric = true; }
435                                                         }
436                                                 }
437                                                 
438                                                 if ((!isChimeric) && pDataArray->trimera) {
439                                                         
440                                                         //split sequence in half by bases
441                                                         string leftQuery, rightQuery;
442                                                         Sequence tempSeq(candidateSeq->getName(), candidateAligned);
443                                                         //divideInHalf(tempSeq, leftQuery, rightQuery);
444                                                         string queryUnAligned = tempSeq.getUnaligned();
445                                                         int numBases = int(queryUnAligned.length() * 0.5);
446                                                         
447                                                         string queryAligned = tempSeq.getAligned();
448                                                         leftQuery = tempSeq.getAligned();
449                                                         rightQuery = tempSeq.getAligned();
450                                                         
451                                                         int baseCount = 0;
452                                                         int leftSpot = 0;
453                                                         for (int i = 0; i < queryAligned.length(); i++) {
454                                                                 //if you are a base
455                                                                 if (isalpha(queryAligned[i])) {         
456                                                                         baseCount++; 
457                                                                 }
458                                                                 
459                                                                 //if you have half
460                                                                 if (baseCount >= numBases) {  leftSpot = i; break; } //first half
461                                                         }
462                                                         
463                                                         //blank out right side
464                                                         for (int i = leftSpot; i < leftQuery.length(); i++) { leftQuery[i] = '.'; }
465                                                         
466                                                         //blank out left side
467                                                         for (int i = 0; i < leftSpot; i++) { rightQuery[i] = '.'; }
468                                                         
469                                                         //run chimeraSlayer on each piece
470                                                         Sequence* left = new Sequence(candidateSeq->getName(), leftQuery);
471                                                         Sequence* right = new Sequence(candidateSeq->getName(), rightQuery);
472                                                         
473                                                         //find chimeras
474                                                         chimera->getChimeras(left);
475                                                         data_results leftResults = chimera->getResults();
476                                                         
477                                                         chimera->getChimeras(right);
478                                                         data_results rightResults = chimera->getResults();
479                                                         
480                                                         //if either piece is chimeric then report
481                                                         Sequence trimmed = chimera->print(out, out2, leftResults, rightResults);
482                                                         if (pDataArray->trim) { trimmed.printSequence(out3);  }
483                                                         
484                                                         delete left; delete right;
485                                                         
486                                                 }else { //already chimeric
487                                                         //print results
488                                                         Sequence trimmed = chimera->print(out, out2);
489                                                         if (pDataArray->trim) { trimmed.printSequence(out3);  }
490                                                 }
491                                                 
492                                                 
493                                         }
494                                         numSeqs++;
495                                 }
496                                 
497                                 delete candidateSeq;
498                                 
499                                 if (inFASTA.eof()) { break; }
500                                 
501                                 //report progress
502                                 if((numSeqs) % 100 == 0){       pDataArray->m->mothurOut("Processing sequence: " + toString(numSeqs)); pDataArray->m->mothurOutEndLine();               }
503                         }
504                         //report progress
505                         if((numSeqs) % 100 != 0){       pDataArray->m->mothurOut("Processing sequence: " + toString(numSeqs)); pDataArray->m->mothurOutEndLine();               }
506                         
507                         pDataArray->numNoParents = chimera->getNumNoParents();
508                         if (pDataArray->numNoParents == numSeqs) {      pDataArray->m->mothurOut("[WARNING]: megablast returned 0 potential parents for all your sequences. This could be due to formatdb.exe not being setup properly, please check formatdb.log for errors.\n"); }
509                         
510                         out.close();
511                         out2.close();
512                         if (pDataArray->trim) { out3.close(); }
513                         inFASTA.close();
514                         delete chimera;
515                         
516                         
517                         ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
518                         
519                         //append files
520                         pDataArray->m->appendFiles(thisoutputFileName, pDataArray->outputFName); pDataArray->m->mothurRemove(thisoutputFileName); 
521                         pDataArray->m->appendFiles(thisaccnosFileName, pDataArray->accnos); pDataArray->m->mothurRemove(thisaccnosFileName);
522                         if (pDataArray->trim) { pDataArray->m->appendFiles(thistrimFastaFileName, pDataArray->fasta); pDataArray->m->mothurRemove(thistrimFastaFileName); }
523                         pDataArray->m->mothurRemove(thisFastaName);
524                         
525                         totalSeqs += numSeqs;
526                         
527                         pDataArray->m->mothurOutEndLine(); pDataArray->m->mothurOut("It took " + toString(time(NULL) - start) + " secs to check " + toString(numSeqs) + " sequences from group " + pDataArray->fileGroup[thisFastaName] + "."); pDataArray->m->mothurOutEndLine();
528                 }
529                 
530                 pDataArray->count = totalSeqs;
531                 
532                 return 0;
533                 
534         }
535         catch(exception& e) {
536                 pDataArray->m->errorOut(e, "ChimeraSlayerCommand", "MySlayerGroupThreadFunction");
537                 exit(1);
538         }
539
540
541 #endif
542
543 /**************************************************************************************************/
544
545
546 #endif
547
548