]> git.donarmstrong.com Git - mothur.git/blob - trimseqscommand.h
fixed bug in phylo.diversity rooting. added filename patterns and create filename...
[mothur.git] / trimseqscommand.h
1 #ifndef TRIMSEQSCOMMAND_H
2 #define TRIMSEQSCOMMAND_H
3
4 /*
5  *  trimseqscommand.h
6  *  Mothur
7  *
8  *  Created by Pat Schloss on 6/6/09.
9  *  Copyright 2009 Patrick D. Schloss. All rights reserved.
10  *
11  */
12
13 #include "mothur.h"
14 #include "command.hpp"
15 #include "sequence.hpp"
16 #include "qualityscores.h"
17 #include "trimoligos.h"
18 #include "counttable.h"
19
20
21 class TrimSeqsCommand : public Command {
22 public:
23         TrimSeqsCommand(string);
24         TrimSeqsCommand();
25         ~TrimSeqsCommand(){}
26         
27         vector<string> setParameters();
28         string getCommandName()                 { return "trim.seqs";   }
29         string getCommandCategory()             { return "Sequence Processing";         }
30         
31         string getHelpString(); 
32     string getOutputPattern(string);    
33         string getCitation() { return "http://www.mothur.org/wiki/Trim.seqs"; }
34         string getDescription()         { return "provides the preprocessing features needed to screen and sort pyrosequences"; }
35
36         int execute(); 
37         void help() { m->mothurOut(getHelpString()); }  
38         
39 private:
40     struct linePair {
41         unsigned long long start;
42         unsigned long long end;
43         linePair(unsigned long long i, unsigned long long j) : start(i), end(j) {}
44         linePair() {}
45     };
46     
47         bool getOligos(vector<vector<string> >&, vector<vector<string> >&, vector<vector<string> >&);
48         bool keepFirstTrim(Sequence&, QualityScores&);
49         bool removeLastTrim(Sequence&, QualityScores&);
50         bool cullLength(Sequence&);
51         bool cullHomoP(Sequence&);
52         bool cullAmbigs(Sequence&);
53     string reverseOligo(string);
54
55         bool abort, createGroup;
56         string fastaFile, oligoFile, qFileName, groupfile, nameFile, countfile, outputDir;
57         
58         bool flip, allFiles, qtrim, keepforward;
59         int numFPrimers, numRPrimers, numLinkers, numSpacers, maxAmbig, maxHomoP, minLength, maxLength, processors, tdiffs, bdiffs, pdiffs, ldiffs, sdiffs, comboStarts;
60         int qWindowSize, qWindowStep, keepFirst, removeLast;
61         double qRollAverage, qThreshold, qWindowAverage, qAverage;
62         vector<string> revPrimer, outputNames;
63         set<string> filesToRemove;
64         map<string, int> barcodes;
65         vector<string> groupVector;
66         map<string, int> primers;
67     vector<string>  linker;
68     vector<string>  spacer;
69         map<string, int> combos;
70         map<string, int> groupToIndex;
71         vector<string> primerNameVector;        //needed here?
72         vector<string> barcodeNameVector;       //needed here?
73         map<string, int> groupCounts;  
74         map<string, string> nameMap;
75     map<string, int> nameCount; //for countfile name -> repCount
76     map<string, string> groupMap; //for countfile name -> group
77
78         vector<int> processIDS;   //processid
79         vector<linePair> lines;
80         vector<linePair> qLines;
81         
82         int driverCreateTrim(string, string, string, string, string, string, string, string, string, string, string, vector<vector<string> >, vector<vector<string> >, vector<vector<string> >, linePair, linePair);    
83         int createProcessesCreateTrim(string, string, string, string, string, string, string, string, string, string, string, vector<vector<string> >, vector<vector<string> >, vector<vector<string> >);
84         int setLines(string, string);
85 };
86
87 /**************************************************************************************************/
88 //custom data structure for threads to use.
89 // This is passed by void pointer so it can be any data type
90 // that can be passed using a single void pointer (LPVOID).
91 struct trimData {
92     unsigned long long start, end;
93     MothurOut* m;
94     string filename, qFileName, trimFileName, scrapFileName, trimQFileName, scrapQFileName, trimNFileName, scrapNFileName, trimCFileName, scrapCFileName, groupFileName, nameFile, countfile;
95         vector<vector<string> > fastaFileNames;
96     vector<vector<string> > qualFileNames;
97     vector<vector<string> > nameFileNames;
98     unsigned long long lineStart, lineEnd, qlineStart, qlineEnd;
99     bool flip, allFiles, qtrim, keepforward, createGroup;
100         int numFPrimers, numRPrimers, numLinkers, numSpacers, maxAmbig, maxHomoP, minLength, maxLength, tdiffs, bdiffs, pdiffs, ldiffs, sdiffs;
101         int qWindowSize, qWindowStep, keepFirst, removeLast, count;
102         double qRollAverage, qThreshold, qWindowAverage, qAverage;
103     vector<string> revPrimer;
104         map<string, int> barcodes;
105         map<string, int> primers;
106     map<string, int> nameCount;
107     vector<string>  linker;
108     vector<string>  spacer;
109         map<string, int> combos;
110         vector<string> primerNameVector;        
111         vector<string> barcodeNameVector;       
112         map<string, int> groupCounts;  
113         map<string, string> nameMap;
114     map<string, string> groupMap;
115     
116         trimData(){}
117         trimData(string fn, string qn, string nf, string cf, string tn, string sn, string tqn, string sqn, string tnn, string snn, string tcn, string scn,string gn, vector<vector<string> > ffn, vector<vector<string> > qfn, vector<vector<string> > nfn, unsigned long long lstart, unsigned long long lend, unsigned long long qstart, unsigned long long qend,  MothurOut* mout,
118                       int pd, int bd, int ld, int sd, int td, map<string, int> pri, map<string, int> bar, vector<string> revP, vector<string> li, vector<string> spa, 
119                       vector<string> priNameVector, vector<string> barNameVector, bool cGroup, bool aFiles, bool keepF, int keepfi, int removeL,
120                       int WindowStep, int WindowSize, int WindowAverage, bool trim, double Threshold, double Average, double RollAverage,
121                       int minL, int maxA, int maxH, int maxL, bool fli, map<string, string> nm, map<string, int> ncount) {
122         filename = fn;
123         qFileName = qn;
124         nameFile = nf;
125         countfile = cf;
126         trimFileName = tn;
127         scrapFileName = sn;
128         trimQFileName = tqn;
129         scrapQFileName = sqn;
130         trimNFileName = tnn;
131         scrapNFileName = snn;
132         trimCFileName = tcn;
133         scrapCFileName = scn;
134         groupFileName = gn;
135         fastaFileNames = ffn;
136         qualFileNames = qfn;
137         nameFileNames = nfn;
138         lineStart = lstart;
139         lineEnd = lend;
140         qlineStart = qstart;
141         qlineEnd = qend;
142                 m = mout;
143         nameCount = ncount;
144         
145         pdiffs = pd;
146         bdiffs = bd;
147         ldiffs = ld;
148         sdiffs = sd;
149         tdiffs = td;
150         barcodes = bar;
151         primers = pri;      numFPrimers = primers.size();
152         revPrimer = revP;   numRPrimers = revPrimer.size();
153         linker = li;        numLinkers = linker.size();
154         spacer = spa;       numSpacers = spacer.size();
155         primerNameVector = priNameVector;
156         barcodeNameVector = barNameVector;
157         
158         createGroup = cGroup;
159         allFiles = aFiles;
160         keepforward = keepF;
161         keepFirst = keepfi;
162         removeLast = removeL;
163         qWindowStep = WindowStep;
164         qWindowSize = WindowSize;
165         qWindowAverage = WindowAverage;
166         qtrim = trim;
167         qThreshold = Threshold;
168         qAverage = Average;
169         qRollAverage = RollAverage;
170         minLength = minL;
171         maxAmbig = maxA;
172         maxHomoP = maxH;
173         maxLength = maxL;
174         flip = fli;
175         nameMap = nm;
176         count = 0;
177         }
178 };
179 /**************************************************************************************************/
180 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
181 #else
182 static DWORD WINAPI MyTrimThreadFunction(LPVOID lpParam){ 
183         trimData* pDataArray;
184         pDataArray = (trimData*)lpParam;
185         
186         try {
187         ofstream trimFASTAFile;
188                 pDataArray->m->openOutputFile(pDataArray->trimFileName, trimFASTAFile);
189                 
190                 ofstream scrapFASTAFile;
191                 pDataArray->m->openOutputFile(pDataArray->scrapFileName, scrapFASTAFile);
192                 
193                 ofstream trimQualFile;
194                 ofstream scrapQualFile;
195                 if(pDataArray->qFileName != ""){
196                         pDataArray->m->openOutputFile(pDataArray->trimQFileName, trimQualFile);
197                         pDataArray->m->openOutputFile(pDataArray->scrapQFileName, scrapQualFile);
198                 }
199                 
200                 ofstream trimNameFile;
201                 ofstream scrapNameFile;
202                 if(pDataArray->nameFile != ""){
203                         pDataArray->m->openOutputFile(pDataArray->trimNFileName, trimNameFile);
204                         pDataArray->m->openOutputFile(pDataArray->scrapNFileName, scrapNameFile);
205                 }
206                 
207                 
208                 ofstream outGroupsFile;
209                 if ((pDataArray->createGroup) && (pDataArray->countfile == "")){        pDataArray->m->openOutputFile(pDataArray->groupFileName, outGroupsFile);   }
210                 if(pDataArray->allFiles){
211                         for (int i = 0; i < pDataArray->fastaFileNames.size(); i++) { //clears old file
212                                 for (int j = 0; j < pDataArray->fastaFileNames[i].size(); j++) { //clears old file
213                                         if (pDataArray->fastaFileNames[i][j] != "") {
214                                                 ofstream temp;
215                                                 pDataArray->m->openOutputFile(pDataArray->fastaFileNames[i][j], temp);                  temp.close();
216                                                 if(pDataArray->qFileName != ""){
217                                                         pDataArray->m->openOutputFile(pDataArray->qualFileNames[i][j], temp);                   temp.close();
218                                                 }
219                                                 
220                                                 if(pDataArray->nameFile != ""){
221                                                         pDataArray->m->openOutputFile(pDataArray->nameFileNames[i][j], temp);                   temp.close();
222                                                 }
223                                         }
224                                 }
225                         }
226                 }
227                 
228         ofstream trimCountFile;
229                 ofstream scrapCountFile;
230                 if(pDataArray->countfile != ""){
231                         pDataArray->m->openOutputFile(pDataArray->trimCFileName, trimCountFile);
232                         pDataArray->m->openOutputFile(pDataArray->scrapCFileName, scrapCountFile);
233             if ((pDataArray->lineStart == 0) || (pDataArray->lineStart == 1)) { trimCountFile << "Representative_Sequence\ttotal" << endl; scrapCountFile << "Representative_Sequence\ttotal" << endl; }
234                 }
235         
236                 ifstream inFASTA;
237                 pDataArray->m->openInputFile(pDataArray->filename, inFASTA);
238                 if ((pDataArray->lineStart == 0) || (pDataArray->lineStart == 1)) {
239                         inFASTA.seekg(0);
240                 }else { //this accounts for the difference in line endings. 
241                         inFASTA.seekg(pDataArray->lineStart-1); pDataArray->m->gobble(inFASTA); 
242                 }
243                 
244                 ifstream qFile;
245                 if(pDataArray->qFileName != "") {
246                         pDataArray->m->openInputFile(pDataArray->qFileName, qFile);
247                         if ((pDataArray->qlineStart == 0) || (pDataArray->qlineStart == 1)) {
248                 qFile.seekg(0);
249             }else { //this accounts for the difference in line endings. 
250                 qFile.seekg(pDataArray->qlineStart-1); pDataArray->m->gobble(qFile); 
251             } 
252                 }
253                 
254                 
255                 TrimOligos trimOligos(pDataArray->pdiffs, pDataArray->bdiffs, pDataArray->ldiffs, pDataArray->sdiffs, pDataArray->primers, pDataArray->barcodes, pDataArray->revPrimer, pDataArray->linker, pDataArray->spacer);
256         
257                 pDataArray->count = pDataArray->lineEnd;
258                 for(int i = 0; i < pDataArray->lineEnd; i++){ //end is the number of sequences to process
259                                    
260                         if (pDataArray->m->control_pressed) { 
261                                 inFASTA.close(); trimFASTAFile.close(); scrapFASTAFile.close();
262                                 if ((pDataArray->createGroup) && (pDataArray->countfile == "")) {        outGroupsFile.close();   }
263                 if(pDataArray->qFileName != "") {       qFile.close();  scrapQualFile.close(); trimQualFile.close();    }
264                 if(pDataArray->nameFile != "")  {       scrapNameFile.close(); trimNameFile.close();    }
265                 if(pDataArray->countfile != "") {       scrapCountFile.close(); trimCountFile.close();  }
266
267                                 if(pDataArray->qFileName != ""){ qFile.close(); }
268                                 return 0;
269                         }
270                         
271                         int success = 1;
272                         string trashCode = "";
273                         int currentSeqsDiffs = 0;
274             
275                         Sequence currSeq(inFASTA); pDataArray->m->gobble(inFASTA);
276                         
277                         QualityScores currQual;
278                         if(pDataArray->qFileName != ""){
279                                 currQual = QualityScores(qFile);  pDataArray->m->gobble(qFile);
280                         }
281                         
282                         string origSeq = currSeq.getUnaligned();
283                         if (origSeq != "") {
284                                 
285                                 int barcodeIndex = 0;
286                                 int primerIndex = 0;
287                                 
288                 if(pDataArray->numLinkers != 0){
289                                         success = trimOligos.stripLinker(currSeq, currQual);
290                                         if(success > pDataArray->ldiffs)                {       trashCode += 'k';       }
291                                         else{ currentSeqsDiffs += success;  }
292                                 }
293                 
294                                 if(pDataArray->barcodes.size() != 0){
295                                         success = trimOligos.stripBarcode(currSeq, currQual, barcodeIndex);
296                                         if(success > pDataArray->bdiffs)                {       trashCode += 'b';       }
297                                         else{ currentSeqsDiffs += success;  }
298                                 }
299                 
300                 if(pDataArray->numSpacers != 0){
301                                         success = trimOligos.stripSpacer(currSeq, currQual);
302                                         if(success > pDataArray->sdiffs)                {       trashCode += 's';       }
303                                         else{ currentSeqsDiffs += success;  }
304
305                                 }
306                 
307                                 if(pDataArray->numFPrimers != 0){
308                                         success = trimOligos.stripForward(currSeq, currQual, primerIndex, pDataArray->keepforward);
309                                         if(success > pDataArray->pdiffs)                {       trashCode += 'f';       }
310                                         else{ currentSeqsDiffs += success;  }
311                                 }
312                                 
313                                 if (currentSeqsDiffs > pDataArray->tdiffs)      {       trashCode += 't';   }
314                                 
315                                 if(pDataArray->numRPrimers != 0){
316                                         success = trimOligos.stripReverse(currSeq, currQual);
317                                         if(!success)                            {       trashCode += 'r';       }
318                                 }
319                 
320                                 if(pDataArray->keepFirst != 0){
321                                         //success = keepFirstTrim(currSeq, currQual);
322                     success = 1;
323                     if(currQual.getName() != ""){
324                         currQual.trimQScores(-1, pDataArray->keepFirst);
325                     }
326                     currSeq.trim(pDataArray->keepFirst);
327                                 }
328                                 
329                                 if(pDataArray->removeLast != 0){
330                                         //success = removeLastTrim(currSeq, currQual);
331                     success = 0;
332                     int length = currSeq.getNumBases() - pDataArray->removeLast;
333                     
334                     if(length > 0){
335                         if(currQual.getName() != ""){
336                             currQual.trimQScores(-1, length);
337                         }
338                         currSeq.trim(length);
339                         success = 1;
340                     }
341                     else{ success = 0; }
342                     
343                                         if(!success)                            {       trashCode += 'l';       }
344                                 }
345                 
346                                 
347                                 if(pDataArray->qFileName != ""){
348                                         int origLength = currSeq.getNumBases();
349                                         
350                                         if(pDataArray->qThreshold != 0)                 {       success = currQual.stripQualThreshold(currSeq, pDataArray->qThreshold);                 }
351                                         else if(pDataArray->qAverage != 0)              {       success = currQual.cullQualAverage(currSeq, pDataArray->qAverage);                              }
352                                         else if(pDataArray->qRollAverage != 0)  {       success = currQual.stripQualRollingAverage(currSeq, pDataArray->qRollAverage);  }
353                                         else if(pDataArray->qWindowAverage != 0){       success = currQual.stripQualWindowAverage(currSeq, pDataArray->qWindowStep, pDataArray->qWindowSize, pDataArray->qWindowAverage);       }
354                                         else                                            {       success = 1;                            }
355                                         
356                                         //you don't want to trim, if it fails above then scrap it
357                                         if ((!pDataArray->qtrim) && (origLength != currSeq.getNumBases())) {  success = 0; }
358                                         
359                                         if(!success)                            {       trashCode += 'q';       }
360                                 }                               
361                 
362                                 if(pDataArray->minLength > 0 || pDataArray->maxLength > 0){
363                                         //success = cullLength(currSeq);
364                     int length = currSeq.getNumBases();
365                     success = 0;        //guilty until proven innocent
366                     if(length >= pDataArray->minLength && pDataArray->maxLength == 0)                   {       success = 1;    }
367                     else if(length >= pDataArray->minLength && length <= pDataArray->maxLength) {       success = 1;    }
368                     else                                                                                                {       success = 0;    }
369                     
370                                         if(!success)                            {       trashCode += 'l';       }
371                                 }
372                                 if(pDataArray->maxHomoP > 0){
373                                         //success = cullHomoP(currSeq);
374                     int longHomoP = currSeq.getLongHomoPolymer();
375                     success = 0;        //guilty until proven innocent
376                     if(longHomoP <= pDataArray->maxHomoP){      success = 1;    }
377                     else                                        {       success = 0;    }
378                     
379                                         if(!success)                            {       trashCode += 'h';       }
380                                 }
381                                 if(pDataArray->maxAmbig != -1){
382                                         //success = cullAmbigs(currSeq);
383                     int numNs = currSeq.getAmbigBases();
384                     success = 0;        //guilty until proven innocent
385                     if(numNs <= pDataArray->maxAmbig)   {       success = 1;    }
386                     else                                        {       success = 0;    }
387                                         if(!success)                            {       trashCode += 'n';       }
388                                 }
389                                 
390                                 if(pDataArray->flip){           // should go last                       
391                                         currSeq.reverseComplement();
392                                         if(pDataArray->qFileName != ""){
393                                                 currQual.flipQScores(); 
394                                         }
395                                 }
396                                 
397                                 if(trashCode.length() == 0){
398                                         currSeq.setAligned(currSeq.getUnaligned());
399                                         currSeq.printSequence(trimFASTAFile);
400                                         
401                                         if(pDataArray->qFileName != ""){
402                                                 currQual.printQScores(trimQualFile);
403                                         }
404                                         
405                                         if(pDataArray->nameFile != ""){
406                                                 map<string, string>::iterator itName = pDataArray->nameMap.find(currSeq.getName());
407                                                 if (itName != pDataArray->nameMap.end()) {  trimNameFile << itName->first << '\t' << itName->second << endl; }
408                                                 else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your namefile, please correct."); pDataArray->m->mothurOutEndLine(); }
409                                         }
410                                         
411                     int numRedundants = 0;
412                     if (pDataArray->countfile != "") {
413                         map<string, int>::iterator itCount = pDataArray->nameCount.find(currSeq.getName());
414                         if (itCount != pDataArray->nameCount.end()) { 
415                             trimCountFile << itCount->first << '\t' << itCount->second << endl;
416                             numRedundants = itCount->second-1;
417                         }else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your count file, please correct."); pDataArray->m->mothurOutEndLine(); }
418                     }
419                                         
420                                         if (pDataArray->createGroup) {
421                                                 if(pDataArray->barcodes.size() != 0){
422                                                         string thisGroup = pDataArray->barcodeNameVector[barcodeIndex];
423                                                         if (pDataArray->primers.size() != 0) { 
424                                                                 if (pDataArray->primerNameVector[primerIndex] != "") { 
425                                                                         if(thisGroup != "") {
426                                                                                 thisGroup += "." + pDataArray->primerNameVector[primerIndex]; 
427                                                                         }else {
428                                                                                 thisGroup = pDataArray->primerNameVector[primerIndex]; 
429                                                                         }
430                                                                 } 
431                                                         }
432                                                         
433                                                         if (pDataArray->countfile == "") { outGroupsFile << currSeq.getName() << '\t' << thisGroup << endl; }
434                             else {   pDataArray->groupMap[currSeq.getName()] = thisGroup; }
435                                                         
436                                                         if (pDataArray->nameFile != "") {
437                                                                 map<string, string>::iterator itName = pDataArray->nameMap.find(currSeq.getName());
438                                                                 if (itName != pDataArray->nameMap.end()) { 
439                                                                         vector<string> thisSeqsNames; 
440                                                                         pDataArray->m->splitAtChar(itName->second, thisSeqsNames, ',');
441                                     numRedundants = thisSeqsNames.size()-1; //we already include ourselves below
442                                                                         for (int k = 1; k < thisSeqsNames.size(); k++) { //start at 1 to skip self
443                                                                                 outGroupsFile << thisSeqsNames[k] << '\t' << thisGroup << endl;
444                                                                         }
445                                                                 }else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your namefile, please correct."); pDataArray->m->mothurOutEndLine(); }                                                   
446                                                         }
447                                                         
448                                                         map<string, int>::iterator it = pDataArray->groupCounts.find(thisGroup);
449                                                         if (it == pDataArray->groupCounts.end()) {      pDataArray->groupCounts[thisGroup] = 1 + numRedundants; }
450                                                         else { pDataArray->groupCounts[it->first] += (1 + numRedundants); }
451                             
452                                                 }
453                                         }
454                                         
455                                         if(pDataArray->allFiles){
456                                                 ofstream output;
457                                                 pDataArray->m->openOutputFileAppend(pDataArray->fastaFileNames[barcodeIndex][primerIndex], output);
458                                                 currSeq.printSequence(output);
459                                                 output.close();
460                                                 
461                                                 if(pDataArray->qFileName != ""){
462                                                         pDataArray->m->openOutputFileAppend(pDataArray->qualFileNames[barcodeIndex][primerIndex], output);
463                                                         currQual.printQScores(output);
464                                                         output.close();                                                 
465                                                 }
466                                                 
467                                                 if(pDataArray->nameFile != ""){
468                                                         map<string, string>::iterator itName = pDataArray->nameMap.find(currSeq.getName());
469                                                         if (itName != pDataArray->nameMap.end()) { 
470                                                                 pDataArray->m->openOutputFileAppend(pDataArray->nameFileNames[barcodeIndex][primerIndex], output);
471                                                                 output << itName->first << '\t' << itName->second << endl; 
472                                                                 output.close();
473                                                         }else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your namefile, please correct."); pDataArray->m->mothurOutEndLine(); }
474                                                 }
475                                         }
476                                 }
477                                 else{
478                                         if(pDataArray->nameFile != ""){ //needs to be before the currSeq name is changed
479                                                 map<string, string>::iterator itName = pDataArray->nameMap.find(currSeq.getName());
480                                                 if (itName != pDataArray->nameMap.end()) {  scrapNameFile << itName->first << '\t' << itName->second << endl; }
481                                                 else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your namefile, please correct."); pDataArray->m->mothurOutEndLine(); }
482                                         }
483                     if (pDataArray->countfile != "") {
484                         map<string, int>::iterator itCount = pDataArray->nameCount.find(currSeq.getName());
485                         if (itCount != pDataArray->nameCount.end()) { 
486                             trimCountFile << itCount->first << '\t' << itCount->second << endl;
487                         }else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your count file, please correct."); pDataArray->m->mothurOutEndLine(); }
488                     }
489                                         currSeq.setName(currSeq.getName() + '|' + trashCode);
490                                         currSeq.setUnaligned(origSeq);
491                                         currSeq.setAligned(origSeq);
492                                         currSeq.printSequence(scrapFASTAFile);
493                                         if(pDataArray->qFileName != ""){
494                                                 currQual.printQScores(scrapQualFile);
495                                         }
496                                 }
497                                 
498                         }
499                         
500                         //report progress
501                         if((i) % 1000 == 0){    pDataArray->m->mothurOut(toString(i)); pDataArray->m->mothurOutEndLine();               }
502                         
503                 }
504                 //report progress
505                 if((pDataArray->count) % 1000 != 0){    pDataArray->m->mothurOut(toString(pDataArray->count)); pDataArray->m->mothurOutEndLine();               }
506                 
507                 
508                 inFASTA.close();
509                 trimFASTAFile.close();
510                 scrapFASTAFile.close();
511                 if (pDataArray->createGroup) {   outGroupsFile.close();   }
512                 if(pDataArray->qFileName != "") {       qFile.close();  scrapQualFile.close(); trimQualFile.close();    }
513                 if(pDataArray->nameFile != "")  {       scrapNameFile.close(); trimNameFile.close();    }
514                 
515         return 0;
516             
517         }
518         catch(exception& e) {
519             pDataArray->m->errorOut(e, "TrimSeqsCommand", "MyTrimThreadFunction");
520             exit(1);
521         }
522     } 
523 #endif
524     
525
526 /**************************************************************************************************/
527
528 #endif