]> git.donarmstrong.com Git - mothur.git/blob - sffmultiplecommand.cpp
changes while testing
[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                         string 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                                 lookupFileName = "LookUp_Titanium.pat"; 
296                                 
297                                 int ableToOpen;
298                                 ifstream in;
299                                 ableToOpen = m->openInputFile(lookupFileName, in, "noerror");
300                                 in.close();     
301                                 
302                                 //if you can't open it, try input location
303                                 if (ableToOpen == 1) {
304                                         if (inputDir != "") { //default path is set
305                                                 string tryPath = inputDir + lookupFileName;
306                                                 m->mothurOut("Unable to open " + lookupFileName + ". Trying input directory " + tryPath); m->mothurOutEndLine();
307                                                 ifstream in2;
308                                                 ableToOpen = m->openInputFile(tryPath, in2, "noerror");
309                                                 in2.close();
310                                                 lookupFileName = tryPath;
311                                         }
312                                 }
313                                 
314                                 //if you can't open it, try default location
315                                 if (ableToOpen == 1) {
316                                         if (m->getDefaultPath() != "") { //default path is set
317                                                 string tryPath = m->getDefaultPath() + m->getSimpleName(lookupFileName);
318                                                 m->mothurOut("Unable to open " + lookupFileName + ". Trying default " + tryPath); m->mothurOutEndLine();
319                                                 ifstream in2;
320                                                 ableToOpen = m->openInputFile(tryPath, in2, "noerror");
321                                                 in2.close();
322                                                 lookupFileName = tryPath;
323                                         }
324                                 }
325                                 
326                                 //if you can't open it its not in current working directory or inputDir, try mothur excutable location
327                                 if (ableToOpen == 1) {
328                                         string exepath = m->argv;
329                                         string tempPath = exepath;
330                                         for (int i = 0; i < exepath.length(); i++) { tempPath[i] = tolower(exepath[i]); }
331                                         exepath = exepath.substr(0, (tempPath.find_last_of('m')));
332                                         
333                                         string tryPath = m->getFullPathName(exepath) + m->getSimpleName(lookupFileName);
334                                         m->mothurOut("Unable to open " + lookupFileName + ". Trying mothur's executable location " + tryPath); m->mothurOutEndLine();
335                                         ifstream in2;
336                                         ableToOpen = m->openInputFile(tryPath, in2, "noerror");
337                                         in2.close();
338                                         lookupFileName = tryPath;
339                                 }
340                                 
341                                 if (ableToOpen == 1) {  m->mothurOut("Unable to open " + lookupFileName + "."); m->mothurOutEndLine(); abort=true;  }
342                         }
343                         else if(temp == "not open")     {       
344                                 
345                                 lookupFileName = validParameter.validFile(parameters, "lookup", false);
346                                 
347                                 //if you can't open it its not inputDir, try mothur excutable location
348                                 string exepath = m->argv;
349                                 string tempPath = exepath;
350                                 for (int i = 0; i < exepath.length(); i++) { tempPath[i] = tolower(exepath[i]); }
351                                 exepath = exepath.substr(0, (tempPath.find_last_of('m')));
352                 
353                                 string tryPath = m->getFullPathName(exepath) + lookupFileName;
354                                 m->mothurOut("Unable to open " + lookupFileName + ". Trying mothur's executable location " + tryPath); m->mothurOutEndLine();
355                                 ifstream in2;
356                                 int ableToOpen = m->openInputFile(tryPath, in2, "noerror");
357                                 in2.close();
358                                 lookupFileName = tryPath;
359                                 
360                                 if (ableToOpen == 1) {  m->mothurOut("Unable to open " + lookupFileName + "."); m->mothurOutEndLine(); abort=true;  }
361                         }else                                           {       lookupFileName = temp;  }
362                 }
363         }
364         catch(exception& e) {
365                 m->errorOut(e, "SffMultipleCommand", "SffMultipleCommand");
366                 exit(1);
367         }
368 }
369 //**********************************************************************************************************************
370 int SffMultipleCommand::execute(){
371         try {
372                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
373                 
374                 vector<string> sffFiles, oligosFiles;
375         readFile(sffFiles, oligosFiles);
376         
377         outputDir = m->hasPath(filename);
378         string fileroot = outputDir + m->getRootName(m->getSimpleName(filename));
379         map<string, string> variables; 
380                 variables["[filename]"] = fileroot;
381         string fasta = getOutputFileName("fasta",variables);
382         string name = getOutputFileName("name",variables);
383         string group = getOutputFileName("group",variables);
384         
385         if (m->control_pressed) { return 0; }
386         
387         if (sffFiles.size() < processors) { processors = sffFiles.size(); }
388         
389 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
390 #else
391         //trim.flows, shhh.flows cannot handle multiple processors for windows.
392         processors = 1; m->mothurOut("This command can only use 1 processor on Windows platforms, using 1 processors.\n\n");
393 #endif
394         if (processors == 1) { driver(sffFiles, oligosFiles, 0, sffFiles.size(), fasta, name, group); }
395         else { createProcesses(sffFiles, oligosFiles, fasta, name, group); } 
396                 
397                 if (m->control_pressed) {  for (int i = 0; i < outputNames.size(); i++) {       m->mothurRemove(outputNames[i]);        } return 0; }
398                 
399         if (append) { 
400             outputNames.push_back(fasta); outputTypes["fasta"].push_back(fasta);
401             m->setFastaFile(fasta);
402             outputNames.push_back(name); outputTypes["name"].push_back(name);
403             m->setNameFile(name);
404             if (makeGroup) { outputNames.push_back(group); outputTypes["group"].push_back(group); m->setGroupFile(group); }
405         }
406         
407                 //report output filenames
408                 m->mothurOutEndLine();
409                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
410                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
411                 m->mothurOutEndLine();
412         
413                 return 0;
414         }
415         catch(exception& e) {
416                 m->errorOut(e, "SffMultipleCommand", "execute");
417                 exit(1);
418         }
419 }
420 //**********************************************************************************************************************
421 int SffMultipleCommand::readFile(vector<string>& sffFiles, vector<string>& oligosFiles){
422         try {
423         
424         ifstream in;
425         m->openInputFile(filename, in);
426         bool allBlank = true;
427         bool allFull = true;
428         
429         string oligos, sff;
430         while (!in.eof()) {
431             
432             if (m->control_pressed) { break; }
433             
434             in >> sff;
435             
436             sff = m->getFullPathName(sff);
437             
438             //ignore file pairing
439             if(sff[0] == '#'){ while (!in.eof())        {       char c = in.get();  if (c == 10 || c == 13){    break;  }       } m->gobble(in); }
440             else { //check for oligos file
441                 oligos = "";
442             
443                 // get rest of line in case there is a oligos filename
444                 while (!in.eof())       {       
445                     char c = in.get(); 
446                     if (c == 10 || c == 13 || c == -1){ break;  }
447                     else if (c == 32 || c == 9){;} //space or tab
448                     else {      oligos += c;  }
449                 } 
450                 sffFiles.push_back(sff);
451                 if (oligos != "") { oligos = m->getFullPathName(oligos); allBlank = false;  }
452                 if (oligos == "") { allFull = false;  }
453                 oligosFiles.push_back(oligos); //will push a blank if there is not an oligos for this sff file
454             }
455             m->gobble(in);
456         }
457         in.close();
458         
459         if (allBlank || allFull) { append = true; }
460         if (allFull) { makeGroup = true; }
461         
462         return 0;
463     }
464         catch(exception& e) {
465                 m->errorOut(e, "SffMultipleCommand", "readFile");
466                 exit(1);
467         }
468 }
469 //**********************************************************************************************************************
470 //runs sffinfo, summary.seqs, trim.flows, shhh.flows, trim.seqs, summary.seqs for each sff file.
471 int SffMultipleCommand::driver(vector<string> sffFiles, vector<string> oligosFiles, int start, int end, string fasta, string name, string group){
472     try {
473         m->mothurRemove(fasta); m->mothurRemove(name); m->mothurRemove(group);
474         int count = 0;
475         for (int s = start; s < end; s++) {
476             
477             string sff = sffFiles[s];
478             string oligos = oligosFiles[s];
479             
480             m->mothurOut("\n>>>>>\tProcessing " + sff + " (file " + toString(s+1) + " of " + toString(sffFiles.size()) + ")\t<<<<<\n");
481             
482             //run sff.info
483             string inputString = "sff=" + sff + ", flow=T";
484             if (trim) { inputString += ", trim=T"; }
485             m->mothurOut("/******************************************/"); m->mothurOutEndLine(); 
486             m->mothurOut("Running command: sffinfo(" + inputString + ")"); m->mothurOutEndLine(); 
487             m->mothurCalling = true;
488             
489             Command* sffCommand = new SffInfoCommand(inputString);
490             sffCommand->execute();
491             
492             if (m->control_pressed){ break; }
493             
494             map<string, vector<string> > filenames = sffCommand->getOutputFiles();
495             
496             delete sffCommand;
497             m->mothurCalling = false;
498             m->mothurOutEndLine(); 
499             
500             //run summary.seqs on the fasta file
501             string fastaFile = "";
502             map<string, vector<string> >::iterator it = filenames.find("fasta");
503             if (it != filenames.end()) {  if ((it->second).size() != 0) { fastaFile = (it->second)[0];  } }
504             else {  m->mothurOut("[ERROR]: sffinfo did not create a fasta file, quitting.\n"); m->control_pressed = true; break;  }
505             
506             inputString = "fasta=" + fastaFile + ", processors=1";
507             m->mothurOutEndLine(); 
508             m->mothurOut("Running command: summary.seqs(" + inputString + ")"); m->mothurOutEndLine(); 
509             m->mothurCalling = true;
510             
511             Command* summarySeqsCommand = new SeqSummaryCommand(inputString);
512             summarySeqsCommand->execute();
513             
514             if (m->control_pressed){ break; }
515             
516             map<string, vector<string> > temp = summarySeqsCommand->getOutputFiles();
517             mergeOutputFileList(filenames, temp);
518             
519             delete summarySeqsCommand;
520             m->mothurCalling = false;
521             
522             m->mothurOutEndLine(); 
523             
524             //run trim.flows on the fasta file
525             string flowFile = "";
526             it = filenames.find("flow");
527             if (it != filenames.end()) {  if ((it->second).size() != 0) { flowFile = (it->second)[0];  } }
528             else {  m->mothurOut("[ERROR]: sffinfo did not create a flow file, quitting.\n"); m->control_pressed = true; break;  }
529             
530             inputString = "flow=" + flowFile;
531             if (oligos != "") { inputString += ", oligos=" + oligos; }
532             inputString += ", maxhomop=" + toString(maxHomoP) + ", maxflows=" + toString(maxFlows) + ", minflows=" + toString(minFlows);
533             inputString += ", pdiffs=" + toString(pdiffs) + ", bdiffs=" + toString(bdiffs) + ", ldiffs=" + toString(ldiffs) + ", sdiffs=" + toString(sdiffs);
534             inputString += ", tdiffs=" + toString(tdiffs) + ", signal=" + toString(signal) + ", noise=" + toString(noise) + ", order=" + flowOrder + ", processors=1";
535             
536             m->mothurOutEndLine(); 
537             m->mothurOut("Running command: trim.flows(" + inputString + ")"); m->mothurOutEndLine(); 
538             m->mothurCalling = true;
539             
540             Command* trimFlowCommand = new TrimFlowsCommand(inputString);
541             trimFlowCommand->execute();
542             
543             if (m->control_pressed){ break; }
544             
545             temp = trimFlowCommand->getOutputFiles();
546             mergeOutputFileList(filenames, temp);
547             
548             delete trimFlowCommand;
549             m->mothurCalling = false;
550             
551             
552             string fileFileName = "";
553             flowFile = "";
554             if (oligos != "") { 
555                 it = temp.find("file");
556                 if (it != temp.end()) {  if ((it->second).size() != 0) { fileFileName = (it->second)[0];  } }
557                 else {  m->mothurOut("[ERROR]: trim.flows did not create a file file, quitting.\n"); m->control_pressed = true; break;  }
558             }else {
559                 vector<string> flowFiles;
560                 it = temp.find("flow");
561                 if (it != temp.end()) {  if ((it->second).size() != 0) { flowFiles = (it->second);  } }
562                 else {  m->mothurOut("[ERROR]: trim.flows did not create a flow file, quitting.\n"); m->control_pressed = true; break;  }
563                 
564                 for (int i = 0; i < flowFiles.size(); i++) {
565                     string end = flowFiles[i].substr(flowFiles[i].length()-9);
566                     if (end == "trim.flow") {
567                         flowFile = flowFiles[i]; i+=flowFiles.size(); //if we found the trim.flow file stop looking
568                     }
569                 }
570             }
571             
572             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;  }
573             
574             if (fileFileName != "") { inputString = "file=" + fileFileName; }
575             else { inputString = "flow=" + flowFile; }
576             
577             inputString += ", lookup=" + lookupFileName + ", cutoff=" + toString(cutoff); + ", maxiters=" + toString(maxIters);
578             if (large) { inputString += ", large=" + toString(largeSize); }
579             inputString += ", sigma=" +toString(sigma);
580             inputString += ", mindelta=" + toString(minDelta);  
581             inputString += ", order=" + flowOrder + ", processors=1";
582             
583             //run shhh.flows
584             m->mothurOutEndLine(); 
585             m->mothurOut("Running command: shhh.flows(" + inputString + ")"); m->mothurOutEndLine(); 
586             m->mothurCalling = true;
587             
588             Command* shhhFlowCommand = new ShhherCommand(inputString);
589             shhhFlowCommand->execute();
590             
591             if (m->control_pressed){ break; }
592             
593             temp = shhhFlowCommand->getOutputFiles();
594             mergeOutputFileList(filenames, temp);
595             
596             delete shhhFlowCommand;
597             m->mothurCalling = false;
598             
599             vector<string> fastaFiles;
600             vector<string> nameFiles;
601             it = temp.find("fasta");
602             if (it != temp.end()) {  if ((it->second).size() != 0) { fastaFiles = (it->second);  } }
603             else {  m->mothurOut("[ERROR]: shhh.flows did not create a fasta file, quitting.\n"); m->control_pressed = true; break;  }
604            
605             it = temp.find("name");
606             if (it != temp.end()) {  if ((it->second).size() != 0) { nameFiles = (it->second);  } }
607             else {  m->mothurOut("[ERROR]: shhh.flows did not create a name file, quitting.\n"); m->control_pressed = true; break;  }
608             
609             //find fasta and name files with the shortest name.  This is because if there is a composite name it will be the shortest.
610             fastaFile = fastaFiles[0];
611             for (int i = 1; i < fastaFiles.size(); i++) { if (fastaFiles[i].length() < fastaFile.length()) { fastaFile = fastaFiles[i]; } }
612             string nameFile = nameFiles[0];
613             for (int i = 1; i < nameFiles.size(); i++) { if (nameFiles[i].length() < nameFile.length()) { nameFile = nameFiles[i]; } }
614             
615             inputString = "fasta=" + fastaFile + ", name=" + nameFile;
616             if (oligos != "") { inputString += ", oligos=" + oligos; }
617             if (allFiles) { inputString += ", allfiles=t"; }
618             else { inputString += ", allfiles=f";  }
619             if (flip) { inputString += ", flip=t"; }
620             else { inputString += ", flip=f";  }
621             if (keepforward) { inputString += ", keepforward=t"; }
622             else { inputString += ", keepforward=f";  }
623             
624             
625             inputString += ", pdiffs=" + toString(pdiffs) + ", bdiffs=" + toString(bdiffs) + ", ldiffs=" + toString(ldiffs) + ", sdiffs=" + toString(sdiffs);
626             inputString += ", tdiffs=" + toString(tdiffs) + ", maxambig=" + toString(maxAmbig) + ", minlength=" + toString(minLength) + ", maxlength=" + toString(maxLength);
627             if (keepFirst != 0) { inputString += ", keepfirst=" + toString(keepFirst); }
628             if (removeLast != 0) { inputString += ", removelast=" + toString(removeLast); }
629             inputString += ", processors=1";
630             
631             //run trim.seqs
632             m->mothurOutEndLine(); 
633             m->mothurOut("Running command: trim.seqs(" + inputString + ")"); m->mothurOutEndLine(); 
634             m->mothurCalling = true;
635             
636             Command* trimseqsCommand = new TrimSeqsCommand(inputString);
637             trimseqsCommand->execute();
638             
639             if (m->control_pressed){ break; }
640             
641             temp = trimseqsCommand->getOutputFiles();
642             mergeOutputFileList(filenames, temp);
643             
644             delete trimseqsCommand;
645             m->mothurCalling = false;
646             
647             it = temp.find("fasta");
648             if (it != temp.end()) {  if ((it->second).size() != 0) { fastaFiles = (it->second);  } }
649             else {  m->mothurOut("[ERROR]: trim.seqs did not create a fasta file, quitting.\n"); m->control_pressed = true; break;  }
650             
651             for (int i = 0; i < fastaFiles.size(); i++) {
652                 string end = fastaFiles[i].substr(fastaFiles[i].length()-10);
653                 if (end == "trim.fasta") {
654                     fastaFile = fastaFiles[i]; i+=fastaFiles.size(); //if we found the trim.fasta file stop looking
655                 }
656             }
657             
658             it = temp.find("name");
659             if (it != temp.end()) {  if ((it->second).size() != 0) { nameFiles = (it->second);  } }
660             else {  m->mothurOut("[ERROR]: trim.seqs did not create a name file, quitting.\n"); m->control_pressed = true; break;  }
661             
662             for (int i = 0; i < nameFiles.size(); i++) {
663                 string end = nameFiles[i].substr(nameFiles[i].length()-10);
664                 if (end == "trim.names") {
665                     nameFile = nameFiles[i]; i+=nameFiles.size(); //if we found the trim.names file stop looking
666                 }
667             }
668             
669             vector<string> groupFiles;
670             string groupFile = "";
671             if (makeGroup) {
672                 it = temp.find("group");
673                 if (it != temp.end()) {  if ((it->second).size() != 0) { groupFiles = (it->second);  } }
674             
675                 //find group file with the shortest name.  This is because if there is a composite group file it will be the shortest.
676                 groupFile = groupFiles[0];
677                 for (int i = 1; i < groupFiles.size(); i++) { if (groupFiles[i].length() < groupFile.length()) { groupFile = groupFiles[i]; } }
678             }
679             
680             inputString = "fasta=" + fastaFile + ", processors=1, name=" + nameFile;
681             m->mothurOutEndLine(); 
682             m->mothurOut("Running command: summary.seqs(" + inputString + ")"); m->mothurOutEndLine(); 
683             m->mothurCalling = true;
684             
685             summarySeqsCommand = new SeqSummaryCommand(inputString);
686             summarySeqsCommand->execute();
687             
688             if (m->control_pressed){ break; }
689             
690             temp = summarySeqsCommand->getOutputFiles();
691             mergeOutputFileList(filenames, temp);
692             
693             delete summarySeqsCommand;
694             m->mothurCalling = false;
695             
696             m->mothurOutEndLine(); 
697             m->mothurOut("/******************************************/"); m->mothurOutEndLine(); 
698             
699             if (append) {
700                 m->appendFiles(fastaFile, fasta);
701                 m->appendFiles(nameFile, name);
702                 if (makeGroup) { m->appendFiles(groupFile, group);  }
703             }
704             count++;
705             
706             for (it = filenames.begin(); it != filenames.end(); it++) {
707                 for (int i = 0; i < (it->second).size(); i++) {
708                     outputNames.push_back((it->second)[i]); outputTypes[it->first].push_back((it->second)[i]);
709                 }
710             }
711         }
712         
713         return count;
714     }
715         catch(exception& e) {
716                 m->errorOut(e, "SffMultipleCommand", "driver");
717                 exit(1);
718         }
719 }
720 //**********************************************************************************************************************
721 int SffMultipleCommand::mergeOutputFileList(map<string, vector<string> >& files, map<string, vector<string> >& temp){
722     try {
723         map<string, vector<string> >::iterator it;
724         for (it = temp.begin(); it != temp.end(); it++) {
725             map<string, vector<string> >::iterator it2 = files.find(it->first);
726             if (it2 == files.end()) { //we do not already have this type so just add it
727                 files[it->first] = it->second;
728             }else { //merge them
729                 for (int i = 0; i < (it->second).size(); i++) {
730                     files[it->first].push_back((it->second)[i]);
731                 }
732             }
733         }
734         
735         return 0;
736     }
737         catch(exception& e) {
738                 m->errorOut(e, "SffMultipleCommand", "mergeOutputFileList");
739                 exit(1);
740         }
741 }
742 //**********************************************************************************************************************
743 int SffMultipleCommand::createProcesses(vector<string> sffFiles, vector<string> oligosFiles, string fasta, string name, string group){
744     try {
745         vector<int> processIDS;
746                 int process = 1;
747                 int num = 0;
748                                 
749                 //divide the groups between the processors
750                 vector<linePair> lines;
751         vector<int> numFilesToComplete;
752                 int numFilesPerProcessor = sffFiles.size() / processors;
753                 for (int i = 0; i < processors; i++) {
754                         int startIndex =  i * numFilesPerProcessor;
755                         int endIndex = (i+1) * numFilesPerProcessor;
756                         if(i == (processors - 1)){      endIndex = sffFiles.size();     }
757                         lines.push_back(linePair(startIndex, endIndex));
758             numFilesToComplete.push_back((endIndex-startIndex));
759                 }
760                 
761 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)          
762                 
763                 //loop through and create all the processes you want
764                 while (process != processors) {
765                         int pid = fork();
766                         
767                         if (pid > 0) {
768                                 processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
769                                 process++;
770                         }else if (pid == 0){
771                                 num = driver(sffFiles, oligosFiles, lines[process].start, lines[process].end, fasta + toString(getpid()) + ".temp", name  + toString(getpid()) + ".temp", group  + toString(getpid()) + ".temp");
772                 
773                 //pass numSeqs to parent
774                                 ofstream out;
775                                 string tempFile = toString(getpid()) + ".num.temp";
776                                 m->openOutputFile(tempFile, out);
777                                 out << num << '\t' << outputNames.size() << endl;
778                 for (int i = 0; i < outputNames.size(); i++) {  out << outputNames[i] << endl;  }
779                                 out.close();
780                 
781                                 exit(0);
782                         }else { 
783                                 m->mothurOut("[ERROR]: unable to spawn the necessary processes."); m->mothurOutEndLine(); 
784                                 for (int i = 0; i < processIDS.size(); i++) { kill (processIDS[i], SIGINT); }
785                                 exit(0);
786                         }
787                 }
788                 
789                 //do my part
790                 num = driver(sffFiles, oligosFiles, lines[0].start, lines[0].end, fasta, name, group);
791                 
792                 //force parent to wait until all the processes are done
793                 for (int i=0;i<processIDS.size();i++) { 
794                         int temp = processIDS[i];
795                         wait(&temp);
796                 }
797         
798         for (int i=0;i<processIDS.size();i++) { 
799             ifstream in;
800                         string tempFile = toString(processIDS[i]) + ".num.temp";
801                         m->openInputFile(tempFile, in);
802                         if (!in.eof()) { 
803                 int tempNum = 0; int outputNamesSize = 0; 
804                 in >> tempNum >> outputNamesSize; m->gobble(in);
805                 for (int j = 0; j < outputNamesSize; j++) {
806                     string tempName;
807                     in >> tempName; m->gobble(in);
808                     outputNames.push_back(tempName);
809                 }
810                 if (tempNum != numFilesToComplete[i+1]) {
811                     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");
812                 }
813             }
814                         in.close(); m->mothurRemove(tempFile);
815             
816             if (append) {
817                 m->appendFiles(fasta+toString(processIDS[i])+".temp", fasta);   m->mothurRemove(fasta+toString(processIDS[i])+".temp");
818                 m->appendFiles(name+toString(processIDS[i])+".temp", name);     m->mothurRemove(name+toString(processIDS[i])+".temp");
819                 if (makeGroup) { m->appendFiles(group+toString(processIDS[i])+".temp", group);  m->mothurRemove(group+toString(processIDS[i])+".temp"); }
820             }
821         }
822 #endif
823         return 0;
824         
825     }
826         catch(exception& e) {
827                 m->errorOut(e, "ShhherCommand", "createProcesses");
828                 exit(1);
829         }
830 }
831 //**********************************************************************************************************************
832
833
834
835