1 /*
2  *  getsharedotucommand.cpp
3  *  Mothur
4  *
5  *  Created by westcott on 9/22/09.
6  *  Copyright 2009 Schloss Lab. All rights reserved.
7  *
8  */
9 
10 #include "getsharedotucommand.h"
11 
12 
13 //**********************************************************************************************************************
setParameters()14 vector<string> GetSharedOTUCommand::setParameters(){
15 	try {
16 		CommandParameter pfasta("fasta", "InputTypes", "", "", "sharedFasta", "none", "none","fasta",false,false); parameters.push_back(pfasta);
17 		CommandParameter pgroup("group", "InputTypes", "", "", "none", "GroupCount", "groupList","",false,false,true); parameters.push_back(pgroup);
18         CommandParameter pcount("count", "InputTypes", "", "", "none", "GroupCount", "none","",false,false); parameters.push_back(pcount);
19 		CommandParameter plist("list", "InputTypes", "", "", "sharedList", "sharedList", "groupList","sharedseq",false,false,true); parameters.push_back(plist);
20         CommandParameter pshared("shared", "InputTypes", "", "", "sharedList-sharedFasta", "sharedList", "none","sharedseq",false,false,true); parameters.push_back(pshared);
21 		CommandParameter poutput("output", "Multiple", "accnos-default", "default", "", "", "","",false,false); parameters.push_back(poutput);
22 		CommandParameter plabel("label", "String", "", "", "", "", "","",false,false); parameters.push_back(plabel);
23 		CommandParameter puniquegroups("uniquegroups", "String", "", "", "", "", "","",false,false,true); parameters.push_back(puniquegroups);
24 		CommandParameter psharedgroups("sharedgroups", "String", "", "", "", "", "","",false,false,true); parameters.push_back(psharedgroups);
25 		CommandParameter pseed("seed", "Number", "", "0", "", "", "","",false,false); parameters.push_back(pseed);
26         CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
27 		CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
28 
29         abort = false; calledHelp = false;
30         userGroups = ""; unique = true; allLines = true;
31 
32         vector<string> tempOutNames;
33         outputTypes["fasta"] = tempOutNames;
34         outputTypes["accnos"] = tempOutNames;
35         outputTypes["sharedseqs"] = tempOutNames;
36 
37 		vector<string> myArray;
38 		for (int i = 0; i < parameters.size(); i++) {	myArray.push_back(parameters[i].name);		}
39 		return myArray;
40 	}
41 	catch(exception& e) {
42 		m->errorOut(e, "GetSharedOTUCommand", "setParameters");
43 		exit(1);
44 	}
45 }
46 //**********************************************************************************************************************
getHelpString()47 string GetSharedOTUCommand::getHelpString(){
48 	try {
49 		string helpString = "";
50 		helpString += "The get.sharedseqs command parameters are list, group, shared, label, uniquegroups, sharedgroups, output and fasta.  The list and group or shared parameters are required, unless you have valid current files.\n";
51 		helpString += "The label parameter allows you to select what distance levels you would like output files for, and are separated by dashes.\n";
52 		helpString += "The uniquegroups and sharedgroups parameters allow you to select groups you would like to know the shared info for, and are separated by dashes.\n";
53 		helpString += "If you enter your groups under the uniquegroups parameter mothur will return the otus that contain ONLY sequences from those groups.\n";
54 		helpString += "If you enter your groups under the sharedgroups parameter mothur will return the otus that contain sequences from those groups and may also contain sequences from other groups.\n";
55 		helpString += "If you do not enter any groups then the get.sharedseqs command will return sequences that are unique to all groups in your group or shared file.\n";
56 		helpString += "The fasta parameter allows you to input a fasta file and outputs a fasta file for each distance level containing only the sequences that are in OTUs shared by the groups specified. It can only be used with a list and group file not the shared file input.\n";
57         helpString += "The count parameter allows you to provide a count file containing the group info for the list file.\n";
58 		helpString += "The output parameter allows you to output the list of names without the group and bin number added. \n";
59 		helpString += "With this option you can use the names file as an input in get.seqs and remove.seqs commands. To do this enter output=accnos. \n";
60 		helpString += "The get.sharedseqs command outputs a .names file for each distance level containing a list of sequences in the OTUs shared by the groups specified.\n";
61 		helpString += "The get.sharedseqs command should be in the following format: get.sharedseqs(list=yourListFile, group=yourGroupFile, label=yourLabels, uniquegroups=yourGroups, fasta=yourFastafile, output=yourOutput).\n";
62 		helpString += "Example get.sharedseqs(list=amazon.fn.list, label=unique-0.01, group=amazon.groups, uniquegroups=forest-pasture, fasta=amazon.fasta, output=accnos).\n";
63 		helpString += "The output to the screen is the distance and the number of otus at that distance for the groups you specified.\n";
64 		helpString += "The default value for label is all labels in your inputfile. The default for groups is all groups in your file.\n";
65 		return helpString;
66 	}
67 	catch(exception& e) {
68 		m->errorOut(e, "GetSharedOTUCommand", "getHelpString");
69 		exit(1);
70 	}
71 }
72 //**********************************************************************************************************************
getOutputPattern(string type)73 string GetSharedOTUCommand::getOutputPattern(string type) {
74     try {
75         string pattern = "";
76 
77         if (type == "fasta")            {   pattern =  "[filename],[distance],[group],shared.fasta";   }
78         else if (type == "accnos")      {   pattern =  "[filename],[distance],[group],accnos";         }
79         else if (type == "sharedseqs")  {   pattern =  "[filename],[distance],[group],shared.seqs";    }
80         else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->setControl_pressed(true);  }
81 
82         return pattern;
83     }
84     catch(exception& e) {
85         m->errorOut(e, "GetSharedOTUCommand", "getOutputPattern");
86         exit(1);
87     }
88 }
89 //**********************************************************************************************************************
GetSharedOTUCommand(string option)90 GetSharedOTUCommand::GetSharedOTUCommand(string option) : Command()  {
91 	try {
92 		if(option == "help") { help(); abort = true; calledHelp = true; }
93 		else if(option == "citation") { citation(); abort = true; calledHelp = true;}
94         else if(option == "category") {  abort = true; calledHelp = true;  }
95 
96 		else {
97 			OptionParser parser(option, setParameters());
98 			map<string,string> parameters = parser.getParameters();
99 
100 			ValidParameters validParameter;
101 
102 
103 			//check for required parameters
104 			listfile = validParameter.validFile(parameters, "list");
105 			if (listfile == "not open") { abort = true; }
106 			else if (listfile == "not found") { listfile = "";			}
107             else {  format = "list"; 	current->setListFile(listfile); }
108 
109 			groupfile = validParameter.validFile(parameters, "group");
110 			if (groupfile == "not open") { abort = true; }
111 			else if (groupfile == "not found") { groupfile = ""; }
112 			else { current->setGroupFile(groupfile); }
113 
114             sharedfile = validParameter.validFile(parameters, "shared");
115 			if (sharedfile == "not open") { abort = true; }
116 			else if (sharedfile == "not found") { sharedfile = ""; }
117 			else { current->setSharedFile(sharedfile); }
118 
119             fastafile = validParameter.validFile(parameters, "fasta");
120 			if (fastafile == "not open") { abort = true; }
121 			else if (fastafile == "not found") {  fastafile = "";  }
122 			else { current->setFastaFile(fastafile); }
123 
124             countfile = validParameter.validFile(parameters, "count");
125             if (countfile == "not open") { countfile = ""; abort = true; }
126             else if (countfile == "not found") { countfile = ""; }
127             else {
128                 current->setCountFile(countfile);
129                 CountTable temp;
130                 if (!temp.testGroups(countfile)) { m->mothurOut("[ERROR]: Your count file does not have group info, aborting.\n");  abort=true; }
131             }
132 
133             if ((sharedfile == "") && (listfile == "")) { //look for currents
134                 //is there are current file available for either of these?
135 				//give priority to shared, then list
136 				sharedfile = current->getSharedFile();
137 				if (sharedfile != "") {  m->mothurOut("Using " + sharedfile + " as input file for the shared parameter.\n");  }
138 				else {
139 					listfile = current->getListFile();
140 					if (listfile != "") {  m->mothurOut("Using " + listfile + " as input file for the list parameter.\n");  }
141 					else {
142 						m->mothurOut("No valid current files. You must provide a shared or list file.\n");
143 						abort = true;
144 					}
145 				}
146             }else if ((sharedfile != "") && (listfile != "")) {
147                 m->mothurOut("You may enter ONLY ONE of the following: shared or list.\n");  abort = true;
148             }
149 
150             if (listfile != "") {
151                 if ((groupfile == "") && (countfile == "")) {
152                     groupfile = current->getGroupFile();
153                     if (groupfile != "") {  m->mothurOut("Using " + groupfile + " as input file for the group parameter.\n");  }
154                     else {
155                         countfile = current->getCountFile();
156                         if (countfile != "") {  m->mothurOut("Using " + countfile + " as input file for the count parameter.\n");  }
157                         else {
158                             m->mothurOut("You need to provide a groupfile or countfile if you are going to use the list format.\n");
159                             abort = true;
160                         }
161                     }
162                 }
163 			}
164 
165 			if ((sharedfile != "") && (fastafile != "")) { m->mothurOut("You cannot use the fasta file with the shared file.\n");  abort = true; }
166 
167 			//check for optional parameter and set defaults
168 			// ...at some point should added some additional type checking...
169 			label = validParameter.valid(parameters, "label");
170 			if (label == "not found") { label = ""; }
171 			else {
172 				if(label != "all") {  util.splitAtDash(label, labels);  allLines = false;  }
173 				else { allLines = true;  }
174 			}
175 
176 			output = validParameter.valid(parameters, "output");
177 			if (output == "not found") { output = ""; }
178 			else if (output == "default") { output = ""; }
179 
180 			groups = validParameter.valid(parameters, "uniquegroups");
181 			if (groups == "not found") { groups = ""; }
182 			else {
183 				userGroups = "unique." + groups;
184 				util.splitAtDash(groups, Groups);
185                 if (Groups.size() != 0) { if (Groups[0]== "all") { Groups.clear(); } }
186                 if (Groups.size() > 4) {  userGroups = "unique.selected_groups"; } //if too many groups then the filename becomes too big.
187 			}
188 
189 			groups = validParameter.valid(parameters, "sharedgroups");
190 			if (groups == "not found") { groups = "";  }
191 			else {
192 				userGroups = groups;
193 				util.splitAtDash(groups, Groups);
194                 if (Groups.size() != 0) { if (Groups[0]== "all") { Groups.clear(); } }
195                 if (Groups.size() > 4) {  userGroups = "selected_groups"; } //if too many groups then the filename becomes too big.
196 				unique = false;
197 			}
198 
199         }
200 
201 	}
202 	catch(exception& e) {
203 		m->errorOut(e, "GetSharedOTUCommand", "GetSharedOTUCommand");
204 		exit(1);
205 	}
206 }
207 //**********************************************************************************************************************
208 
execute()209 int GetSharedOTUCommand::execute(){
210 	try {
211 
212 		if (abort) { if (calledHelp) { return 0; }  return 2;	}
213 
214         if ( sharedfile != "") { runShared(); }
215         else {
216             if (groupfile != "") {
217                 groupMap = new GroupMap(groupfile);
218 
219                 int groupError = groupMap->readMap();
220                 if (groupError == 1) { delete groupMap; return 0; }
221                 vector<string> allGroups = groupMap->getNamesOfGroups();
222             }else{
223                 ct = new CountTable();
224                 ct->readTable(countfile, true, false);
225             }
226 
227             if (m->getControl_pressed()) { delete groupMap; return 0; }
228 
229             if (Groups.size() == 0) {
230                 if (groupfile != "") { Groups = groupMap->getNamesOfGroups(); }
231                 else {  Groups = ct->getNamesOfGroups();  }
232 
233                 //make string for outputfile name
234                 userGroups = "unique.";
235                 for(int i = 0; i < Groups.size(); i++) {  userGroups += Groups[i] + "-";  }
236                 userGroups = userGroups.substr(0, userGroups.length()-1);
237                 if (Groups.size() > 4) {  userGroups = "unique.selected_groups"; } //if too many groups then the filename becomes too big.
238             }
239 
240             //put groups in map to find easier
241             for(int i = 0; i < Groups.size(); i++) { groupFinder[Groups[i]] = Groups[i]; }
242 
243             if (fastafile != "") {
244                 ifstream inFasta;
245                 util.openInputFile(fastafile, inFasta);
246 
247                 while(!inFasta.eof()) {
248                     if (m->getControl_pressed()) { outputTypes.clear(); inFasta.close(); delete groupMap; return 0; }
249 
250                     Sequence seq(inFasta); util.gobble(inFasta);
251                     if (seq.getName() != "") {  seqs.push_back(seq);   }
252                 }
253                 inFasta.close();
254             }
255 
256             InputData input(listfile, "list", nullVector);
257             set<string> processedLabels;
258             set<string> userLabels = labels;
259             string lastLabel = "";
260 
261             ListVector* list = util.getNextList(input, allLines, userLabels, processedLabels, lastLabel);
262 
263             while (list != NULL) {
264 
265                 if (m->getControl_pressed()) { delete list; break; }
266 
267                 process(list); delete list;
268 
269                 list = util.getNextList(input, allLines, userLabels, processedLabels, lastLabel);
270             }
271 
272             if (m->getControl_pressed()) { outputTypes.clear(); for (int i = 0; i < outputNames.size(); i++) {	util.mothurRemove(outputNames[i]); }  if (groupfile != "") { delete groupMap; }else { delete ct; } return 0; }
273 		}
274 		//set fasta file as new current fastafile
275 		string currentName = "";
276 		itTypes = outputTypes.find("fasta");
277 		if (itTypes != outputTypes.end()) {
278 			if ((itTypes->second).size() != 0) { currentName = (itTypes->second)[0]; current->setFastaFile(currentName); }
279 		}
280 
281 		if (output == "accnos") {
282 			itTypes = outputTypes.find("accnos");
283 			if (itTypes != outputTypes.end()) {
284 				if ((itTypes->second).size() != 0) { currentName = (itTypes->second)[0]; current->setAccnosFile(currentName); }
285 			}
286 		}
287 
288 		m->mothurOut("\nOutput File Names: \n");
289 		for (int i = 0; i < outputNames.size(); i++) {	m->mothurOut(outputNames[i] +"\n"); 	} m->mothurOutEndLine();
290 
291 
292 		return 0;
293 	}
294 
295 	catch(exception& e) {
296 		m->errorOut(e, "GetSharedOTUCommand", "execute");
297 		exit(1);
298 	}
299 }
300 /***********************************************************/
process(ListVector * shared)301 int GetSharedOTUCommand::process(ListVector* shared) {
302 	try {
303 
304 		map<string, string> fastaMap;
305 
306 		ofstream outNames;
307 		string outputFileNames;
308 
309 		if (outputdir == "") { outputdir += util.hasPath(listfile); }
310         map<string, string> variables;
311         variables["[filename]"] = outputdir + util.getRootName(util.getSimpleName(listfile));
312         variables["[distance]"] = shared->getLabel();
313         variables["[group]"] = userGroups;
314 		if (output != "accnos") { outputFileNames = getOutputFileName("sharedseqs", variables); }
315 		else { outputFileNames = getOutputFileName("accnos", variables); }
316 
317 		util.openOutputFile(outputFileNames, outNames);
318 
319 		bool wroteSomething = false;
320 		int num = 0;
321 
322 		//go through each bin, find out if shared
323         vector<string> binLabels = shared->getLabels();
324 		for (int i = 0; i < shared->getNumBins(); i++) {
325 			if (m->getControl_pressed()) { outNames.close(); util.mothurRemove(outputFileNames); return 0; }
326 
327 			bool uniqueOTU = true;
328 
329 			map<string, int> atLeastOne;
330 			for (int f = 0; f < Groups.size(); f++) { atLeastOne[Groups[f]] = 0; }
331 
332 			vector<string> namesOfSeqsInThisBin;
333 
334 			string names = shared->get(i);
335             vector<string> binNames;
336             util.splitAtComma(names, binNames);
337 			for(int j = 0; j < binNames.size(); j++) {
338 				string name = binNames[j];
339 
340 				//find group
341                 string seqGroup = "not found"; vector<string> seqsGroups;
342                 if (groupfile != "") {  seqGroup = groupMap->getGroup(name); }
343                 else {
344                     seqsGroups = ct->getGroups(name);
345                     seqGroup = util.getStringFromVector(seqsGroups, "-");
346                 }
347 
348 				if (output != "accnos") {
349 					namesOfSeqsInThisBin.push_back((name + "|" + seqGroup + "|" + binLabels[i]));
350 				}else {  namesOfSeqsInThisBin.push_back(name);	}
351 
352 				if (seqGroup == "not found") { m->mothurOut(name + " is not in your groupfile. Please correct.\n");  exit(1);  }
353 
354                 if (groupfile != "") {
355                     //is this seq in one of hte groups we care about
356                     it = groupFinder.find(seqGroup);
357                     if (it == groupFinder.end()) {  uniqueOTU = false;  } //you have a sequence from a group you don't want
358                     else {  atLeastOne[seqGroup]++;  }
359                 }else {
360                     for (int k = 0; k < seqsGroups.size(); k++) {
361                         //is this seq in one of hte groups we care about
362                         it = groupFinder.find(seqsGroups[k]);
363                         if (it == groupFinder.end()) {  uniqueOTU = false;  } //you have a sequence from a group you don't want
364                         else {  atLeastOne[seqsGroups[k]]++;  }
365                     }
366                 }
367 			}
368 
369 			//make sure you have at least one seq from each group you want
370 			bool sharedByAll = true;
371 			map<string, int>::iterator it2;
372 			for (it2 = atLeastOne.begin(); it2 != atLeastOne.end(); it2++) {
373 				if (it2->second == 0) {  sharedByAll = false;	}
374 			}
375 
376 			//if the user wants unique bins and this is unique then print
377 			//or this the user wants shared bins and this bin is shared then print
378 			if ((unique && uniqueOTU && sharedByAll) || (!unique && sharedByAll)) {
379 
380 				wroteSomething = true;
381 				num++;
382 
383 				//output list of names
384 				for (int j = 0; j < namesOfSeqsInThisBin.size(); j++) {
385 					outNames << namesOfSeqsInThisBin[j] << endl;
386 
387 					if (fastafile != "") {
388 						if (output != "accnos") {
389 							string seqName = namesOfSeqsInThisBin[j].substr(0,namesOfSeqsInThisBin[j].find_last_of('|'));
390 							seqName = seqName.substr(0,seqName.find_last_of('|'));
391 							fastaMap[seqName] = namesOfSeqsInThisBin[j];  //fastaMap needs to contain just the seq name for output later
392 						}else {
393 							fastaMap[namesOfSeqsInThisBin[j]] = namesOfSeqsInThisBin[j];
394 						}
395 					}
396 				}
397 			}
398 		}
399 
400 		outNames.close();
401 
402 		if (!wroteSomething) {
403 			util.mothurRemove(outputFileNames);
404 			string outputString = "\t" + toString(num) + " - No otus shared by groups";
405 
406 			string groupString = "";
407 			for (int h = 0; h < Groups.size(); h++) {
408 				groupString += "  " + Groups[h];
409 			}
410 
411 			outputString += groupString + ".";
412 			m->mothurOut(outputString); m->mothurOutEndLine();
413 		}else {
414 			m->mothurOut("\t" + toString(num)); m->mothurOutEndLine();
415 			outputNames.push_back(outputFileNames);
416 			if (output != "accnos") { outputTypes["sharedseqs"].push_back(outputFileNames); }
417 			else { outputTypes["accnos"].push_back(outputFileNames); }
418 		}
419 
420 		//if fasta file provided output new fasta file
421 		if ((fastafile != "") && wroteSomething) {
422 			if (outputdir == "") { outputdir += util.hasPath(fastafile); }
423             variables["[filename]"] = outputdir + util.getRootName(util.getSimpleName(fastafile));
424 			string outputFileFasta = getOutputFileName("fasta", variables);
425 			ofstream outFasta;
426 			util.openOutputFile(outputFileFasta, outFasta);
427 			outputNames.push_back(outputFileFasta); outputTypes["fasta"].push_back(outputFileFasta);
428 
429 			for (int k = 0; k < seqs.size(); k++) {
430 				if (m->getControl_pressed()) { outFasta.close(); return 0; }
431 
432 				//if this is a sequence we want, output it
433 				it = fastaMap.find(seqs[k].getName());
434 				if (it != fastaMap.end()) {
435 
436 					if (output != "accnos") {
437 						outFasta << ">" << it->second << endl;
438 					}else {
439 						outFasta << ">" << it->first << endl;
440 					}
441 
442 					outFasta << seqs[k].getAligned() << endl;
443 				}
444 			}
445 
446 			outFasta.close();
447 		}
448 
449 		return 0;
450 
451 	}
452 	catch(exception& e) {
453 		m->errorOut(e, "GetSharedOTUCommand", "process");
454 		exit(1);
455 	}
456 }
457 /***********************************************************/
runShared()458 int GetSharedOTUCommand::runShared() {
459 	try {
460         InputData input(sharedfile, "sharedfile", nullVector);
461 		set<string> processedLabels;
462         set<string> userLabels = labels;
463         string lastLabel = "";
464 
465         SharedRAbundVectors* lookup = util.getNextShared(input, allLines, userLabels, processedLabels, lastLabel);
466         //Groups = lookup->getNamesGroups();
467 
468         if (userGroups == "") {
469             //make string for outputfile name
470             userGroups = "unique.";
471             for(int i = 0; i < Groups.size(); i++) {  userGroups += Groups[i] + "-";  }
472             userGroups = userGroups.substr(0, userGroups.length()-1);
473             if (Groups.size() > 4) {  userGroups = "unique.selected_groups"; } //if too many groups then the filename becomes too big.
474         }
475 
476         //put groups in map to find easier
477         for(int i = 0; i < Groups.size(); i++) { groupFinder[Groups[i]] = Groups[i];}
478 
479         while (lookup != NULL) {
480 
481             if (m->getControl_pressed()) { delete lookup; break; }
482 
483             process(lookup); delete lookup;
484 
485             lookup = util.getNextShared(input, allLines, userLabels, processedLabels, lastLabel);
486         }
487 
488 		if (m->getControl_pressed()) { outputTypes.clear(); for (int i = 0; i < outputNames.size(); i++) {	util.mothurRemove(outputNames[i]); } return 0; }
489 
490 
491 		return 0;
492 
493     }
494 	catch(exception& e) {
495 		m->errorOut(e, "GetSharedOTUCommand", "runShared");
496 		exit(1);
497 	}
498 }
499 /***********************************************************/
process(SharedRAbundVectors * & lookup)500 int GetSharedOTUCommand::process(SharedRAbundVectors*& lookup) {
501 	try {
502 
503 		string outputFileNames;
504 		if (outputdir == "") { outputdir += util.hasPath(sharedfile); }
505         map<string, string> variables;
506         variables["[filename]"] = outputdir + util.getRootName(util.getSimpleName(sharedfile));
507         variables["[distance]"] = lookup->getLabel();
508         variables["[group]"] = userGroups;
509 		if (output != "accnos") { outputFileNames = getOutputFileName("sharedseqs", variables); }
510 		else { outputFileNames = getOutputFileName("accnos", variables); }
511 
512         ofstream outNames;
513 		util.openOutputFile(outputFileNames, outNames);
514 
515 		bool wroteSomething = false;
516 		int num = 0;
517 
518 		//go through each bin, find out if shared
519 		for (int i = 0; i < lookup->getNumBins(); i++) {
520 			if (m->getControl_pressed()) { outNames.close(); util.mothurRemove(outputFileNames); return 0; }
521 
522 			bool uniqueOTU = true;
523 			map<string, int> atLeastOne;
524 			for (int f = 0; f < Groups.size(); f++) {  atLeastOne[Groups[f]] = 0;  }
525 
526 			set<string> namesOfGroupsInThisBin;
527 
528             vector<string> groupNames = lookup->getNamesGroups();
529 			for(int j = 0; j < lookup->size(); j++) {
530 				string seqGroup = groupNames[j];
531                 string name = lookup->getOTUName(i);
532                 int abund = lookup->get(i, seqGroup);
533 
534                 if (abund != 0) {
535                     if (output != "accnos") {
536                         namesOfGroupsInThisBin.insert(name + "|" + seqGroup + "|" + toString(abund));
537                     }else {  namesOfGroupsInThisBin.insert(name);	}
538 
539                     //is this seq in one of the groups we care about
540                     it = groupFinder.find(seqGroup);
541                     if (it == groupFinder.end()) {  uniqueOTU = false;  } //you have sequences from a group you don't want
542                     else {  atLeastOne[seqGroup]++;  }
543 				}
544 			}
545 
546 			//make sure you have at least one seq from each group you want
547 			bool sharedByAll = true;
548 			map<string, int>::iterator it2;
549 			for (it2 = atLeastOne.begin(); it2 != atLeastOne.end(); it2++) {
550 				if (it2->second == 0) {  sharedByAll = false;	}
551 			}
552 
553 			//if the user wants unique bins and this is unique then print
554 			//or this the user wants shared bins and this bin is shared then print
555 			if ((unique && uniqueOTU && sharedByAll) || (!unique && sharedByAll)) {
556 
557 				wroteSomething = true;
558 				num++;
559 
560 				//output list of names
561 				for (set<string>::iterator itNames = namesOfGroupsInThisBin.begin(); itNames != namesOfGroupsInThisBin.end(); itNames++) {
562 					outNames << (*itNames) << endl;
563 				}
564 			}
565 		}
566 		outNames.close();
567 
568 		if (!wroteSomething) {
569 			util.mothurRemove(outputFileNames);
570 			string outputString = "\t" + toString(num) + " - No otus shared by groups";
571 
572 			string groupString = "";
573 			for (int h = 0; h < Groups.size(); h++) {
574 				groupString += "  " + Groups[h];
575 			}
576 
577 			outputString += groupString + ".";
578 			m->mothurOut(outputString); m->mothurOutEndLine();
579 		}else {
580 			m->mothurOut("\t" + toString(num)); m->mothurOutEndLine();
581 			outputNames.push_back(outputFileNames);
582 			if (output != "accnos") { outputTypes["sharedseqs"].push_back(outputFileNames); }
583 			else { outputTypes["accnos"].push_back(outputFileNames); }
584 		}
585 
586 		return 0;
587 	}
588 	catch(exception& e) {
589 		m->errorOut(e, "GetSharedOTUCommand", "process");
590 		exit(1);
591 	}
592 }
593 
594 //**********************************************************************************************************************
595