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