]> git.donarmstrong.com Git - mothur.git/blob - sharedcommand.cpp
added classify.shared command and random forest files. added count file to pcr.seqs...
[mothur.git] / sharedcommand.cpp
1 /*
2  *  sharedcommand.cpp
3  *  Dotur
4  *
5  *  Created by Sarah Westcott on 1/2/09.
6  *  Copyright 2009 Schloss Lab UMASS Amherst. All rights reserved.
7  *
8  */
9
10 #include "sharedcommand.h"
11 #include "sharedutilities.h"
12 #include "counttable.h"
13
14 //********************************************************************************************************************
15 //sorts lowest to highest
16 inline bool compareSharedRabunds(SharedRAbundVector* left, SharedRAbundVector* right){
17         return (left->getGroup() < right->getGroup());  
18 }
19 //**********************************************************************************************************************
20 vector<string> SharedCommand::setParameters(){  
21         try {
22         CommandParameter pbiom("biom", "InputTypes", "", "", "BiomListGroup", "BiomListGroup", "none",false,false); parameters.push_back(pbiom);
23                 CommandParameter plist("list", "InputTypes", "", "", "BiomListGroup", "BiomListGroup", "ListGroup",false,false); parameters.push_back(plist);
24         CommandParameter pcount("count", "InputTypes", "", "", "", "GroupCount", "",false,false); parameters.push_back(pcount);
25                 CommandParameter pgroup("group", "InputTypes", "", "", "none", "GroupCount", "ListGroup",false,false); parameters.push_back(pgroup);
26                 //CommandParameter pordergroup("ordergroup", "InputTypes", "", "", "none", "none", "none",false,false); parameters.push_back(pordergroup);
27                 CommandParameter plabel("label", "String", "", "", "", "", "",false,false); parameters.push_back(plabel);
28                 CommandParameter pgroups("groups", "String", "", "", "", "", "",false,false); parameters.push_back(pgroups);
29                 CommandParameter pinputdir("inputdir", "String", "", "", "", "", "",false,false); parameters.push_back(pinputdir);
30                 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "",false,false); parameters.push_back(poutputdir);
31                 
32                 vector<string> myArray;
33                 for (int i = 0; i < parameters.size(); i++) {   myArray.push_back(parameters[i].name);          }
34                 return myArray;
35         }
36         catch(exception& e) {
37                 m->errorOut(e, "SharedCommand", "setParameters");
38                 exit(1);
39         }
40 }
41 //**********************************************************************************************************************
42 string SharedCommand::getHelpString(){  
43         try {
44                 string helpString = "";
45                 helpString += "The make.shared command reads a list and group file or a biom file and creates a shared file. If a list and group are provided a rabund file is created for each group.\n";
46                 helpString += "The make.shared command parameters are list, group, biom, groups, count and label. list and group or count are required unless a current file is available or you provide a biom file.\n";
47         helpString += "The count parameter allows you to provide a count file containing the group info for the list file.\n";
48                 helpString += "The groups parameter allows you to indicate which groups you want to include, group names should be separated by dashes. ex. groups=A-B-C. Default is all groups in your groupfile.\n";
49                 helpString += "The label parameter is only valid with the list and group option and allows you to indicate which labels you want to include, label names should be separated by dashes. Default is all labels in your list file.\n";
50                 //helpString += "The ordergroup parameter allows you to indicate the order of the groups in the sharedfile, by default the groups are listed alphabetically.\n";
51                 return helpString;
52         }
53         catch(exception& e) {
54                 m->errorOut(e, "SharedCommand", "getHelpString");
55                 exit(1);
56         }
57 }
58 //**********************************************************************************************************************
59 string SharedCommand::getOutputFileNameTag(string type, string inputName=""){   
60         try {
61         string outputFileName = "";
62                 map<string, vector<string> >::iterator it;
63         
64         //is this a type this command creates
65         it = outputTypes.find(type);
66         if (it == outputTypes.end()) {  m->mothurOut("[ERROR]: this command doesn't create a " + type + " output file.\n"); }
67         else {
68             if (type == "shared")            {   outputFileName =  "shared";   }
69             else if (type == "rabund")    {   outputFileName =  "rabund";   }
70             else if (type == "group")        {   outputFileName =  "groups";   }
71             else { m->mothurOut("[ERROR]: No definition for type " + type + " output file tag.\n"); m->control_pressed = true;  }
72         }
73         return outputFileName;
74         }
75         catch(exception& e) {
76                 m->errorOut(e, "SharedCommand", "getOutputFileNameTag");
77                 exit(1);
78         }
79 }
80
81 //**********************************************************************************************************************
82 SharedCommand::SharedCommand(){ 
83         try {
84                 abort = true; calledHelp = true; 
85                 setParameters();
86                 //initialize outputTypes
87                 vector<string> tempOutNames;
88                 outputTypes["rabund"] = tempOutNames;
89                 outputTypes["shared"] = tempOutNames;
90                 outputTypes["group"] = tempOutNames;
91         }
92         catch(exception& e) {
93                 m->errorOut(e, "SharedCommand", "SharedCommand");
94                 exit(1);
95         }
96 }
97 //**********************************************************************************************************************
98 SharedCommand::SharedCommand(string option)  {
99         try {
100                 abort = false; calledHelp = false;   
101                 allLines = 1;
102                 
103                 //allow user to run help
104                 if(option == "help") { help(); abort = true; calledHelp = true; }
105                 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
106                 
107                 else {
108                         
109                          vector<string> myArray = setParameters();
110                          
111                          OptionParser parser(option);
112                          map<string, string> parameters = parser.getParameters();
113                          
114                          ValidParameters validParameter;
115                          map<string, string>::iterator it;
116                          
117                          //check to make sure all parameters are valid for command
118                          for (it = parameters.begin(); it != parameters.end(); it++) { 
119                                  if (validParameter.isValidParameter(it->first, myArray, it->second) != true) {  abort = true;  }
120                          }
121                          
122                          //if the user changes the input directory command factory will send this info to us in the output parameter 
123                         string inputDir = validParameter.validFile(parameters, "inputdir", false);              
124                          if (inputDir == "not found"){  inputDir = "";          }
125                          else {
126                                  string path;
127                                  it = parameters.find("list");
128                                  //user has given a template file
129                                  if(it != parameters.end()){ 
130                                          path = m->hasPath(it->second);
131                                          //if the user has not given a path then, add inputdir. else leave path alone.
132                                          if (path == "") {      parameters["list"] = inputDir + it->second;             }
133                                  }
134                          
135                                  it = parameters.find("group");
136                                  //user has given a template file
137                                  if(it != parameters.end()){ 
138                                          path = m->hasPath(it->second);
139                                          //if the user has not given a path then, add inputdir. else leave path alone.
140                                          if (path == "") {      parameters["group"] = inputDir + it->second;            }
141                                  }
142                          
143                                  it = parameters.find("count");
144                                  //user has given a template file
145                                  if(it != parameters.end()){ 
146                                          path = m->hasPath(it->second);
147                                          //if the user has not given a path then, add inputdir. else leave path alone.
148                                          if (path == "") {      parameters["count"] = inputDir + it->second;            }
149                                  }
150                  
151                  it = parameters.find("biom");
152                                  //user has given a template file
153                                  if(it != parameters.end()){ 
154                                          path = m->hasPath(it->second);
155                                          //if the user has not given a path then, add inputdir. else leave path alone.
156                                          if (path == "") {      parameters["biom"] = inputDir + it->second;             }
157                                  }
158                          }
159                          
160              vector<string> tempOutNames;
161              outputTypes["rabund"] = tempOutNames;
162              outputTypes["shared"] = tempOutNames;
163              outputTypes["group"] = tempOutNames;
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                          //check for required parameters
169                          listfile = validParameter.validFile(parameters, "list", true);
170                          if (listfile == "not open") { listfile = ""; abort = true; }
171                          else if (listfile == "not found") { listfile = "";  }
172                          else { m->setListFile(listfile); }     
173             
174              biomfile = validParameter.validFile(parameters, "biom", true);
175              if (biomfile == "not open") { biomfile = ""; abort = true; }
176              else if (biomfile == "not found") { biomfile = "";  }
177              else { m->setBiomFile(biomfile); }         
178                                                         
179                          ordergroupfile = validParameter.validFile(parameters, "ordergroup", true);
180                          if (ordergroupfile == "not open") { abort = true; }    
181                          else if (ordergroupfile == "not found") { ordergroupfile = ""; }
182                                                  
183                          groupfile = validParameter.validFile(parameters, "group", true);
184                          if (groupfile == "not open") { groupfile = ""; abort = true; } 
185                          else if (groupfile == "not found") { groupfile = ""; }
186                          else {  m->setGroupFile(groupfile); }
187             
188              countfile = validParameter.validFile(parameters, "count", true);
189              if (countfile == "not open") { countfile = ""; abort = true; }     
190              else if (countfile == "not found") { countfile = ""; }
191              else {  
192                  m->setCountTableFile(countfile); 
193                  CountTable temp;
194                  if (!temp.testGroups(countfile)) { m->mothurOut("[ERROR]: Your count file does not have group info, aborting."); m->mothurOutEndLine(); abort=true; }
195              }
196                          
197             if ((biomfile == "") && (listfile == "")) { 
198                                 //is there are current file available for either of these?
199                                 //give priority to list, then biom
200                                 listfile = m->getListFile(); 
201                                 if (listfile != "") {  m->mothurOut("Using " + listfile + " as input file for the list parameter."); m->mothurOutEndLine(); }
202                                 else { 
203                                         biomfile = m->getBiomFile(); 
204                                         if (biomfile != "") {  m->mothurOut("Using " + biomfile + " as input file for the biom parameter."); m->mothurOutEndLine(); }
205                                         else { 
206                                                 m->mothurOut("No valid current files. You must provide a list or biom file before you can use the make.shared command."); m->mothurOutEndLine(); 
207                                                 abort = true;
208                                         }
209                                 }
210                         }
211                         else if ((biomfile != "") && (listfile != "")) { m->mothurOut("When executing a make.shared command you must enter ONLY ONE of the following: list or biom."); m->mothurOutEndLine(); abort = true; }
212                         
213                         if (listfile != "") {
214                                 if ((groupfile == "") && (countfile == "")) { 
215                                         groupfile = m->getGroupFile(); 
216                                         if (groupfile != "") {  m->mothurOut("Using " + groupfile + " as input file for the group parameter."); m->mothurOutEndLine(); }
217                                         else { 
218                                                 countfile = m->getCountTableFile(); 
219                         if (countfile != "") {  m->mothurOut("Using " + countfile + " as input file for the count parameter."); m->mothurOutEndLine(); }
220                         else { 
221                             m->mothurOut("You need to provide a groupfile or countfile if you are going to use the list format."); m->mothurOutEndLine(); 
222                             abort = true; 
223                         }       
224                                         }       
225                                 }
226                         }
227
228                         
229                          string groups = validParameter.validFile(parameters, "groups", false);                 
230                          if (groups == "not found") { groups = ""; }
231                          else { 
232                                  m->splitAtDash(groups, Groups);
233                                  m->setGroups(Groups);
234                          }
235                          
236                          //check for optional parameter and set defaults
237                          // ...at some point should added some additional type checking...
238                          string label = validParameter.validFile(parameters, "label", false);                   
239                          if (label == "not found") { label = ""; }
240                          else { 
241                                  if(label != "all") {  m->splitAtDash(label, labels);  allLines = 0;  }
242                                  else { allLines = 1;  }
243                          }
244                 }
245                 
246         }
247         catch(exception& e) {
248                 m->errorOut(e, "SharedCommand", "SharedCommand");
249                 exit(1);
250         }
251 }
252 //**********************************************************************************************************************
253
254 int SharedCommand::execute(){
255         try {
256                 
257                 if (abort == true) { if (calledHelp) { return 0; }  return 2;   }
258                         
259                 //getting output filename
260         string filename = "";
261                 if (listfile != "") { filename = listfile; }
262         else { filename = biomfile; }
263                 
264                 if (outputDir == "") { outputDir += m->hasPath(filename); }
265                 
266                 filename = outputDir + m->getRootName(m->getSimpleName(filename));
267                 filename = filename + getOutputFileNameTag("shared");
268                 outputNames.push_back(filename); outputTypes["shared"].push_back(filename);
269                 
270         if (listfile != "") {  createSharedFromListGroup(filename);  }
271         else {   createSharedFromBiom(filename);  }
272         
273         if (m->control_pressed) { for (int i = 0; i < outputNames.size(); i++) {        m->mothurRemove(outputNames[i]); }  }
274         
275                 //set rabund file as new current rabundfile
276                 string current = "";
277                 itTypes = outputTypes.find("rabund");
278                 if (itTypes != outputTypes.end()) {
279                         if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setRabundFile(current); }
280                 }
281                 
282                 itTypes = outputTypes.find("shared");
283                 if (itTypes != outputTypes.end()) {
284                         if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setSharedFile(current); }
285                 }       
286                 
287                 itTypes = outputTypes.find("group");
288                 if (itTypes != outputTypes.end()) {
289                         if ((itTypes->second).size() != 0) { current = (itTypes->second)[0]; m->setGroupFile(current); }
290                 }
291                 
292                 m->mothurOutEndLine();
293                 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
294                 for (int i = 0; i < outputNames.size(); i++) {  m->mothurOut(outputNames[i]); m->mothurOutEndLine();    }
295                 m->mothurOutEndLine();
296                 
297                 return 0;
298         }
299         catch(exception& e) {
300                 m->errorOut(e, "SharedCommand", "execute");
301                 exit(1);
302         }
303 }
304 //**********************************************************************************************************************
305 int SharedCommand::createSharedFromBiom(string filename) {
306         try {
307         ofstream out;
308         m->openOutputFile(filename, out);
309         
310         /*{
311             "id":"/Users/SarahsWork/Desktop/release/temp.job2.shared-unique",
312             "format": "Biological Observation Matrix 0.9.1",
313             "format_url": "http://biom-format.org",
314             "type": "OTU table",
315             "generated_by": "mothur1.24.0",
316             "date": "Tue Apr 17 13:12:07 2012", */
317         
318         ifstream in;
319         m->openInputFile(biomfile, in);
320          
321         string matrixFormat = "";
322         int numRows = 0;
323         int numCols = 0;
324         int shapeNumRows = 0;
325         int shapeNumCols = 0;
326         vector<string> otuNames;
327         vector<string> groupNames;
328         map<string, string> fileLines;
329         vector<string> names;
330         int countOpenBrace = 0;
331         int countClosedBrace = 0;
332         int openParen = -1; //account for opening brace
333         int closeParen = 0;
334         bool ignoreCommas = false;
335         bool atComma = false;
336         string line = "";
337         string matrixElementType = "";
338         
339         while (!in.eof()) { //split file by tags, so each "line" will have something like "id":"/Users/SarahsWork/Desktop/release/final.tx.1.subsample.1.pick.shared-1"
340             if (m->control_pressed) { break; }
341             
342             char c = in.get(); m->gobble(in);
343             
344             if (c == '[')               { countOpenBrace++;     }
345             else if (c == ']')          { countClosedBrace++;   }
346             else if (c == '{')          { openParen++;          }
347             else if (c == '}')          { closeParen++;         }
348             else if ((!ignoreCommas) && (c == ','))          { atComma = true;       }  
349             
350             if ((countOpenBrace != countClosedBrace) && (countOpenBrace != countClosedBrace)) { ignoreCommas = true;  }
351             else if ((countOpenBrace == countClosedBrace) && (countOpenBrace == countClosedBrace)) { ignoreCommas = false;  }
352             if (atComma && !ignoreCommas) { 
353                 if (fileLines.size() == 0) { //clip first {
354                     line = line.substr(1);
355                 }
356                 string tag = getTag(line);
357                 fileLines[tag] = line;
358                 line = "";
359                 atComma = false;
360                 ignoreCommas = false;
361                 
362             }else {  line += c;  }
363             
364         }
365         if (line != "") {
366             line = line.substr(0, line.length()-1);
367             string tag = getTag(line);
368             fileLines[tag] = line;
369         }
370         in.close();
371         
372         map<string, string>::iterator it;
373         it = fileLines.find("type");
374         if (it == fileLines.end()) { m->mothurOut("[ERROR]: you file does not have a type provided.\n"); }
375         else {
376             string thisLine = it->second;
377             string type = getTag(thisLine);
378             if ((type != "OTU table") && (type != "OTUtable")) { m->mothurOut("[ERROR]: " + type + " is not a valid biom type for mothur. Only type allowed is OTU table.\n"); m->control_pressed = true;  }
379         }
380         
381         if (m->control_pressed) { out.close(); m->mothurRemove(filename); return 0; }
382         
383         it = fileLines.find("matrix_type");
384         if (it == fileLines.end()) { m->mothurOut("[ERROR]: you file does not have a matrix_type provided.\n"); }
385         else {
386             string thisLine = it->second;
387             matrixFormat = getTag(thisLine);
388             if ((matrixFormat != "sparse") && (matrixFormat != "dense")) { m->mothurOut("[ERROR]: " + matrixFormat + " is not a valid biom matrix_type for mothur. Types allowed are sparse and dense.\n"); m->control_pressed = true; }
389         }
390         
391         if (m->control_pressed) { out.close(); m->mothurRemove(filename); return 0; }
392         
393         it = fileLines.find("matrix_element_type");
394         if (it == fileLines.end()) { m->mothurOut("[ERROR]: you file does not have a matrix_element_type provided.\n"); }
395         else {
396             string thisLine = it->second;
397             matrixElementType = getTag(thisLine);
398             if ((matrixElementType != "int") && (matrixElementType != "float")) { m->mothurOut("[ERROR]: " + matrixElementType + " is not a valid biom matrix_element_type for mothur. Types allowed are int and float.\n"); m->control_pressed = true; }
399             if (matrixElementType == "float") { m->mothurOut("[WARNING]: the shared file only uses integers, any float values will be rounded down to the nearest integer.\n"); }
400         }
401         
402         if (m->control_pressed) { out.close(); m->mothurRemove(filename); return 0; }
403         
404         it = fileLines.find("rows");
405         if (it == fileLines.end()) { m->mothurOut("[ERROR]: you file does not have a rows provided.\n"); }
406         else {
407             string thisLine = it->second;
408             otuNames = readRows(thisLine, numRows);  
409         }
410         
411         if (m->control_pressed) { out.close(); m->mothurRemove(filename); return 0; }
412         
413         it = fileLines.find("columns");
414         if (it == fileLines.end()) { m->mothurOut("[ERROR]: you file does not have a columns provided.\n"); }
415         else {
416             string thisLine = it->second;
417             //read sample names
418             groupNames = readRows(thisLine, numCols); 
419             
420             //if users selected groups, then remove the groups not wanted.
421             SharedUtil util;
422             vector<string> Groups = m->getGroups();
423             vector<string> allGroups = groupNames;
424             util.setGroups(Groups, allGroups);
425             m->setGroups(Groups);
426             
427             //fill filehandles with neccessary ofstreams
428             int i;
429             ofstream* temp;
430             for (i=0; i<Groups.size(); i++) {
431                 temp = new ofstream;
432                 filehandles[Groups[i]] = temp;
433             }
434             
435             //set fileroot
436             fileroot = outputDir + m->getRootName(m->getSimpleName(biomfile));
437             
438             //clears file before we start to write to it below
439             for (int i=0; i<Groups.size(); i++) {
440                 m->mothurRemove((fileroot + Groups[i] + ".rabund"));
441                 outputNames.push_back((fileroot + Groups[i] + ".rabund"));
442                 outputTypes["rabund"].push_back((fileroot + Groups[i] + ".rabund"));
443             }
444         }
445         
446         if (m->control_pressed) { for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) { delete it3->second; } out.close(); m->mothurRemove(filename); return 0; }
447
448         it = fileLines.find("shape");
449         if (it == fileLines.end()) { m->mothurOut("[ERROR]: you file does not have a shape provided.\n"); }
450         else {
451             string thisLine = it->second;
452             getDims(thisLine, shapeNumRows, shapeNumCols);
453             
454             //check shape
455             if (shapeNumCols != numCols) { m->mothurOut("[ERROR]: shape indicates " + toString(shapeNumCols) + " columns, but I only read " + toString(numCols) + " columns.\n"); m->control_pressed = true; }
456             
457             if (shapeNumRows != numRows) { m->mothurOut("[ERROR]: shape indicates " + toString(shapeNumRows) + " rows, but I only read " + toString(numRows) + " rows.\n"); m->control_pressed = true; }
458         }
459         
460         if (m->control_pressed) { for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) { delete it3->second; } out.close(); m->mothurRemove(filename); return 0; }
461         
462         it = fileLines.find("data");
463         if (it == fileLines.end()) { m->mothurOut("[ERROR]: you file does not have a data provided.\n"); }
464         else {
465             string thisLine = it->second;
466             m->currentBinLabels = otuNames;
467             
468             //read data
469             vector<SharedRAbundVector*> lookup = readData(matrixFormat, thisLine, matrixElementType, groupNames, otuNames.size());
470             
471             m->mothurOutEndLine(); m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
472             lookup[0]->printHeaders(out); 
473             printSharedData(lookup, out);
474         }
475         
476         for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) { delete it3->second; } 
477         out.close();
478         
479         if (m->control_pressed) {  m->mothurRemove(filename); return 0; }
480
481         return 0;
482     }
483         catch(exception& e) {
484                 m->errorOut(e, "SharedCommand", "createSharedFromBiom");
485                 exit(1);
486         }
487 }
488 //**********************************************************************************************************************
489 vector<SharedRAbundVector*> SharedCommand::readData(string matrixFormat, string line, string matrixElementType, vector<string>& groupNames, int numOTUs) {
490         try {
491         
492         vector<SharedRAbundVector*> lookup; 
493         
494         //creates new sharedRAbunds
495         for (int i = 0; i < groupNames.size(); i++) {
496             SharedRAbundVector* temp = new SharedRAbundVector(numOTUs); //sets all abunds to 0
497             temp->setLabel("dummy");
498             temp->setGroup(groupNames[i]);
499             lookup.push_back(temp);
500         }
501         
502         bool dataStart = false;
503         bool inBrackets = false;
504         string num = "";
505         vector<int> nums;
506         int otuCount = 0;
507         for (int i = 0; i < line.length(); i++) {
508             
509             if (m->control_pressed) { return lookup; }
510             
511             //look for opening [ to indicate data is starting
512             if ((line[i] == '[') && (!dataStart)) { dataStart = true; i++;  if (!(i < line.length())) { break; } }
513             else if ((line[i] == ']') && dataStart && (!inBrackets)) { break; } //we are done reading data
514                 
515             if (dataStart) {
516                 if ((line[i] == '[') && (!inBrackets)) { inBrackets = true; i++;  if (!(i < line.length())) { break; } }
517                 else if ((line[i] == ']') && (inBrackets)) { 
518                     inBrackets = false; 
519                     int temp;
520                     float temp2;
521                     if (matrixElementType == "float") { m->mothurConvert(num, temp2); temp = (int)temp2; }
522                     else { m->mothurConvert(num, temp); }
523                     nums.push_back(temp);
524                     num = "";
525                     
526                     //save info to vectors
527                     if (matrixFormat == "dense") {
528                         
529                         //sanity check
530                         if (nums.size() != lookup.size()) { m->mothurOut("[ERROR]: trouble parsing OTU data.  OTU " + toString(otuCount) + " causing errors.\n"); m->control_pressed = true; }
531                         
532                         //set abundances for this otu
533                         //nums contains [abundSample0, abundSample1, abundSample2, ...] for current OTU
534                         for (int j = 0; j < lookup.size(); j++) { lookup[j]->set(otuCount, nums[j], groupNames[j]); }
535                         
536                         otuCount++;
537                     }else {
538                         //sanity check
539                         if (nums.size() != 3) { m->mothurOut("[ERROR]: trouble parsing OTU data.\n"); m->control_pressed = true; }
540                         
541                         //nums contains [otuNum, sampleNum, abundance]
542                         lookup[nums[1]]->set(nums[0], nums[2], groupNames[nums[1]]);
543                     }
544                     nums.clear();
545                 }
546                 
547                 if (inBrackets) {
548                     if (line[i] == ',') {
549                         int temp;
550                         m->mothurConvert(num, temp);
551                         nums.push_back(temp);
552                         num = "";
553                     }else { if (!isspace(line[i])) { num += line[i]; }  }
554                 }
555             }
556         }
557         
558         SharedUtil util;
559         
560                 bool remove = false;
561                 for (int i = 0; i < lookup.size(); i++) {
562                         //if this sharedrabund is not from a group the user wants then delete it.
563                         if (util.isValidGroup(lookup[i]->getGroup(), m->getGroups()) == false) { 
564                                 remove = true;
565                                 delete lookup[i]; lookup[i] = NULL;
566                                 lookup.erase(lookup.begin()+i); 
567                                 i--; 
568                         }
569                 }
570                 
571                 if (remove) { eliminateZeroOTUS(lookup); }
572
573         
574         return lookup;
575     }
576         catch(exception& e) {
577                 m->errorOut(e, "SharedCommand", "readData");
578                 exit(1);
579         }
580 }
581 //**********************************************************************************************************************
582 int SharedCommand::eliminateZeroOTUS(vector<SharedRAbundVector*>& thislookup) {
583     try {
584         
585         vector<SharedRAbundVector*> newLookup;
586         for (int i = 0; i < thislookup.size(); i++) {
587             SharedRAbundVector* temp = new SharedRAbundVector();
588             temp->setLabel(thislookup[i]->getLabel());
589             temp->setGroup(thislookup[i]->getGroup());
590             newLookup.push_back(temp);
591         }
592         
593         //for each bin
594         vector<string> newBinLabels;
595         string snumBins = toString(thislookup[0]->getNumBins());
596         for (int i = 0; i < thislookup[0]->getNumBins(); i++) {
597             if (m->control_pressed) { for (int j = 0; j < newLookup.size(); j++) {  delete newLookup[j];  } return 0; }
598             
599             //look at each sharedRabund and make sure they are not all zero
600             bool allZero = true;
601             for (int j = 0; j < thislookup.size(); j++) {
602                 if (thislookup[j]->getAbundance(i) != 0) { allZero = false;  break;  }
603             }
604             
605             //if they are not all zero add this bin
606             if (!allZero) {
607                 for (int j = 0; j < thislookup.size(); j++) {
608                     newLookup[j]->push_back(thislookup[j]->getAbundance(i), thislookup[j]->getGroup());
609                 }
610                 
611                 //if there is a bin label use it otherwise make one
612                 string binLabel = "Otu";
613                 string sbinNumber = toString(i+1);
614                 if (sbinNumber.length() < snumBins.length()) { 
615                     int diff = snumBins.length() - sbinNumber.length();
616                     for (int h = 0; h < diff; h++) { binLabel += "0"; }
617                 }
618                 binLabel += sbinNumber; 
619                 if (i < m->currentBinLabels.size()) {  binLabel = m->currentBinLabels[i]; }
620                 
621                 newBinLabels.push_back(binLabel);
622             }
623         }
624         
625         for (int j = 0; j < thislookup.size(); j++) {  delete thislookup[j];  }
626         
627         thislookup = newLookup;
628         m->currentBinLabels = newBinLabels;
629         
630         return 0;
631         
632     }
633     catch(exception& e) {
634         m->errorOut(e, "SharedCommand", "eliminateZeroOTUS");
635         exit(1);
636     }
637 }
638 //**********************************************************************************************************************
639 int SharedCommand::getDims(string line, int& shapeNumRows, int& shapeNumCols) {
640         try {
641         //get shape
642         bool inBar = false;
643         string num = "";
644         
645         for (int i = 0; i < line.length(); i++) {
646             
647             //you want to ignore any ; until you reach the next '
648             if ((line[i] == '[') && (!inBar)) {  inBar = true; i++;  if (!(i < line.length())) { break; } } 
649             else if ((line[i] == ']') && (inBar)) {  
650                 inBar= false;  
651                 m->mothurConvert(num, shapeNumCols);
652                 break;
653             } 
654             
655             if (inBar) {  
656                 if (line[i] == ',') {
657                     m->mothurConvert(num, shapeNumRows);
658                     num = "";
659                 }else { if (!isspace(line[i])) { num += line[i]; }  }
660             }
661         }
662         
663         return 0;
664     }
665         catch(exception& e) {
666                 m->errorOut(e, "SharedCommand", "getDims");
667                 exit(1);
668         }
669 }
670 //**********************************************************************************************************************
671 vector<string> SharedCommand::readRows(string line, int& numRows) {
672         try {
673         /*"rows":[
674          {"id":"Otu01", "metadata":{"taxonomy":["Bacteria", "Bacteroidetes", "Bacteroidia", "Bacteroidales", "Porphyromonadaceae", "unclassified"], "bootstrap":[100, 100, 100, 100, 100, 100]}},
675          {"id":"Otu02", "metadata":{"taxonomy":["Bacteria", "Bacteroidetes", "Bacteroidia", "Bacteroidales", "Rikenellaceae", "Alistipes"], "bootstrap":[100, 100, 100, 100, 100, 100]}},
676          ...
677          ],*/
678         vector<string> names;
679         int countOpenBrace = 0;
680         int countClosedBrace = 0;
681         int openParen = 0;
682         int closeParen = 0;
683         string nextRow = "";
684         bool end = false;
685         
686         for (int i = 0; i < line.length(); i++) {
687             
688             if (m->control_pressed) { return names; }
689             
690             if (line[i] == '[')         { countOpenBrace++;     }
691             else if (line[i] == ']')    { countClosedBrace++;   }
692             else if (line[i] == '{')    { openParen++;          }
693             else if (line[i] == '}')    { closeParen++;         }
694             else if (openParen != 0)    { nextRow += line[i];   }  //you are reading the row info
695             
696             //you have reached the end of the rows info
697             if ((countOpenBrace == countClosedBrace) && (countClosedBrace != 0)) { end = true; break; }
698             if ((openParen == closeParen) && (closeParen != 0)) { //process row 
699                 numRows++;
700                 vector<string> items;
701                 m->splitAtChar(nextRow, items, ','); //parse by comma, will return junk for metadata but we aren't using that anyway
702                 string part = items[0]; items.clear();
703                 m->splitAtChar(part, items, ':'); //split part we want containing the ids
704                 string name = items[1];
705                 
706                 //remove "" if needed
707                 int pos = name.find("\"");
708                 if (pos != string::npos) {
709                     string newName = "";
710                     for (int k = 0; k < name.length(); k++) {
711                         if (name[k] != '\"') { newName += name[k]; }
712                     }
713                     name = newName;
714                 }
715                 names.push_back(name);
716                 nextRow = "";
717                 openParen = 0;
718                 closeParen = 0;
719             }
720         }
721         
722         return names;
723     }
724         catch(exception& e) {
725                 m->errorOut(e, "SharedCommand", "readRows");
726                 exit(1);
727         }
728 }
729 //**********************************************************************************************************************
730 //designed for things like "type": "OTU table", returns type 
731 string SharedCommand::getTag(string& line) {
732         try {
733         bool inQuotes = false;
734         string tag = "";
735         char c = '\"';
736         
737         for (int i = 0; i < line.length(); i++) {
738         
739             //you want to ignore any ; until you reach the next '
740                         if ((line[i] == c) && (!inQuotes)) {  inQuotes = true;  } 
741                         else if ((line[i] == c) && (inQuotes)) {  
742                 inQuotes= false;  
743                 line = line.substr(i+1);
744                 return tag;
745             } 
746             
747                         if (inQuotes) {  if (line[i] != c) { tag += line[i]; }  }
748         }
749         
750         return tag;
751     }
752         catch(exception& e) {
753                 m->errorOut(e, "SharedCommand", "getInfo");
754                 exit(1);
755         }
756 }
757 //**********************************************************************************************************************
758 int SharedCommand::createSharedFromListGroup(string filename) {
759         try {
760         ofstream out;
761         m->openOutputFile(filename, out);
762         
763         GroupMap* groupMap = NULL;
764         CountTable* countTable = NULL;
765         if (groupfile != "") {
766             groupMap = new GroupMap(groupfile);
767         
768             int groupError = groupMap->readMap();
769             if (groupError == 1) { delete groupMap; return 0; }
770             vector<string> allGroups = groupMap->getNamesOfGroups();
771             m->setAllGroups(allGroups);
772         }else{
773             countTable = new CountTable();
774             countTable->readTable(countfile);
775         }
776         
777         if (m->control_pressed) { return 0; }
778         
779         pickedGroups = false;
780         
781         //if hte user has not specified any groups then use them all
782         if (Groups.size() == 0) {
783             if (groupfile != "") { Groups = groupMap->getNamesOfGroups();  }
784             else {  Groups = countTable->getNamesOfGroups();  }
785             m->setGroups(Groups);
786         }else { pickedGroups = true; }
787         
788         //fill filehandles with neccessary ofstreams
789         int i;
790         ofstream* temp;
791         for (i=0; i<Groups.size(); i++) {
792             temp = new ofstream;
793             filehandles[Groups[i]] = temp;
794         }
795         
796         //set fileroot
797         fileroot = outputDir + m->getRootName(m->getSimpleName(listfile));
798         
799         //clears file before we start to write to it below
800         for (int i=0; i<Groups.size(); i++) {
801             m->mothurRemove((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));
802             outputNames.push_back((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));
803             outputTypes["rabund"].push_back((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));
804         }
805         
806         string errorOff = "no error";
807         
808         //if user provided an order file containing the order the shared file should be in read it
809         //if (ordergroupfile != "") { readOrderFile(); }
810         
811         InputData input(listfile, "shared");
812         SharedListVector* SharedList = input.getSharedListVector();
813         string lastLabel = SharedList->getLabel();
814         vector<SharedRAbundVector*> lookup; 
815         
816         if (m->control_pressed) { 
817             delete SharedList; if (groupMap != NULL) { delete groupMap; } if (countTable != NULL) { delete countTable; }
818             for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {  delete it3->second;  }
819             out.close(); m->mothurRemove(filename); 
820             for (int i=0; i<Groups.size(); i++) {  m->mothurRemove((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));              }
821             return 0; 
822         }
823         
824         //sanity check
825         vector<string> namesSeqs;
826         int numGroupNames = 0;
827         if (m->groupMode == "group") { namesSeqs = groupMap->getNamesSeqs(); numGroupNames = groupMap->getNumSeqs(); }
828         else { namesSeqs = countTable->getNamesOfSeqs(); numGroupNames = countTable->getNumUniqueSeqs(); }
829         int error = ListGroupSameSeqs(namesSeqs, SharedList);
830         
831         if ((!pickedGroups) && (SharedList->getNumSeqs() != numGroupNames)) {  //if the user has not specified any groups and their files don't match exit with error
832             m->mothurOut("Your group file contains " + toString(numGroupNames) + " sequences and list file contains " + toString(SharedList->getNumSeqs()) + " sequences. Please correct."); m->mothurOutEndLine(); m->control_pressed = true;
833             
834             out.close(); m->mothurRemove(filename); //remove blank shared file you made
835             
836             //delete memory
837             for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) { delete it3->second; }
838             delete SharedList; if (groupMap != NULL) { delete groupMap; } if (countTable != NULL) { delete countTable; }
839             return 0; 
840         }
841         
842         if (error == 1) { m->control_pressed = true; }
843         
844         //if user has specified groups make new groupfile for them
845         if ((pickedGroups) && (m->groupMode == "group")) { //make new group file
846             string groups = "";
847             if (m->getNumGroups() < 4) {
848                 for (int i = 0; i < m->getNumGroups(); i++) {
849                     groups += (m->getGroups())[i] + ".";
850                 }
851             }else { groups = "merge"; }
852             
853             string newGroupFile = outputDir + m->getRootName(m->getSimpleName(listfile)) + groups + getOutputFileNameTag("group");
854             outputTypes["group"].push_back(newGroupFile); 
855             outputNames.push_back(newGroupFile);
856             ofstream outGroups;
857             m->openOutputFile(newGroupFile, outGroups);
858             
859             vector<string> names = groupMap->getNamesSeqs();
860             string groupName;
861             for (int i = 0; i < names.size(); i++) {
862                 groupName = groupMap->getGroup(names[i]);
863                 if (isValidGroup(groupName, m->getGroups())) {
864                     outGroups << names[i] << '\t' << groupName << endl;
865                 }
866             }
867             outGroups.close();
868         }
869         
870         //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
871         set<string> processedLabels;
872         set<string> userLabels = labels;        
873         
874         while((SharedList != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
875             if (m->control_pressed) { 
876                 delete SharedList; if (groupMap != NULL) { delete groupMap; } if (countTable != NULL) { delete countTable; }
877                 for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {  delete it3->second;  }
878                 out.close(); m->mothurRemove(filename); 
879                 for (int i=0; i<Groups.size(); i++) {  m->mothurRemove((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));          }
880                 return 0; 
881             }
882             
883             if(allLines == 1 || labels.count(SharedList->getLabel()) == 1){
884                 
885                 lookup = SharedList->getSharedRAbundVector();
886                 
887                 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
888                 if (pickedGroups) { //check for otus with no seqs in them
889                     eliminateZeroOTUS(lookup);
890                 }
891                 
892                 if (m->control_pressed) { 
893                     delete SharedList; if (groupMap != NULL) { delete groupMap; } if (countTable != NULL) { delete countTable; }
894                     for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
895                     for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {  delete it3->second;  }
896                     out.close(); m->mothurRemove(filename); 
897                     for (int i=0; i<Groups.size(); i++) {  m->mothurRemove((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));              }
898                     return 0; 
899                 }
900                 
901                 if (!m->printedHeaders) { lookup[0]->printHeaders(out); }
902                 printSharedData(lookup, out); //prints info to the .shared file
903                 for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
904                 
905                 processedLabels.insert(SharedList->getLabel());
906                 userLabels.erase(SharedList->getLabel());
907             }
908             
909             if ((m->anyLabelsToProcess(SharedList->getLabel(), userLabels, errorOff) == true) && (processedLabels.count(lastLabel) != 1)) {
910                 string saveLabel = SharedList->getLabel();
911                 
912                 delete SharedList;
913                 SharedList = input.getSharedListVector(lastLabel); //get new list vector to process
914                 
915                 lookup = SharedList->getSharedRAbundVector();
916                 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
917                 if (pickedGroups) { //check for otus with no seqs in them
918                     eliminateZeroOTUS(lookup);
919                 }
920                 
921                 
922                 if (m->control_pressed) { 
923                     delete SharedList; if (groupMap != NULL) { delete groupMap; } if (countTable != NULL) { delete countTable; }
924                     for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
925                     for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {  delete it3->second;  }
926                     out.close(); m->mothurRemove(filename); 
927                     for (int i=0; i<Groups.size(); i++) {  m->mothurRemove((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));              }
928                     return 0; 
929                 }
930                 
931                 if (!m->printedHeaders) { lookup[0]->printHeaders(out); }
932                 printSharedData(lookup, out); //prints info to the .shared file
933                 for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
934                 
935                 processedLabels.insert(SharedList->getLabel());
936                 userLabels.erase(SharedList->getLabel());
937                 
938                 //restore real lastlabel to save below
939                 SharedList->setLabel(saveLabel);
940             }
941             
942             
943             lastLabel = SharedList->getLabel();
944             
945             delete SharedList;
946             SharedList = input.getSharedListVector(); //get new list vector to process
947         }
948         
949         //output error messages about any remaining user labels
950         set<string>::iterator it;
951         bool needToRun = false;
952         for (it = userLabels.begin(); it != userLabels.end(); it++) {  
953             if (processedLabels.count(lastLabel) != 1) {
954                 needToRun = true;
955             }
956         }
957         
958         //run last label if you need to
959         if (needToRun == true)  {
960             if (SharedList != NULL) {   delete SharedList;      }
961             SharedList = input.getSharedListVector(lastLabel); //get new list vector to process
962             
963             lookup = SharedList->getSharedRAbundVector();
964             m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
965             if (pickedGroups) { //check for otus with no seqs in them
966                 eliminateZeroOTUS(lookup);
967             }
968             
969             if (m->control_pressed) { 
970                 if (groupMap != NULL) { delete groupMap; } if (countTable != NULL) { delete countTable; }
971                 for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {  delete it3->second;   }
972                 out.close(); m->mothurRemove(filename); 
973                 for (int i=0; i<Groups.size(); i++) {  m->mothurRemove((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));          }
974                 return 0; 
975             }
976             
977             if (!m->printedHeaders) { lookup[0]->printHeaders(out); }
978             printSharedData(lookup, out); //prints info to the .shared file
979             for (int i = 0; i < lookup.size(); i++) {  delete lookup[i];  }
980             delete SharedList;
981         }
982         
983         out.close();
984         
985         for (it3 = filehandles.begin(); it3 != filehandles.end(); it3++) {
986             delete it3->second;
987         }
988         
989         if (groupMap != NULL) { delete groupMap; } if (countTable != NULL) { delete countTable; }
990                 
991         if (m->control_pressed) { 
992             m->mothurRemove(filename); 
993             for (int i=0; i<Groups.size(); i++) {  m->mothurRemove((fileroot + Groups[i] + "." + getOutputFileNameTag("rabund")));              }
994             return 0; 
995         }
996
997         return 0;
998     }
999         catch(exception& e) {
1000                 m->errorOut(e, "SharedCommand", "createSharedFromListGroup");
1001                 exit(1);
1002         }
1003 }
1004 //**********************************************************************************************************************
1005 void SharedCommand::printSharedData(vector<SharedRAbundVector*> thislookup, ofstream& out) {
1006         try {
1007                 
1008                 if (order.size() == 0) { //user has not specified an order so do aplabetically
1009                         sort(thislookup.begin(), thislookup.end(), compareSharedRabunds);
1010                         
1011                         m->clearGroups();
1012                         vector<string> Groups;
1013                         
1014                         //initialize bin values
1015                         for (int i = 0; i < thislookup.size(); i++) {
1016                                 out << thislookup[i]->getLabel() << '\t' << thislookup[i]->getGroup() << '\t';
1017                                 thislookup[i]->print(out);
1018                                 
1019                                 Groups.push_back(thislookup[i]->getGroup());
1020                                 
1021                                 RAbundVector rav = thislookup[i]->getRAbundVector();
1022                                 m->openOutputFileAppend(fileroot + thislookup[i]->getGroup() + "." + getOutputFileNameTag("rabund"), *(filehandles[thislookup[i]->getGroup()]));
1023                                 rav.print(*(filehandles[thislookup[i]->getGroup()]));
1024                                 (*(filehandles[thislookup[i]->getGroup()])).close();
1025                         }
1026                         m->setGroups(Groups);
1027                 }else{
1028                         //create a map from groupName to each sharedrabund
1029                         map<string, SharedRAbundVector*> myMap;
1030                         map<string, SharedRAbundVector*>::iterator myIt;
1031                         
1032                         for (int i = 0; i < thislookup.size(); i++) {
1033                                 myMap[thislookup[i]->getGroup()] = thislookup[i];
1034                         }
1035                         
1036                         m->clearGroups();
1037                         vector<string> Groups;
1038                         
1039                         //loop through ordered list and print the rabund
1040                         for (int i = 0; i < order.size(); i++) {
1041                                 myIt = myMap.find(order[i]);
1042                                 
1043                                 if(myIt != myMap.end()) { //we found it
1044                                         out << (myIt->second)->getLabel() << '\t' << (myIt->second)->getGroup() << '\t';
1045                                         (myIt->second)->print(out);
1046                                         
1047                                         Groups.push_back((myIt->second)->getGroup());
1048                                 
1049                                         RAbundVector rav = (myIt->second)->getRAbundVector();
1050                                         m->openOutputFileAppend(fileroot + (myIt->second)->getGroup() + "." + getOutputFileNameTag("rabund"), *(filehandles[(myIt->second)->getGroup()]));
1051                                         rav.print(*(filehandles[(myIt->second)->getGroup()]));
1052                                         (*(filehandles[(myIt->second)->getGroup()])).close();
1053                                 }else{
1054                                         m->mothurOut("Can't find shared info for " + order[i] + ", skipping."); m->mothurOutEndLine();
1055                                 }
1056                         }
1057                         
1058                         m->setGroups(Groups);
1059                 
1060                 }
1061  
1062         }
1063         catch(exception& e) {
1064                 m->errorOut(e, "SharedCommand", "printSharedData");
1065                 exit(1);
1066         }
1067 }
1068 //**********************************************************************************************************************
1069 int SharedCommand::ListGroupSameSeqs(vector<string>& groupMapsSeqs, SharedListVector* SharedList) {
1070         try {
1071                 int error = 0; 
1072         
1073                 set<string> groupNamesSeqs;
1074                 for(int i = 0; i < groupMapsSeqs.size(); i++) {
1075                         groupNamesSeqs.insert(groupMapsSeqs[i]);
1076                 }
1077                 
1078                 //go through list and if group returns "not found" output it
1079                 for (int i = 0; i < SharedList->getNumBins(); i++) {
1080                         if (m->control_pressed) { return 0; } 
1081                         
1082                         string names = SharedList->get(i); 
1083                         
1084                         vector<string> listNames;
1085                         m->splitAtComma(names, listNames);
1086                         
1087                         for (int j = 0; j < listNames.size(); j++) {
1088                                 int num = groupNamesSeqs.count(listNames[j]);
1089                                 
1090                                 if (num == 0) { 
1091                     error = 1; 
1092                     if (groupfile != "") { 
1093                         m->mothurOut("[ERROR]: " + listNames[j] + " is in your listfile and not in your groupfile. Please correct."); m->mothurOutEndLine();    } 
1094                     else{ m->mothurOut("[ERROR]: " + listNames[j] + " is in your listfile and not in your count file. Please correct."); m->mothurOutEndLine(); }
1095                 }else { groupNamesSeqs.erase(listNames[j]); }
1096                         }
1097                 }
1098                 
1099                 for (set<string>::iterator itGroupSet = groupNamesSeqs.begin(); itGroupSet != groupNamesSeqs.end(); itGroupSet++) {
1100                         error = 1; 
1101                         m->mothurOut("[ERROR]: " + (*itGroupSet) + " is in your groupfile and not your listfile. Please correct."); m->mothurOutEndLine();
1102                 }
1103                                 
1104                 return error;
1105         }
1106         catch(exception& e) {
1107                 m->errorOut(e, "SharedCommand", "ListGroupSameSeqs");
1108                 exit(1);
1109         }
1110 }
1111 //**********************************************************************************************************************
1112
1113 SharedCommand::~SharedCommand(){
1114         //delete list;
1115         
1116         
1117 }
1118 //**********************************************************************************************************************
1119 int SharedCommand::readOrderFile() {
1120         try {
1121                 //remove old names
1122                 order.clear();
1123                 
1124                 ifstream in;
1125                 m->openInputFile(ordergroupfile, in);
1126                 string thisGroup;
1127                 
1128                 while(!in.eof()){
1129                         in >> thisGroup; m->gobble(in);
1130                                                 
1131                         order.push_back(thisGroup);
1132                         
1133                         if (m->control_pressed) { order.clear(); break; }
1134                 }
1135                 in.close();             
1136                 
1137                 return 0;
1138         }
1139         catch(exception& e) {
1140                 m->errorOut(e, "SharedCommand", "readOrderFile");
1141                 exit(1);
1142         }
1143 }
1144 //**********************************************************************************************************************
1145
1146 bool SharedCommand::isValidGroup(string groupname, vector<string> groups) {
1147         try {
1148                 for (int i = 0; i < groups.size(); i++) {
1149                         if (groupname == groups[i]) { return true; }
1150                 }
1151                 
1152                 return false;
1153         }
1154         catch(exception& e) {
1155                 m->errorOut(e, "SharedCommand", "isValidGroup");
1156                 exit(1);
1157         }
1158 }
1159 /************************************************************/
1160
1161