]> git.donarmstrong.com Git - mothur.git/blob - sffmultiplecommand.cpp
working on pam
[mothur.git] / sffmultiplecommand.cpp
1 //
2 //  sffmultiplecommand.cpp
3 //  Mothur
4 //
5 //  Created by Sarah Westcott on 8/14/12.
6 //  Copyright (c) 2012 Schloss Lab. All rights reserved.
7 //
8
9 #include "sffmultiplecommand.h"
10
11
12
13 //**********************************************************************************************************************
14 vector<string> SffMultipleCommand::setParameters(){     
15         try {           
16                 CommandParameter pfile("file", "InputTypes", "", "", "none", "none", "none","fasta-name",false,true,true); parameters.push_back(pfile);
17         
18         //sffinfo
19                 CommandParameter ptrim("trim", "Boolean", "", "T", "", "", "","",false,false); parameters.push_back(ptrim);
20         
21         //trim.flows
22                 CommandParameter pmaxhomop("maxhomop", "Number", "", "9", "", "", "","",false,false); parameters.push_back(pmaxhomop);
23                 CommandParameter pmaxflows("maxflows", "Number", "", "450", "", "", "","",false,false); parameters.push_back(pmaxflows);
24                 CommandParameter pminflows("minflows", "Number", "", "450", "", "", "","",false,false); parameters.push_back(pminflows);
25                 CommandParameter ppdiffs("pdiffs", "Number", "", "0", "", "", "","",false,false,true); parameters.push_back(ppdiffs);
26                 CommandParameter pbdiffs("bdiffs", "Number", "", "0", "", "", "","",false,false,true); parameters.push_back(pbdiffs);
27         CommandParameter pldiffs("ldiffs", "Number", "", "0", "", "", "","",false,false); parameters.push_back(pldiffs);
28                 CommandParameter psdiffs("sdiffs", "Number", "", "0", "", "", "","",false,false); parameters.push_back(psdiffs);
29         CommandParameter ptdiffs("tdiffs", "Number", "", "0", "", "", "","",false,false); parameters.push_back(ptdiffs);
30                 CommandParameter psignal("signal", "Number", "", "0.50", "", "", "","",false,false); parameters.push_back(psignal);
31                 CommandParameter pnoise("noise", "Number", "", "0.70", "", "", "","",false,false); parameters.push_back(pnoise);
32                 CommandParameter porder("order", "Multiple", "A-B-I", "A", "", "", "","",false,false, true); parameters.push_back(porder);
33         //shhh.flows
34         CommandParameter plookup("lookup", "InputTypes", "", "", "none", "none", "none","",false,false,true); parameters.push_back(plookup);
35                 CommandParameter pcutoff("cutoff", "Number", "", "0.01", "", "", "","",false,false); parameters.push_back(pcutoff);
36                 CommandParameter pmaxiter("maxiter", "Number", "", "1000", "", "", "","",false,false); parameters.push_back(pmaxiter);
37         CommandParameter plarge("large", "Number", "", "-1", "", "", "","",false,false); parameters.push_back(plarge);
38                 CommandParameter psigma("sigma", "Number", "", "60", "", "", "","",false,false); parameters.push_back(psigma);
39                 CommandParameter pmindelta("mindelta", "Number", "", "0.000001", "", "", "","",false,false); parameters.push_back(pmindelta);
40         
41         //trim.seqs parameters
42         CommandParameter pallfiles("allfiles", "Boolean", "", "t", "", "", "","",false,false); parameters.push_back(pallfiles);
43         CommandParameter pflip("flip", "Boolean", "", "F", "", "", "","",false,false,true); parameters.push_back(pflip);
44                 CommandParameter pmaxambig("maxambig", "Number", "", "-1", "", "", "","",false,false); parameters.push_back(pmaxambig);
45                 CommandParameter pminlength("minlength", "Number", "", "0", "", "", "","",false,false); parameters.push_back(pminlength);
46                 CommandParameter pmaxlength("maxlength", "Number", "", "0", "", "", "","",false,false); parameters.push_back(pmaxlength);
47                 CommandParameter pkeepforward("keepforward", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(pkeepforward);
48         CommandParameter pkeepfirst("keepfirst", "Number", "", "0", "", "", "","",false,false); parameters.push_back(pkeepfirst);
49                 CommandParameter premovelast("removelast", "Number", "", "0", "", "", "","",false,false); parameters.push_back(premovelast);
50
51         
52         CommandParameter pprocessors("processors", "Number", "", "1", "", "", "","",false,false,true); parameters.push_back(pprocessors);
53                 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
54                 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
55                 
56                 vector<string> myArray;
57                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
58                 return myArray;
59         }
60         catch(exception& e) {
61                 m->errorOut(e, "SffMultipleCommand", "setParameters");
62                 exit(1);
63         }
64 }
65 //**********************************************************************************************************************
66 string SffMultipleCommand::getHelpString(){     
67         try {
68                 string helpString = "";
69                 helpString += "The sff.multiple command reads a file containing sff filenames and optional oligos filenames. It runs the files through sffinfo, trim.flows, shhh.flows and trim.seqs combining the results.\n";
70                 helpString += "The sff.multiple command parameters are: ";
71         vector<string> parameters = setParameters();
72         for (int i = 0; i < parameters.size()-1; i++) {
73             helpString += parameters[i] + ", ";
74         }
75         helpString += parameters[parameters.size()-1] + ".\n";
76                 helpString += "The file parameter allows you to enter the a file containing the list of sff files and optional oligos files.\n";
77         helpString += "The trim parameter allows you to indicate if you would like a sequences and quality scores generated by sffinfo trimmed to the clipQualLeft and clipQualRight values.  Default=True. \n";
78         helpString += "The maxambig parameter allows you to set the maximum number of ambigious bases allowed. The default is -1.\n";
79                 helpString += "The maxhomop parameter allows you to set a maximum homopolymer length. \n";
80                 helpString += "The minlength parameter allows you to set and minimum sequence length. \n";
81                 helpString += "The maxlength parameter allows you to set and maximum sequence length. \n";
82                 helpString += "The tdiffs parameter is used to specify the total number of differences allowed in the sequence. The default is pdiffs + bdiffs + sdiffs + ldiffs.\n";
83                 helpString += "The bdiffs parameter is used to specify the number of differences allowed in the barcode. The default is 0.\n";
84                 helpString += "The pdiffs parameter is used to specify the number of differences allowed in the primer. The default is 0.\n";
85         helpString += "The ldiffs parameter is used to specify the number of differences allowed in the linker. The default is 0.\n";
86                 helpString += "The sdiffs parameter is used to specify the number of differences allowed in the spacer. The default is 0.\n";
87                 helpString += "The allfiles parameter will create separate group and fasta file for each grouping. The default is F.\n";
88                 helpString += "The keepforward parameter allows you to indicate whether you want the forward primer removed or not. The default is F, meaning remove the forward primer.\n";
89                 helpString += "The keepfirst parameter trims the sequence to the first keepfirst number of bases after the barcode or primers are removed, before the sequence is checked to see if it meets the other requirements. \n";
90                 helpString += "The removelast removes the last removelast number of bases after the barcode or primers are removed, before the sequence is checked to see if it meets the other requirements.\n";
91         helpString += "The order parameter options are A, B or I.  Default=A. A = TACG and B = TACGTACGTACGATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGC and I = TACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGC.\n";
92                 helpString += "Example sff.multiple(file=mySffOligosFile.txt, trim=F).\n";
93                 helpString += "Note: No spaces between parameter labels (i.e. file), '=' and parameters (i.e.mySffOligosFile.txt).\n";
94                 return helpString;
95         }
96         catch(exception& e) {
97                 m->errorOut(e, "SffMultipleCommand", "getHelpString");
98                 exit(1);
99         }
100 }
101 //**********************************************************************************************************************
102 string SffMultipleCommand::getOutputPattern(string type) {
103     try {
104         string pattern = "";
105         
106         if (type == "fasta") {  pattern = "[filename],fasta"; } 
107         else if (type == "name") {  pattern = "[filename],names"; } 
108         else if (type == "group") {  pattern = "[filename],groups"; }
109         else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true;  }
110         
111         return pattern;
112     }
113     catch(exception& e) {
114         m->errorOut(e, "SffMultipleCommand", "getOutputPattern");
115         exit(1);
116     }
117 }
118 //**********************************************************************************************************************
119 SffMultipleCommand::SffMultipleCommand(){       
120         try {
121                 abort = true; calledHelp = true; 
122                 setParameters();
123                 vector<string> tempOutNames;
124                 outputTypes["fasta"] = tempOutNames;
125         outputTypes["name"] = tempOutNames;
126         outputTypes["group"] = tempOutNames;
127         }
128         catch(exception& e) {
129                 m->errorOut(e, "SffMultipleCommand", "SffMultipleCommand");
130                 exit(1);
131         }
132 }
133 //**********************************************************************************************************************
134
135 SffMultipleCommand::SffMultipleCommand(string option)  {
136         try {
137                 abort = false; calledHelp = false;  append=false; makeGroup=false;
138                 
139                 //allow user to run help
140                 if(option == "help") { help(); abort = true; calledHelp = true; }
141                 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
142                 
143                 else {
144                         //valid paramters for this command
145                         vector<string> myArray = setParameters();
146                         
147                         OptionParser parser(option);
148                         map<string, string> parameters = parser.getParameters();
149                         
150                         ValidParameters validParameter;
151             map<string,string>::iterator it;
152             
153                         //check to make sure all parameters are valid for command
154                         for (it = parameters.begin(); it != parameters.end(); it++) { 
155                                 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
156                         }
157                         
158                         //initialize outputTypes
159                         vector<string> tempOutNames;
160                         outputTypes["fasta"] = tempOutNames;
161             outputTypes["name"] = tempOutNames;
162             outputTypes["group"] = tempOutNames;
163
164                         
165                         //if the user changes the output directory command factory will send this info to us in the output parameter 
166                         outputDir = validParameter.validFile(parameters, "outputdir", false);           if (outputDir == "not found"){  outputDir = "";         }
167                         
168                         //if the user changes the input directory command factory will send this info to us in the output parameter 
169                         inputDir = validParameter.validFile(parameters, "inputdir", false);             
170                         if (inputDir == "not found"){   inputDir = "";          }
171                         else {
172                                 string path;
173                 it = parameters.find("file");
174                                 //user has given a template file
175                                 if(it != parameters.end()){ 
176                                         path = m->hasPath(it->second);
177                                         //if the user has not given a path then, add inputdir. else leave path alone.
178                                         if (path == "") {       parameters["file"] = inputDir + it->second;             }
179                                 }
180                 
181                 it = parameters.find("lookup");
182                                 //user has given a template file
183                                 if(it != parameters.end()){ 
184                                         path = m->hasPath(it->second);
185                                         //if the user has not given a path then, add inputdir. else leave path alone.
186                                         if (path == "") {       parameters["lookup"] = inputDir + it->second;           }
187                                 }
188                         }
189             
190                         filename = validParameter.validFile(parameters, "file", true);
191             if (filename == "not open") { filename = ""; abort = true; }
192             else if (filename == "not found") { filename = "";  }
193                         
194                         string temp;
195                         temp = validParameter.validFile(parameters, "trim", false);                                     if (temp == "not found"){       temp = "T";                             }
196                         trim = m->isTrue(temp); 
197             
198             temp = validParameter.validFile(parameters, "minflows", false);     if (temp == "not found") { temp = "450"; }
199                         m->mothurConvert(temp, minFlows);  
200             
201                         temp = validParameter.validFile(parameters, "maxflows", false); if (temp == "not found") { temp = "450"; }
202                         m->mothurConvert(temp, maxFlows);  
203             
204             temp = validParameter.validFile(parameters, "maxhomop", false);             if (temp == "not found"){       temp = "9";             }
205                         m->mothurConvert(temp, maxHomoP);  
206             
207                         temp = validParameter.validFile(parameters, "signal", false);           if (temp == "not found"){       temp = "0.50";  }
208                         m->mothurConvert(temp, signal);  
209             
210                         temp = validParameter.validFile(parameters, "noise", false);            if (temp == "not found"){       temp = "0.70";  }
211                         m->mothurConvert(temp, noise);  
212             
213                         temp = validParameter.validFile(parameters, "bdiffs", false);           if (temp == "not found"){       temp = "0";             }
214                         m->mothurConvert(temp, bdiffs);
215                         
216                         temp = validParameter.validFile(parameters, "pdiffs", false);           if (temp == "not found"){       temp = "0";             }
217                         m->mothurConvert(temp, pdiffs);
218                         
219             temp = validParameter.validFile(parameters, "ldiffs", false);               if (temp == "not found") { temp = "0"; }
220                         m->mothurConvert(temp, ldiffs);
221             
222             temp = validParameter.validFile(parameters, "sdiffs", false);               if (temp == "not found") { temp = "0"; }
223                         m->mothurConvert(temp, sdiffs);
224                         
225                         temp = validParameter.validFile(parameters, "tdiffs", false);           if (temp == "not found") { int tempTotal = pdiffs + bdiffs + ldiffs + sdiffs;  temp = toString(tempTotal); }
226                         m->mothurConvert(temp, tdiffs);
227                         
228                         if(tdiffs == 0){        tdiffs = bdiffs + pdiffs + ldiffs + sdiffs;     }
229             
230                         
231                         temp = validParameter.validFile(parameters, "processors", false);       if (temp == "not found"){       temp = m->getProcessors();      }
232                         m->setProcessors(temp);
233                         m->mothurConvert(temp, processors);
234             
235                         temp = validParameter.validFile(parameters, "order", false);  if (temp == "not found"){         temp = "A";     }
236             if (temp.length() > 1) {  m->mothurOut("[ERROR]: " + temp + " is not a valid option for order. order options are A, B, or I. A = TACG, B = TACGTACGTACGATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGC, and I = TACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGC.\n");  abort=true;
237             }
238             else {
239                 if (toupper(temp[0]) == 'A') {  flowOrder = "A";   }
240                 else if(toupper(temp[0]) == 'B'){
241                     flowOrder = "B";   }
242                 else if(toupper(temp[0]) == 'I'){
243                     flowOrder = "I";   }
244                 else {
245                     m->mothurOut("[ERROR]: " + temp + " is not a valid option for order. order options are A, B, or I. A = TACG, B = TACGTACGTACGATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATAGATCGCATGACGATCGCATATCGTCAGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGTAGTCGAGCATCATCTGACGCAGTACGTGCATGATCTCAGTCAGCAGCTATGTCAGTGCATGCATAGATCGCATGACGATCGCATATCGTCAGTGCAGTGACTGATCGTCATCAGCTAGCATCGACTGCATGATCTCAGTCAGCAGC, and I = TACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGCTACGTACGTCTGAGCATCGATCGATGTACAGC.\n");  abort=true;
246                 }
247             }
248
249             
250             temp = validParameter.validFile(parameters, "cutoff", false);       if (temp == "not found"){       temp = "0.01";          }
251                         m->mothurConvert(temp, cutoff); 
252                         
253                         temp = validParameter.validFile(parameters, "mindelta", false); if (temp == "not found"){       temp = "0.000001";      }
254                         minDelta = temp; 
255             
256                         temp = validParameter.validFile(parameters, "maxiter", false);  if (temp == "not found"){       temp = "1000";          }
257                         m->mothurConvert(temp, maxIters); 
258             
259             temp = validParameter.validFile(parameters, "large", false);        if (temp == "not found"){       temp = "0";             }
260                         m->mothurConvert(temp, largeSize); 
261             if (largeSize != 0) { large = true; }
262             else { large = false;  }
263             if (largeSize < 0) {  m->mothurOut("The value of the large cannot be negative.\n"); }
264             
265                         temp = validParameter.validFile(parameters, "sigma", false);if (temp == "not found")    {       temp = "60";            }
266                         m->mothurConvert(temp, sigma); 
267             
268             temp = validParameter.validFile(parameters, "flip", false);
269                         if (temp == "not found")    {   flip = 0;       }
270                         else {  flip = m->isTrue(temp);         }
271                         
272                         temp = validParameter.validFile(parameters, "maxambig", false);         if (temp == "not found") { temp = "-1"; }
273                         m->mothurConvert(temp, maxAmbig);  
274                        
275                         temp = validParameter.validFile(parameters, "minlength", false);        if (temp == "not found") { temp = "0"; }
276                         m->mothurConvert(temp, minLength); 
277                         
278                         temp = validParameter.validFile(parameters, "maxlength", false);        if (temp == "not found") { temp = "0"; }
279                         m->mothurConvert(temp, maxLength);
280                                                 
281                         temp = validParameter.validFile(parameters, "keepfirst", false);        if (temp == "not found") { temp = "0"; }
282                         convert(temp, keepFirst);
283             
284                         temp = validParameter.validFile(parameters, "removelast", false);       if (temp == "not found") { temp = "0"; }
285                         convert(temp, removeLast);
286                         
287                         temp = validParameter.validFile(parameters, "allfiles", false);         if (temp == "not found") { temp = "F"; }
288                         allFiles = m->isTrue(temp);
289             
290             temp = validParameter.validFile(parameters, "keepforward", false);          if (temp == "not found") { temp = "F"; }
291                         keepforward = m->isTrue(temp);
292             
293             temp = validParameter.validFile(parameters, "lookup", true);
294                         if (temp == "not found")        {
295                 string path = m->argv;
296                 string tempPath = path;
297                 for (int i = 0; i < path.length(); i++) { tempPath[i] = tolower(path[i]); }
298                 path = path.substr(0, (tempPath.find_last_of('m')));
299                 
300 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
301                 path += "lookupFiles/";
302 #else
303                 path += "lookupFiles\\";
304 #endif
305                                 lookupFileName = m->getFullPathName(path) + "LookUp_Titanium.pat";
306                                 bool ableToOpen = m->checkLocations(lookupFileName, inputDir);
307                 if (!ableToOpen) { abort=true; }
308                         }else if(temp == "not open")    {       
309                                 
310                                 lookupFileName = validParameter.validFile(parameters, "lookup", false);
311                                 
312                                 //if you can't open it its not inputDir, try mothur excutable location
313                                 string exepath = m->argv;
314                                 string tempPath = exepath;
315                                 for (int i = 0; i < exepath.length(); i++) { tempPath[i] = tolower(exepath[i]); }
316                                 exepath = exepath.substr(0, (tempPath.find_last_of('m')));
317                 
318                                 string tryPath = m->getFullPathName(exepath) + m->getSimpleName(lookupFileName);
319                                 m->mothurOut("Unable to open " + lookupFileName + ". Trying mothur's executable location " + tryPath); m->mothurOutEndLine();
320                                 ifstream in2;
321                                 int ableToOpen = m->openInputFile(tryPath, in2, "noerror");
322                                 in2.close();
323                                 lookupFileName = tryPath;
324                                 
325                                 if (ableToOpen == 1) {  m->mothurOut("Unable to open " + lookupFileName + "."); m->mothurOutEndLine(); abort=true;  }
326                         }else                                           {       lookupFileName = temp;  }
327                 }
328         }
329         catch(exception& e) {
330                 m->errorOut(e, "SffMultipleCommand", "SffMultipleCommand");
331                 exit(1);
332         }
333 }
334 //**********************************************************************************************************************
335 int SffMultipleCommand::execute(){
336         try {
337                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
338                 
339                 vector<string> sffFiles, oligosFiles;
340         readFile(sffFiles, oligosFiles);
341         
342         string thisOutputDir = outputDir;
343         if (thisOutputDir == "") { thisOutputDir = m->hasPath(filename); }
344         string fileroot = thisOutputDir + m->getRootName(m->getSimpleName(filename));
345         map<string, string> variables; 
346                 variables["[filename]"] = fileroot;
347         string fasta = getOutputFileName("fasta",variables);
348         string name = getOutputFileName("name",variables);
349         string group = getOutputFileName("group",variables);
350         
351         if (m->control_pressed) { return 0; }
352         
353         if (sffFiles.size() < processors) { processors = sffFiles.size(); }
354         
355 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
356 #else
357         //trim.flows, shhh.flows cannot handle multiple processors for windows.
358         processors = 1; m->mothurOut("This command can only use 1 processor on Windows platforms, using 1 processors.\n\n");
359 #endif
360         if (processors == 1) { driver(sffFiles, oligosFiles, 0, sffFiles.size(), fasta, name, group); }
361         else { createProcesses(sffFiles, oligosFiles, fasta, name, group); } 
362                 
363                 if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);        } return 0; }
364                 
365         if (append) { 
366             outputNames.push_back(fasta); outputTypes["fasta"].push_back(fasta);
367             m->setFastaFile(fasta);
368             outputNames.push_back(name); outputTypes["name"].push_back(name);
369             m->setNameFile(name);
370             if (makeGroup) { outputNames.push_back(group); outputTypes["group"].push_back(group); m->setGroupFile(group); }
371         }
372         
373         m->setProcessors(toString(processors));
374         
375                 //report output filenames
376                 m->mothurOutEndLine();
377                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
378                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
379                 m->mothurOutEndLine();
380         
381                 return 0;
382         }
383         catch(exception& e) {
384                 m->errorOut(e, "SffMultipleCommand", "execute");
385                 exit(1);
386         }
387 }
388 //**********************************************************************************************************************
389 int SffMultipleCommand::readFile(vector<string>& sffFiles, vector<string>& oligosFiles){
390         try {
391         
392         ifstream in;
393         m->openInputFile(filename, in);
394         bool allBlank = true;
395         bool allFull = true;
396         
397         string oligos, sff;
398         while (!in.eof()) {
399             
400             if (m->control_pressed) { break; }
401             
402             in >> sff;
403             
404             //ignore file pairing
405             if(sff[0] == '#'){ while (!in.eof())        {       char c = in.get();  if (c == 10 || c == 13){    break;  }       } m->gobble(in); }
406             else { //check for oligos file
407                 bool ableToOpenSff = m->checkLocations(sff, inputDir);
408                 
409                 oligos = "";
410             
411                 // get rest of line in case there is a oligos filename
412                 while (!in.eof())       {       
413                     char c = in.get(); 
414                     if (c == 10 || c == 13 || c == -1){ break;  }
415                     else if (c == 32 || c == 9){;} //space or tab
416                     else {      oligos += c;  }
417                 }
418                 
419                 if (ableToOpenSff) {
420                     sffFiles.push_back(sff);
421                     if (oligos != "") {
422                         bool ableToOpenOligos = m->checkLocations(oligos, inputDir);
423                         if (ableToOpenOligos) {  allBlank = false; }
424                         else { m->mothurOut("Can not find " + oligos + ". Ignoring.\n"); oligos = ""; }
425                     }
426                     if (oligos == "") { allFull = false;  }
427                     oligosFiles.push_back(oligos); //will push a blank if there is not an oligos for this sff file
428                 }else { m->mothurOut("Can not find " + sff + ". Ignoring.\n"); }
429             }
430             m->gobble(in);
431         }
432         in.close();
433         
434         if (allBlank || allFull) { append = true; }
435         if (allFull) { makeGroup = true; }
436         
437         return 0;
438     }
439         catch(exception& e) {
440                 m->errorOut(e, "SffMultipleCommand", "readFile");
441                 exit(1);
442         }
443 }
444 //**********************************************************************************************************************
445 //runs sffinfo, summary.seqs, trim.flows, shhh.flows, trim.seqs, summary.seqs for each sff file.
446 int SffMultipleCommand::driver(vector<string> sffFiles, vector<string> oligosFiles, int start, int end, string fasta, string name, string group){
447     try {
448         m->mothurRemove(fasta); m->mothurRemove(name); m->mothurRemove(group);
449         int count = 0;
450         for (int s = start; s < end; s++) {
451             
452             string sff = sffFiles[s];
453             string oligos = oligosFiles[s];
454             
455             m->mothurOut("\n>>>>>\tProcessing " + sff + " (file " + toString(s+1) + " of " + toString(sffFiles.size()) + ")\t<<<<<\n");
456             
457             //run sff.info
458             string redirects = "";
459             if (inputDir != "")     { redirects += ", inputdir=" + inputDir;    }
460             if (outputDir != "")    { redirects += ", outputdir=" + outputDir;  }
461             string inputString = "sff=" + sff + ", flow=T";
462             if (trim) { inputString += ", trim=T"; }
463             if (redirects != "") { inputString += redirects; }
464             m->mothurOut("/******************************************/"); m->mothurOutEndLine(); 
465             m->mothurOut("Running command: sffinfo(" + inputString + ")"); m->mothurOutEndLine(); 
466             m->mothurCalling = true;
467             
468             Command* sffCommand = new SffInfoCommand(inputString);
469             sffCommand->execute();
470             
471             if (m->control_pressed){ break; }
472             
473             map<string, vector<string> > filenames = sffCommand->getOutputFiles();
474             
475             delete sffCommand;
476             m->mothurCalling = false;
477             m->mothurOutEndLine(); 
478             
479             redirects = "";
480             if (outputDir != "")    { redirects += ", outputdir=" + outputDir;  }
481
482             //run summary.seqs on the fasta file
483             string fastaFile = "";
484             map<string, vector<string> >::iterator it = filenames.find("fasta");
485             if (it != filenames.end()) {  if ((it->second).size() != 0) { fastaFile = (it->second)[0];  } }
486             else {  m->mothurOut("[ERROR]: sffinfo did not create a fasta file, quitting.\n"); m->control_pressed = true; break;  }
487             
488             inputString = "fasta=" + fastaFile + ", processors=1";
489             if (redirects != "") { inputString += redirects; }
490             m->mothurOutEndLine(); 
491             m->mothurOut("Running command: summary.seqs(" + inputString + ")"); m->mothurOutEndLine(); 
492             m->mothurCalling = true;
493             
494             Command* summarySeqsCommand = new SeqSummaryCommand(inputString);
495             summarySeqsCommand->execute();
496             
497             if (m->control_pressed){ break; }
498             
499             map<string, vector<string> > temp = summarySeqsCommand->getOutputFiles();
500             mergeOutputFileList(filenames, temp);
501             
502             delete summarySeqsCommand;
503             m->mothurCalling = false;
504             
505             m->mothurOutEndLine(); 
506             
507             //run trim.flows on the fasta file
508             string flowFile = "";
509             it = filenames.find("flow");
510             if (it != filenames.end()) {  if ((it->second).size() != 0) { flowFile = (it->second)[0];  } }
511             else {  m->mothurOut("[ERROR]: sffinfo did not create a flow file, quitting.\n"); m->control_pressed = true; break;  }
512             
513             inputString = "flow=" + flowFile;
514             if (oligos != "") { inputString += ", oligos=" + oligos; }
515             inputString += ", maxhomop=" + toString(maxHomoP) + ", maxflows=" + toString(maxFlows) + ", minflows=" + toString(minFlows);
516             inputString += ", pdiffs=" + toString(pdiffs) + ", bdiffs=" + toString(bdiffs) + ", ldiffs=" + toString(ldiffs) + ", sdiffs=" + toString(sdiffs);
517             inputString += ", tdiffs=" + toString(tdiffs) + ", signal=" + toString(signal) + ", noise=" + toString(noise) + ", order=" + flowOrder + ", processors=1";
518             if (redirects != "") { inputString += redirects; }
519             m->mothurOutEndLine(); 
520             m->mothurOut("Running command: trim.flows(" + inputString + ")"); m->mothurOutEndLine(); 
521             m->mothurCalling = true;
522             
523             Command* trimFlowCommand = new TrimFlowsCommand(inputString);
524             trimFlowCommand->execute();
525             
526             if (m->control_pressed){ break; }
527             
528             temp = trimFlowCommand->getOutputFiles();
529             mergeOutputFileList(filenames, temp);
530             
531             delete trimFlowCommand;
532             m->mothurCalling = false;
533             
534             
535             string fileFileName = "";
536             flowFile = "";
537             if (oligos != "") { 
538                 it = temp.find("file");
539                 if (it != temp.end()) {  if ((it->second).size() != 0) { fileFileName = (it->second)[0];  } }
540                 else {  m->mothurOut("[ERROR]: trim.flows did not create a file file, quitting.\n"); m->control_pressed = true; break;  }
541             }else {
542                 vector<string> flowFiles;
543                 it = temp.find("flow");
544                 if (it != temp.end()) {  if ((it->second).size() != 0) { flowFiles = (it->second);  } }
545                 else {  m->mothurOut("[ERROR]: trim.flows did not create a flow file, quitting.\n"); m->control_pressed = true; break;  }
546                 
547                 for (int i = 0; i < flowFiles.size(); i++) {
548                     string end = flowFiles[i].substr(flowFiles[i].length()-9);
549                     if (end == "trim.flow") {
550                         flowFile = flowFiles[i]; i+=flowFiles.size(); //if we found the trim.flow file stop looking
551                     }
552                 }
553             }
554             
555             if ((fileFileName == "") && (flowFile == "")) { m->mothurOut("[ERROR]: trim.flows did not create a file file or a trim.flow file, quitting.\n"); m->control_pressed = true; break;  }
556             
557             if (fileFileName != "") { inputString = "file=" + fileFileName; }
558             else { inputString = "flow=" + flowFile; }
559             
560             inputString += ", lookup=" + lookupFileName + ", cutoff=" + toString(cutoff); + ", maxiters=" + toString(maxIters);
561             if (large) { inputString += ", large=" + toString(largeSize); }
562             inputString += ", sigma=" +toString(sigma);
563             inputString += ", mindelta=" + toString(minDelta);  
564             inputString += ", order=" + flowOrder + ", processors=1";
565             if (redirects != "") { inputString += redirects; }
566             //run shhh.flows
567             m->mothurOutEndLine(); 
568             m->mothurOut("Running command: shhh.flows(" + inputString + ")"); m->mothurOutEndLine(); 
569             m->mothurCalling = true;
570             
571             Command* shhhFlowCommand = new ShhherCommand(inputString);
572             shhhFlowCommand->execute();
573             
574             if (m->control_pressed){ break; }
575             
576             temp = shhhFlowCommand->getOutputFiles();
577             mergeOutputFileList(filenames, temp);
578             
579             delete shhhFlowCommand;
580             m->mothurCalling = false;
581             
582             vector<string> fastaFiles;
583             vector<string> nameFiles;
584             it = temp.find("fasta");
585             if (it != temp.end()) {  if ((it->second).size() != 0) { fastaFiles = (it->second);  } }
586             else {  m->mothurOut("[ERROR]: shhh.flows did not create a fasta file, quitting.\n"); m->control_pressed = true; break;  }
587            
588             it = temp.find("name");
589             if (it != temp.end()) {  if ((it->second).size() != 0) { nameFiles = (it->second);  } }
590             else {  m->mothurOut("[ERROR]: shhh.flows did not create a name file, quitting.\n"); m->control_pressed = true; break;  }
591             
592             //find fasta and name files with the shortest name.  This is because if there is a composite name it will be the shortest.
593             fastaFile = fastaFiles[0];
594             for (int i = 1; i < fastaFiles.size(); i++) { if (fastaFiles[i].length() < fastaFile.length()) { fastaFile = fastaFiles[i]; } }
595             string nameFile = nameFiles[0];
596             for (int i = 1; i < nameFiles.size(); i++) { if (nameFiles[i].length() < nameFile.length()) { nameFile = nameFiles[i]; } }
597             
598             inputString = "fasta=" + fastaFile + ", name=" + nameFile;
599             if (oligos != "") { inputString += ", oligos=" + oligos; }
600             if (allFiles) { inputString += ", allfiles=t"; }
601             else { inputString += ", allfiles=f";  }
602             if (flip) { inputString += ", flip=t"; }
603             else { inputString += ", flip=f";  }
604             if (keepforward) { inputString += ", keepforward=t"; }
605             else { inputString += ", keepforward=f";  }
606             
607             
608             inputString += ", pdiffs=" + toString(pdiffs) + ", bdiffs=" + toString(bdiffs) + ", ldiffs=" + toString(ldiffs) + ", sdiffs=" + toString(sdiffs);
609             inputString += ", tdiffs=" + toString(tdiffs) + ", maxambig=" + toString(maxAmbig) + ", minlength=" + toString(minLength) + ", maxlength=" + toString(maxLength);
610             if (keepFirst != 0) { inputString += ", keepfirst=" + toString(keepFirst); }
611             if (removeLast != 0) { inputString += ", removelast=" + toString(removeLast); }
612             inputString += ", processors=1";
613             if (redirects != "") { inputString += redirects; }
614             //run trim.seqs
615             m->mothurOutEndLine(); 
616             m->mothurOut("Running command: trim.seqs(" + inputString + ")"); m->mothurOutEndLine(); 
617             m->mothurCalling = true;
618             
619             Command* trimseqsCommand = new TrimSeqsCommand(inputString);
620             trimseqsCommand->execute();
621             
622             if (m->control_pressed){ break; }
623             
624             temp = trimseqsCommand->getOutputFiles();
625             mergeOutputFileList(filenames, temp);
626             
627             delete trimseqsCommand;
628             m->mothurCalling = false;
629             
630             it = temp.find("fasta");
631             if (it != temp.end()) {  if ((it->second).size() != 0) { fastaFiles = (it->second);  } }
632             else {  m->mothurOut("[ERROR]: trim.seqs did not create a fasta file, quitting.\n"); m->control_pressed = true; break;  }
633             
634             for (int i = 0; i < fastaFiles.size(); i++) {
635                 string end = fastaFiles[i].substr(fastaFiles[i].length()-10);
636                 if (end == "trim.fasta") {
637                     fastaFile = fastaFiles[i]; i+=fastaFiles.size(); //if we found the trim.fasta file stop looking
638                 }
639             }
640             
641             it = temp.find("name");
642             if (it != temp.end()) {  if ((it->second).size() != 0) { nameFiles = (it->second);  } }
643             else {  m->mothurOut("[ERROR]: trim.seqs did not create a name file, quitting.\n"); m->control_pressed = true; break;  }
644             
645             for (int i = 0; i < nameFiles.size(); i++) {
646                 string end = nameFiles[i].substr(nameFiles[i].length()-10);
647                 if (end == "trim.names") {
648                     nameFile = nameFiles[i]; i+=nameFiles.size(); //if we found the trim.names file stop looking
649                 }
650             }
651             
652             vector<string> groupFiles;
653             string groupFile = "";
654             if (makeGroup) {
655                 it = temp.find("group");
656                 if (it != temp.end()) {  if ((it->second).size() != 0) { groupFiles = (it->second);  } }
657             
658                 //find group file with the shortest name.  This is because if there is a composite group file it will be the shortest.
659                 groupFile = groupFiles[0];
660                 for (int i = 1; i < groupFiles.size(); i++) { if (groupFiles[i].length() < groupFile.length()) { groupFile = groupFiles[i]; } }
661             }
662             
663             inputString = "fasta=" + fastaFile + ", processors=1, name=" + nameFile;
664             if (redirects != "") { inputString += redirects; }
665             m->mothurOutEndLine(); 
666             m->mothurOut("Running command: summary.seqs(" + inputString + ")"); m->mothurOutEndLine(); 
667             m->mothurCalling = true;
668             
669             summarySeqsCommand = new SeqSummaryCommand(inputString);
670             summarySeqsCommand->execute();
671             
672             if (m->control_pressed){ break; }
673             
674             temp = summarySeqsCommand->getOutputFiles();
675             mergeOutputFileList(filenames, temp);
676             
677             delete summarySeqsCommand;
678             m->mothurCalling = false;
679             
680             m->mothurOutEndLine(); 
681             m->mothurOut("/******************************************/"); m->mothurOutEndLine(); 
682             
683             if (append) {
684                 m->appendFiles(fastaFile, fasta);
685                 m->appendFiles(nameFile, name);
686                 if (makeGroup) { m->appendFiles(groupFile, group);  }
687             }
688             
689             
690             for (it = filenames.begin(); it != filenames.end(); it++) {
691                 for (int i = 0; i < (it->second).size(); i++) {
692                     outputNames.push_back((it->second)[i]); outputTypes[it->first].push_back((it->second)[i]);
693                 }
694             }
695             count++;
696         }
697         
698         return count;
699     }
700         catch(exception& e) {
701                 m->errorOut(e, "SffMultipleCommand", "driver");
702                 exit(1);
703         }
704 }
705 //**********************************************************************************************************************
706 int SffMultipleCommand::mergeOutputFileList(map<string, vector<string> >& files, map<string, vector<string> >& temp){
707     try {
708         map<string, vector<string> >::iterator it;
709         for (it = temp.begin(); it != temp.end(); it++) {
710             map<string, vector<string> >::iterator it2 = files.find(it->first);
711             if (it2 == files.end()) { //we do not already have this type so just add it
712                 files[it->first] = it->second;
713             }else { //merge them
714                 for (int i = 0; i < (it->second).size(); i++) {
715                     files[it->first].push_back((it->second)[i]);
716                 }
717             }
718         }
719         
720         return 0;
721     }
722         catch(exception& e) {
723                 m->errorOut(e, "SffMultipleCommand", "mergeOutputFileList");
724                 exit(1);
725         }
726 }
727 //**********************************************************************************************************************
728 int SffMultipleCommand::createProcesses(vector<string> sffFiles, vector<string> oligosFiles, string fasta, string name, string group){
729     try {
730         vector<int> processIDS;
731                 int process = 1;
732                 int num = 0;
733                                 
734                 //divide the groups between the processors
735                 vector<linePair> lines;
736         vector<int> numFilesToComplete;
737                 int numFilesPerProcessor = sffFiles.size() / processors;
738                 for (int i = 0; i < processors; i++) {
739                         int startIndex =  i * numFilesPerProcessor;
740                         int endIndex = (i+1) * numFilesPerProcessor;
741                         if(i == (processors - 1)){      endIndex = sffFiles.size();     }
742                         lines.push_back(linePair(startIndex, endIndex));
743             numFilesToComplete.push_back((endIndex-startIndex));
744                 }
745                 
746 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)          
747                 
748                 //loop through and create all the processes you want
749                 while (process != processors) {
750                         int pid = fork();
751                         
752                         if (pid > 0) {
753                                 processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
754                                 process++;
755                         }else if (pid == 0){
756                                 num = driver(sffFiles, oligosFiles, lines[process].start, lines[process].end, fasta + toString(getpid()) + ".temp", name  + toString(getpid()) + ".temp", group  + toString(getpid()) + ".temp");
757                 
758                 //pass numSeqs to parent
759                                 ofstream out;
760                                 string tempFile = toString(getpid()) + ".num.temp";
761                                 m->openOutputFile(tempFile, out);
762                                 out << num << '\t' << outputNames.size() << endl;
763                 for (int i = 0; i < outputNames.size(); i++) {  out << outputNames[i] << endl;  }
764                                 out.close();
765                 
766                                 exit(0);
767                         }else { 
768                                 m->mothurOut("[ERROR]: unable to spawn the necessary processes."); m->mothurOutEndLine(); 
769                                 for (int i = 0; i < processIDS.size(); i++) { kill (processIDS[i], SIGINT); }
770                                 exit(0);
771                         }
772                 }
773                 
774                 //do my part
775                 num = driver(sffFiles, oligosFiles, lines[0].start, lines[0].end, fasta, name, group);
776                 
777                 //force parent to wait until all the processes are done
778                 for (int i=0;i<processIDS.size();i++) { 
779                         int temp = processIDS[i];
780                         wait(&temp);
781                 }
782         
783         for (int i=0;i<processIDS.size();i++) { 
784             ifstream in;
785                         string tempFile = toString(processIDS[i]) + ".num.temp";
786                         m->openInputFile(tempFile, in);
787                         if (!in.eof()) { 
788                 int tempNum = 0; int outputNamesSize = 0; 
789                 in >> tempNum >> outputNamesSize; m->gobble(in);
790                 for (int j = 0; j < outputNamesSize; j++) {
791                     string tempName;
792                     in >> tempName; m->gobble(in);
793                     outputNames.push_back(tempName);
794                 }
795                 if (tempNum != numFilesToComplete[i+1]) {
796                     m->mothurOut("[ERROR]: main process expected " + toString(processIDS[i]) + " to complete " + toString(numFilesToComplete[i+1]) + " files, and it only reported completing " + toString(tempNum) + ". This will cause file mismatches.  The flow files may be too large to process with multiple processors. \n");
797                 }
798             }
799                         in.close(); m->mothurRemove(tempFile);
800             
801             if (append) {
802                 m->appendFiles(fasta+toString(processIDS[i])+".temp", fasta);   m->mothurRemove(fasta+toString(processIDS[i])+".temp");
803                 m->appendFiles(name+toString(processIDS[i])+".temp", name);     m->mothurRemove(name+toString(processIDS[i])+".temp");
804                 if (makeGroup) { m->appendFiles(group+toString(processIDS[i])+".temp", group);  m->mothurRemove(group+toString(processIDS[i])+".temp"); }
805             }
806         }
807 #endif
808         return 0;
809         
810     }
811         catch(exception& e) {
812                 m->errorOut(e, "ShhherCommand", "createProcesses");
813                 exit(1);
814         }
815 }
816 //**********************************************************************************************************************
817
818
819
820