5 * Created by Sarah Westcott on 3/30/09.
6 * Copyright 2009 Schloss Lab UMASS Amherst. All rights reserved.
10 #include "venncommand.h"
14 //#include "jackknife.h"
15 #include "sharedsobscollectsummary.h"
16 #include "sharedchao1.h"
17 #include "sharedace.h"
20 //**********************************************************************************************************************
21 vector<string> VennCommand::setParameters(){
23 CommandParameter plist("list", "InputTypes", "", "", "LRSS", "LRSS", "none","svg",false,false,true); parameters.push_back(plist);
24 CommandParameter pshared("shared", "InputTypes", "", "", "LRSS", "LRSS", "none","svg",false,false,true); parameters.push_back(pshared);
25 CommandParameter pgroups("groups", "String", "", "", "", "", "","",false,false); parameters.push_back(pgroups);
26 CommandParameter plabel("label", "String", "", "", "", "", "","",false,false); parameters.push_back(plabel);
27 CommandParameter pcalc("calc", "String", "", "", "", "", "","",false,false); parameters.push_back(pcalc);
28 CommandParameter pabund("abund", "Number", "", "10", "", "", "","",false,false); parameters.push_back(pabund);
29 CommandParameter pnseqs("nseqs", "Boolean", "", "F", "", "", "","",false,false); parameters.push_back(pnseqs);
30 CommandParameter psharedotus("sharedotus", "Boolean", "", "t", "", "", "","",false,false); parameters.push_back(psharedotus);
31 CommandParameter pfontsize("fontsize", "Number", "", "24", "", "", "","",false,false); parameters.push_back(pfontsize);
32 CommandParameter ppermute("permute", "Multiple", "1-2-3-4", "4", "", "", "","",false,false); parameters.push_back(ppermute); CommandParameter pinputdir("inputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(pinputdir);
33 CommandParameter poutputdir("outputdir", "String", "", "", "", "", "","",false,false); parameters.push_back(poutputdir);
35 vector<string> myArray;
36 for (int i = 0; i < parameters.size(); i++) { myArray.push_back(parameters[i].name); }
40 m->errorOut(e, "VennCommand", "setParameters");
44 //**********************************************************************************************************************
45 string VennCommand::getHelpString(){
47 string helpString = "";
48 helpString += "The venn command parameters are list, shared, groups, calc, abund, nseqs, permute, sharedotus, fontsize and label. shared, relabund, list, rabund or sabund is required unless you have a valid current file.\n";
49 helpString += "The groups parameter allows you to specify which of the groups in your groupfile you would like included in your venn diagram, you may only use a maximum of 4 groups.\n";
50 helpString += "The group names are separated by dashes. The label allows you to select what distance levels you would like a venn diagram created for, and are also separated by dashes.\n";
51 helpString += "The fontsize parameter allows you to adjust the font size of the picture created, default=24.\n";
52 helpString += "The venn command should be in the following format: venn(groups=yourGroups, calc=yourCalcs, label=yourLabels, abund=yourAbund).\n";
53 helpString += "Example venn(groups=A-B-C, calc=sharedsobs-sharedchao, abund=20).\n";
54 helpString += "The default value for groups is all the groups in your groupfile up to 4, and all labels in your inputfile will be used.\n";
55 helpString += "The default value for calc is sobs if you have only read a list file or if you have selected only one group, and sharedsobs if you have multiple groups.\n";
56 helpString += "The default available estimators for calc are sobs, chao and ace if you have only read a list file, and sharedsobs, sharedchao and sharedace if you have read a shared file.\n";
57 helpString += "The nseqs parameter will output the number of sequences represented by the otus in the picture, default=F.\n";
58 helpString += "If you have more than 4 groups, you can use the permute parameter to set the number of groups you would like mothur to divide the samples into to draw the venn diagrams for all possible combos. Default=4.\n";
59 helpString += "The only estimators available four 4 groups are sharedsobs and sharedchao.\n";
60 helpString += "The sharedotus parameter can be used with the sharedsobs calculator to get the names of the OTUs in each section of the venn diagram. Default=t.\n";
61 helpString += "The venn command outputs a .svg file for each calculator you specify at each distance you choose.\n";
62 helpString += "Note: No spaces between parameter labels (i.e. groups), '=' and parameters (i.e.yourGroups).\n";
66 m->errorOut(e, "VennCommand", "getHelpString");
70 //**********************************************************************************************************************
71 string VennCommand::getOutputPattern(string type) {
75 if (type == "svg") { pattern = "[filename],svg"; }
76 else { m->mothurOut("[ERROR]: No definition for type " + type + " output pattern.\n"); m->control_pressed = true; }
81 m->errorOut(e, "VennCommand", "getOutputPattern");
86 //**********************************************************************************************************************
87 VennCommand::VennCommand(){
89 abort = true; calledHelp = true;
91 vector<string> tempOutNames;
92 outputTypes["svg"] = tempOutNames;
95 m->errorOut(e, "VennCommand", "VennCommand");
99 //**********************************************************************************************************************
101 VennCommand::VennCommand(string option) {
103 abort = false; calledHelp = false;
106 //allow user to run help
107 if(option == "help") { help(); abort = true; calledHelp = true; }
108 else if(option == "citation") { citation(); abort = true; calledHelp = true;}
111 vector<string> myArray = setParameters();
113 OptionParser parser(option);
114 map<string,string> parameters = parser.getParameters();
115 map<string,string>::iterator it;
117 ValidParameters validParameter;
119 //check to make sure all parameters are valid for command
120 for (map<string,string>::iterator it = parameters.begin(); it != parameters.end(); it++) {
121 if (validParameter.isValidParameter(it->first, myArray, it->second) != true) { abort = true; }
124 //if the user changes the input directory command factory will send this info to us in the output parameter
125 string inputDir = validParameter.validFile(parameters, "inputdir", false);
126 if (inputDir == "not found"){ inputDir = ""; }
129 it = parameters.find("shared");
130 //user has given a template file
131 if(it != parameters.end()){
132 path = m->hasPath(it->second);
133 //if the user has not given a path then, add inputdir. else leave path alone.
134 if (path == "") { parameters["shared"] = inputDir + it->second; }
137 it = parameters.find("list");
138 //user has given a template file
139 if(it != parameters.end()){
140 path = m->hasPath(it->second);
141 //if the user has not given a path then, add inputdir. else leave path alone.
142 if (path == "") { parameters["list"] = inputDir + it->second; }
146 //check for required parameters
147 listfile = validParameter.validFile(parameters, "list", true);
148 if (listfile == "not open") { listfile = ""; abort = true; }
149 else if (listfile == "not found") { listfile = ""; }
150 else { format = "list"; inputfile = listfile; m->setListFile(listfile); }
152 sharedfile = validParameter.validFile(parameters, "shared", true);
153 if (sharedfile == "not open") { sharedfile = ""; abort = true; }
154 else if (sharedfile == "not found") { sharedfile = ""; }
155 else { format = "sharedfile"; inputfile = sharedfile; m->setSharedFile(sharedfile); }
157 if ((sharedfile == "") && (listfile == "")) {
158 //is there are current file available for any of these?
159 //give priority to shared, then list, then rabund, then sabund
160 //if there is a current shared file, use it
161 sharedfile = m->getSharedFile();
162 if (sharedfile != "") { inputfile = sharedfile; format = "sharedfile"; m->mothurOut("Using " + sharedfile + " as input file for the shared parameter."); m->mothurOutEndLine(); }
164 listfile = m->getListFile();
165 if (listfile != "") { inputfile = listfile; format = "list"; m->mothurOut("Using " + listfile + " as input file for the list parameter."); m->mothurOutEndLine(); }
167 m->mothurOut("No valid current files. You must provide a list or shared file."); m->mothurOutEndLine();
173 //if the user changes the output directory command factory will send this info to us in the output parameter
174 outputDir = validParameter.validFile(parameters, "outputdir", false); if (outputDir == "not found"){ outputDir = m->hasPath(inputfile); }
176 //check for optional parameter and set defaults
177 // ...at some point should added some additional type checking...
178 label = validParameter.validFile(parameters, "label", false);
179 if (label == "not found") { label = ""; }
181 if(label != "all") { m->splitAtDash(label, labels); allLines = 0; }
182 else { allLines = 1; }
185 groups = validParameter.validFile(parameters, "groups", false);
186 if (groups == "not found") { groups = ""; }
188 m->splitAtDash(groups, Groups);
189 m->setGroups(Groups);
192 calc = validParameter.validFile(parameters, "calc", false);
193 if (calc == "not found") {
194 if(format == "list") { calc = "sobs"; }
195 else { calc = "sharedsobs"; }
198 if (calc == "default") {
199 if(format == "list") { calc = "sobs"; }
200 else { calc = "sharedsobs"; }
203 m->splitAtDash(calc, Estimators);
204 if (m->inUsersGroups("citation", Estimators)) {
205 ValidCalculators validCalc; validCalc.printCitations(Estimators);
206 //remove citation from list of calcs
207 for (int i = 0; i < Estimators.size(); i++) { if (Estimators[i] == "citation") { Estimators.erase(Estimators.begin()+i); break; } }
211 temp = validParameter.validFile(parameters, "abund", false); if (temp == "not found") { temp = "10"; }
212 m->mothurConvert(temp, abund);
214 temp = validParameter.validFile(parameters, "nseqs", false); if (temp == "not found"){ temp = "f"; }
215 nseqs = m->isTrue(temp);
217 temp = validParameter.validFile(parameters, "permute", false); if (temp == "not found"){ temp = "4"; }
218 m->mothurConvert(temp, perm);
219 if ((perm == 1) || (perm == 2) || (perm == 3) || (perm == 4)) { }
220 else { m->mothurOut("[ERROR]: Not a valid permute value. Valid values are 1, 2, 3, and 4."); m->mothurOutEndLine(); abort = true; }
222 temp = validParameter.validFile(parameters, "sharedotus", false); if (temp == "not found"){ temp = "t"; }
223 sharedOtus = m->isTrue(temp);
225 temp = validParameter.validFile(parameters, "fontsize", false); if (temp == "not found") { temp = "24"; }
226 m->mothurConvert(temp, fontsize);
231 catch(exception& e) {
232 m->errorOut(e, "VennCommand", "VennCommand");
236 //**********************************************************************************************************************
238 int VennCommand::execute(){
241 if (abort == true) { if (calledHelp) { return 0; } return 2; }
243 ValidCalculators validCalculator;
245 if (format == "list") {
246 for (int i=0; i<Estimators.size(); i++) {
247 if (validCalculator.isValidCalculator("vennsingle", Estimators[i]) == true) {
248 if (Estimators[i] == "sobs") {
249 vennCalculators.push_back(new Sobs());
250 }else if (Estimators[i] == "chao") {
251 vennCalculators.push_back(new Chao1());
252 }else if (Estimators[i] == "ace") {
253 if(abund < 5) { abund = 10; }
254 vennCalculators.push_back(new Ace(abund));
259 for (int i=0; i<Estimators.size(); i++) {
260 if (validCalculator.isValidCalculator("vennshared", Estimators[i]) == true) {
261 if (Estimators[i] == "sharedsobs") {
262 vennCalculators.push_back(new SharedSobsCS());
263 }else if (Estimators[i] == "sharedchao") {
264 vennCalculators.push_back(new SharedChao1());
265 }else if (Estimators[i] == "sharedace") {
266 vennCalculators.push_back(new SharedAce());
272 //if the users entered no valid calculators don't execute command
273 if (vennCalculators.size() == 0) { m->mothurOut("No valid calculators given, please correct."); m->mothurOutEndLine(); return 0; }
275 venn = new Venn(outputDir, nseqs, inputfile, fontsize, sharedOtus);
276 input = new InputData(inputfile, format);
280 if (format == "sharedfile") {
281 lookup = input->getSharedRAbundVectors();
282 lastLabel = lookup[0]->getLabel();
284 if ((lookup.size() > 4)) { combos = findCombinations(lookup.size()); }
285 }else if (format == "list") {
286 sabund = input->getSAbundVector();
287 lastLabel = sabund->getLabel();
290 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
291 set<string> processedLabels;
292 set<string> userLabels = labels;
294 if (format != "list") {
296 //as long as you are not at the end of the file or done wih the lines you want
297 while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
299 if (m->control_pressed) {
300 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
301 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
302 m->clearGroups(); delete venn; delete input;
303 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
307 if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){
308 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
309 processedLabels.insert(lookup[0]->getLabel());
310 userLabels.erase(lookup[0]->getLabel());
314 if (lookup.size() > 4) {
315 set< set<int> >::iterator it3;
316 set<int>::iterator it2;
317 for (it3 = combos.begin(); it3 != combos.end(); it3++) {
319 set<int> poss = *it3;
320 vector<SharedRAbundVector*> subset;
321 for (it2 = poss.begin(); it2 != poss.end(); it2++) { subset.push_back(lookup[*it2]); }
323 vector<string> outfilenames = venn->getPic(subset, vennCalculators);
324 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
327 vector<string> outfilenames = venn->getPic(lookup, vennCalculators);
328 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
332 if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
333 string saveLabel = lookup[0]->getLabel();
335 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
336 lookup = input->getSharedRAbundVectors(lastLabel);
338 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
339 processedLabels.insert(lookup[0]->getLabel());
340 userLabels.erase(lookup[0]->getLabel());
342 if (lookup.size() > 4) {
343 set< set<int> >::iterator it3;
344 set<int>::iterator it2;
345 for (it3 = combos.begin(); it3 != combos.end(); it3++) {
347 set<int> poss = *it3;
348 vector<SharedRAbundVector*> subset;
349 for (it2 = poss.begin(); it2 != poss.end(); it2++) { subset.push_back(lookup[*it2]); }
351 vector<string> outfilenames = venn->getPic(subset, vennCalculators);
352 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
355 vector<string> outfilenames = venn->getPic(lookup, vennCalculators);
356 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
359 //restore real lastlabel to save below
360 lookup[0]->setLabel(saveLabel);
364 lastLabel = lookup[0]->getLabel();
366 //get next line to process
367 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
368 lookup = input->getSharedRAbundVectors();
371 if (m->control_pressed) {
372 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
373 m->clearGroups(); delete venn; delete input;
374 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
379 //output error messages about any remaining user labels
380 set<string>::iterator it;
381 bool needToRun = false;
382 for (it = userLabels.begin(); it != userLabels.end(); it++) {
383 m->mothurOut("Your file does not include the label " + *it);
384 if (processedLabels.count(lastLabel) != 1) {
385 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
388 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
392 //run last label if you need to
393 if (needToRun == true) {
394 for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }
395 lookup = input->getSharedRAbundVectors(lastLabel);
397 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
398 processedLabels.insert(lookup[0]->getLabel());
399 userLabels.erase(lookup[0]->getLabel());
401 if (lookup.size() > 4) {
402 set< set<int> >::iterator it3;
403 set<int>::iterator it2;
404 for (it3 = combos.begin(); it3 != combos.end(); it3++) {
406 set<int> poss = *it3;
407 vector<SharedRAbundVector*> subset;
408 for (it2 = poss.begin(); it2 != poss.end(); it2++) { subset.push_back(lookup[*it2]); }
410 vector<string> outfilenames = venn->getPic(subset, vennCalculators);
411 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
414 vector<string> outfilenames = venn->getPic(lookup, vennCalculators);
415 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
418 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
422 //reset groups parameter
425 if (m->control_pressed) {
426 m->clearGroups(); delete venn; delete input;
427 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
428 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
435 while((sabund != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
437 if (m->control_pressed) {
438 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
439 delete sabund; delete venn; delete input;
440 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
444 if(allLines == 1 || labels.count(sabund->getLabel()) == 1){
446 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
447 vector<string> outfilenames = venn->getPic(sabund, vennCalculators);
448 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
451 processedLabels.insert(sabund->getLabel());
452 userLabels.erase(sabund->getLabel());
455 if ((m->anyLabelsToProcess(sabund->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
456 string saveLabel = sabund->getLabel();
459 sabund = input->getSAbundVector(lastLabel);
461 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
462 vector<string> outfilenames = venn->getPic(sabund, vennCalculators);
463 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
466 processedLabels.insert(sabund->getLabel());
467 userLabels.erase(sabund->getLabel());
469 //restore real lastlabel to save below
470 sabund->setLabel(saveLabel);
473 lastLabel = sabund->getLabel();
476 sabund = input->getSAbundVector();
479 if (m->control_pressed) {
480 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
481 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
482 delete venn; delete input;
486 //output error messages about any remaining user labels
487 set<string>::iterator it;
488 bool needToRun = false;
489 for (it = userLabels.begin(); it != userLabels.end(); it++) {
490 m->mothurOut("Your file does not include the label " + *it);
491 if (processedLabels.count(lastLabel) != 1) {
492 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
495 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
499 //run last label if you need to
500 if (needToRun == true) {
501 if (sabund != NULL) { delete sabund; }
502 sabund = input->getSAbundVector(lastLabel);
504 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
505 vector<string> outfilenames = venn->getPic(sabund, vennCalculators);
506 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
512 if (m->control_pressed) {
513 delete venn; delete input;
514 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
515 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
520 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
521 delete venn; delete input;
523 m->mothurOutEndLine();
524 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
525 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
526 m->mothurOutEndLine();
531 catch(exception& e) {
532 m->errorOut(e, "VennCommand", "execute");
536 //**********************************************************************************************************************
537 //returns a vector of sets containing the group combinations
538 set< set<int> > VennCommand::findCombinations(int lookupSize){
540 set< set<int> > combos;
543 for (int i = 0; i < lookupSize; i++) { possibles.insert(i); }
545 getCombos(possibles, combos);
550 catch(exception& e) {
551 m->errorOut(e, "VennCommand", "findCombinations");
555 //**********************************************************************************************************************
556 //recusively finds combos of length perm
557 int VennCommand::getCombos(set<int> possibles, set< set<int> >& combos){
560 if (possibles.size() == perm) { //done
561 if (combos.count(possibles) == 0) { //no dups
562 combos.insert(possibles);
564 }else { //we still have work to do
565 set<int>::iterator it;
566 set<int>::iterator it2;
567 for (it = possibles.begin(); it != possibles.end(); it++) {
569 set<int> newPossibles;
570 for (it2 = possibles.begin(); it2 != possibles.end(); it2++) { //all possible combos of one length smaller
572 newPossibles.insert(*it2);
575 getCombos(newPossibles, combos);
581 catch(exception& e) {
582 m->errorOut(e, "VennCommand", "getCombos");
587 //**********************************************************************************************************************