]> git.donarmstrong.com Git - mothur.git/blob - trimseqscommand.h
added get.dists and remove.dists commands. fixed bug in trim.seqs windows paralelliza...
[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 = 0;
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                 pDataArray->count++;
285                                 
286                                 int barcodeIndex = 0;
287                                 int primerIndex = 0;
288                                 
289                 if(pDataArray->numLinkers != 0){
290                                         success = trimOligos.stripLinker(currSeq, currQual);
291                                         if(success > pDataArray->ldiffs)                {       trashCode += 'k';       }
292                                         else{ currentSeqsDiffs += success;  }
293                                 }
294                 
295                                 if(pDataArray->barcodes.size() != 0){
296                                         success = trimOligos.stripBarcode(currSeq, currQual, barcodeIndex);
297                                         if(success > pDataArray->bdiffs)                {       trashCode += 'b';       }
298                                         else{ currentSeqsDiffs += success;  }
299                                 }
300                 
301                 if(pDataArray->numSpacers != 0){
302                                         success = trimOligos.stripSpacer(currSeq, currQual);
303                                         if(success > pDataArray->sdiffs)                {       trashCode += 's';       }
304                                         else{ currentSeqsDiffs += success;  }
305
306                                 }
307                 
308                                 if(pDataArray->numFPrimers != 0){
309                                         success = trimOligos.stripForward(currSeq, currQual, primerIndex, pDataArray->keepforward);
310                                         if(success > pDataArray->pdiffs)                {       trashCode += 'f';       }
311                                         else{ currentSeqsDiffs += success;  }
312                                 }
313                                 
314                                 if (currentSeqsDiffs > pDataArray->tdiffs)      {       trashCode += 't';   }
315                                 
316                                 if(pDataArray->numRPrimers != 0){
317                                         success = trimOligos.stripReverse(currSeq, currQual);
318                                         if(!success)                            {       trashCode += 'r';       }
319                                 }
320                 
321                                 if(pDataArray->keepFirst != 0){
322                                         //success = keepFirstTrim(currSeq, currQual);
323                     success = 1;
324                     if(currQual.getName() != ""){
325                         currQual.trimQScores(-1, pDataArray->keepFirst);
326                     }
327                     currSeq.trim(pDataArray->keepFirst);
328                                 }
329                                 
330                                 if(pDataArray->removeLast != 0){
331                                         //success = removeLastTrim(currSeq, currQual);
332                     success = 0;
333                     int length = currSeq.getNumBases() - pDataArray->removeLast;
334                     
335                     if(length > 0){
336                         if(currQual.getName() != ""){
337                             currQual.trimQScores(-1, length);
338                         }
339                         currSeq.trim(length);
340                         success = 1;
341                     }
342                     else{ success = 0; }
343                     
344                                         if(!success)                            {       trashCode += 'l';       }
345                                 }
346                 
347                                 
348                                 if(pDataArray->qFileName != ""){
349                                         int origLength = currSeq.getNumBases();
350                                         
351                                         if(pDataArray->qThreshold != 0)                 {       success = currQual.stripQualThreshold(currSeq, pDataArray->qThreshold);                 }
352                                         else if(pDataArray->qAverage != 0)              {       success = currQual.cullQualAverage(currSeq, pDataArray->qAverage);                              }
353                                         else if(pDataArray->qRollAverage != 0)  {       success = currQual.stripQualRollingAverage(currSeq, pDataArray->qRollAverage);  }
354                                         else if(pDataArray->qWindowAverage != 0){       success = currQual.stripQualWindowAverage(currSeq, pDataArray->qWindowStep, pDataArray->qWindowSize, pDataArray->qWindowAverage);       }
355                                         else                                            {       success = 1;                            }
356                                         
357                                         //you don't want to trim, if it fails above then scrap it
358                                         if ((!pDataArray->qtrim) && (origLength != currSeq.getNumBases())) {  success = 0; }
359                                         
360                                         if(!success)                            {       trashCode += 'q';       }
361                                 }                               
362                 
363                                 if(pDataArray->minLength > 0 || pDataArray->maxLength > 0){
364                                         //success = cullLength(currSeq);
365                     int length = currSeq.getNumBases();
366                     success = 0;        //guilty until proven innocent
367                     if(length >= pDataArray->minLength && pDataArray->maxLength == 0)                   {       success = 1;    }
368                     else if(length >= pDataArray->minLength && length <= pDataArray->maxLength) {       success = 1;    }
369                     else                                                                                                {       success = 0;    }
370                     
371                                         if(!success)                            {       trashCode += 'l';       }
372                                 }
373                                 if(pDataArray->maxHomoP > 0){
374                                         //success = cullHomoP(currSeq);
375                     int longHomoP = currSeq.getLongHomoPolymer();
376                     success = 0;        //guilty until proven innocent
377                     if(longHomoP <= pDataArray->maxHomoP){      success = 1;    }
378                     else                                        {       success = 0;    }
379                     
380                                         if(!success)                            {       trashCode += 'h';       }
381                                 }
382                                 if(pDataArray->maxAmbig != -1){
383                                         //success = cullAmbigs(currSeq);
384                     int numNs = currSeq.getAmbigBases();
385                     success = 0;        //guilty until proven innocent
386                     if(numNs <= pDataArray->maxAmbig)   {       success = 1;    }
387                     else                                        {       success = 0;    }
388                                         if(!success)                            {       trashCode += 'n';       }
389                                 }
390                                 
391                                 if(pDataArray->flip){           // should go last                       
392                                         currSeq.reverseComplement();
393                                         if(pDataArray->qFileName != ""){
394                                                 currQual.flipQScores(); 
395                                         }
396                                 }
397                                 
398                                 if(trashCode.length() == 0){
399                     string thisGroup = "";
400                     if (pDataArray->createGroup) {
401                                                 if(pDataArray->barcodes.size() != 0){
402                                                         thisGroup = pDataArray->barcodeNameVector[barcodeIndex];
403                                                         if (pDataArray->primers.size() != 0) { 
404                                                                 if (pDataArray->primerNameVector[primerIndex] != "") { 
405                                                                         if(thisGroup != "") {
406                                                                                 thisGroup += "." + pDataArray->primerNameVector[primerIndex]; 
407                                                                         }else {
408                                                                                 thisGroup = pDataArray->primerNameVector[primerIndex]; 
409                                                                         }
410                                                                 } 
411                                                         }
412                         }
413                     }
414                     
415                     int pos = thisGroup.find("ignore");
416                     if (pos == string::npos) {
417                         
418                         currSeq.setAligned(currSeq.getUnaligned());
419                         currSeq.printSequence(trimFASTAFile);
420                         
421                         if(pDataArray->qFileName != ""){
422                             currQual.printQScores(trimQualFile);
423                         }
424                         
425                         if(pDataArray->nameFile != ""){
426                             map<string, string>::iterator itName = pDataArray->nameMap.find(currSeq.getName());
427                             if (itName != pDataArray->nameMap.end()) {  trimNameFile << itName->first << '\t' << itName->second << endl; }
428                             else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your namefile, please correct."); pDataArray->m->mothurOutEndLine(); }
429                         }
430                         
431                         int numRedundants = 0;
432                         if (pDataArray->countfile != "") {
433                             map<string, int>::iterator itCount = pDataArray->nameCount.find(currSeq.getName());
434                             if (itCount != pDataArray->nameCount.end()) { 
435                                 trimCountFile << itCount->first << '\t' << itCount->second << endl;
436                                 numRedundants = itCount->second-1;
437                             }else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your count file, please correct."); pDataArray->m->mothurOutEndLine(); }
438                         }
439                         
440                         if (pDataArray->createGroup) {
441                             if(pDataArray->barcodes.size() != 0){
442                                 
443                                 if (pDataArray->countfile == "") { outGroupsFile << currSeq.getName() << '\t' << thisGroup << endl; }
444                                 else {   pDataArray->groupMap[currSeq.getName()] = thisGroup; }
445                                 
446                                 if (pDataArray->nameFile != "") {
447                                     map<string, string>::iterator itName = pDataArray->nameMap.find(currSeq.getName());
448                                     if (itName != pDataArray->nameMap.end()) { 
449                                         vector<string> thisSeqsNames; 
450                                         pDataArray->m->splitAtChar(itName->second, thisSeqsNames, ',');
451                                         numRedundants = thisSeqsNames.size()-1; //we already include ourselves below
452                                         for (int k = 1; k < thisSeqsNames.size(); k++) { //start at 1 to skip self
453                                             outGroupsFile << thisSeqsNames[k] << '\t' << thisGroup << endl;
454                                         }
455                                     }else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your namefile, please correct."); pDataArray->m->mothurOutEndLine(); }                                                       
456                                 }
457                                 
458                                 map<string, int>::iterator it = pDataArray->groupCounts.find(thisGroup);
459                                 if (it == pDataArray->groupCounts.end()) {      pDataArray->groupCounts[thisGroup] = 1 + numRedundants; }
460                                 else { pDataArray->groupCounts[it->first] += (1 + numRedundants); }
461                                 
462                             }
463                         }
464                         
465                         if(pDataArray->allFiles){
466                             ofstream output;
467                             pDataArray->m->openOutputFileAppend(pDataArray->fastaFileNames[barcodeIndex][primerIndex], output);
468                             currSeq.printSequence(output);
469                             output.close();
470                             
471                             if(pDataArray->qFileName != ""){
472                                 pDataArray->m->openOutputFileAppend(pDataArray->qualFileNames[barcodeIndex][primerIndex], output);
473                                 currQual.printQScores(output);
474                                 output.close();                                                 
475                             }
476                             
477                             if(pDataArray->nameFile != ""){
478                                 map<string, string>::iterator itName = pDataArray->nameMap.find(currSeq.getName());
479                                 if (itName != pDataArray->nameMap.end()) { 
480                                     pDataArray->m->openOutputFileAppend(pDataArray->nameFileNames[barcodeIndex][primerIndex], output);
481                                     output << itName->first << '\t' << itName->second << endl; 
482                                     output.close();
483                                 }else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your namefile, please correct."); pDataArray->m->mothurOutEndLine(); }
484                             }
485                         }
486                     }
487                                 }
488                                 else{
489                                         if(pDataArray->nameFile != ""){ //needs to be before the currSeq name is changed
490                                                 map<string, string>::iterator itName = pDataArray->nameMap.find(currSeq.getName());
491                                                 if (itName != pDataArray->nameMap.end()) {  scrapNameFile << itName->first << '\t' << itName->second << endl; }
492                                                 else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your namefile, please correct."); pDataArray->m->mothurOutEndLine(); }
493                                         }
494                     if (pDataArray->countfile != "") {
495                         map<string, int>::iterator itCount = pDataArray->nameCount.find(currSeq.getName());
496                         if (itCount != pDataArray->nameCount.end()) { 
497                             trimCountFile << itCount->first << '\t' << itCount->second << endl;
498                         }else { pDataArray->m->mothurOut("[ERROR]: " + currSeq.getName() + " is not in your count file, please correct."); pDataArray->m->mothurOutEndLine(); }
499                     }
500                                         currSeq.setName(currSeq.getName() + '|' + trashCode);
501                                         currSeq.setUnaligned(origSeq);
502                                         currSeq.setAligned(origSeq);
503                                         currSeq.printSequence(scrapFASTAFile);
504                                         if(pDataArray->qFileName != ""){
505                                                 currQual.printQScores(scrapQualFile);
506                                         }
507                                 }
508                                 
509                         }
510                         
511                         //report progress
512                         if((i) % 1000 == 0){    pDataArray->m->mothurOut(toString(i)); pDataArray->m->mothurOutEndLine();               }
513                         
514                 }
515                 //report progress
516                 if((pDataArray->count) % 1000 != 0){    pDataArray->m->mothurOut(toString(pDataArray->count)); pDataArray->m->mothurOutEndLine();               }
517                 
518                 
519                 inFASTA.close();
520                 trimFASTAFile.close();
521                 scrapFASTAFile.close();
522                 if (pDataArray->createGroup) {   outGroupsFile.close();   }
523                 if(pDataArray->qFileName != "") {       qFile.close();  scrapQualFile.close(); trimQualFile.close();    }
524                 if(pDataArray->nameFile != "")  {       scrapNameFile.close(); trimNameFile.close();    }
525                 
526         return 0;
527             
528         }
529         catch(exception& e) {
530             pDataArray->m->errorOut(e, "TrimSeqsCommand", "MyTrimThreadFunction");
531             exit(1);
532         }
533     } 
534 #endif
535     
536
537 /**************************************************************************************************/
538
539 #endif