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);
218 if (temp == "not found"){ temp = "4"; }
220 if ((temp == "1") || (temp == "2") || (temp == "3") || (temp == "4")) {}
222 bool permTrue = m->isTrue(temp);
223 if (permTrue) { temp = "4"; }
227 m->mothurConvert(temp, perm);
228 if ((perm == 1) || (perm == 2) || (perm == 3) || (perm == 4)) { }
229 else { m->mothurOut("[ERROR]: Not a valid permute value. Valid values are 1, 2, 3, 4 and true."); m->mothurOutEndLine(); abort = true; }
231 temp = validParameter.validFile(parameters, "sharedotus", false); if (temp == "not found"){ temp = "t"; }
232 sharedOtus = m->isTrue(temp);
234 temp = validParameter.validFile(parameters, "fontsize", false); if (temp == "not found") { temp = "24"; }
235 m->mothurConvert(temp, fontsize);
240 catch(exception& e) {
241 m->errorOut(e, "VennCommand", "VennCommand");
245 //**********************************************************************************************************************
247 int VennCommand::execute(){
250 if (abort == true) { if (calledHelp) { return 0; } return 2; }
252 ValidCalculators validCalculator;
254 if (format == "list") {
255 for (int i=0; i<Estimators.size(); i++) {
256 if (validCalculator.isValidCalculator("vennsingle", Estimators[i]) == true) {
257 if (Estimators[i] == "sobs") {
258 vennCalculators.push_back(new Sobs());
259 }else if (Estimators[i] == "chao") {
260 vennCalculators.push_back(new Chao1());
261 }else if (Estimators[i] == "ace") {
262 if(abund < 5) { abund = 10; }
263 vennCalculators.push_back(new Ace(abund));
268 for (int i=0; i<Estimators.size(); i++) {
269 if (validCalculator.isValidCalculator("vennshared", Estimators[i]) == true) {
270 if (Estimators[i] == "sharedsobs") {
271 vennCalculators.push_back(new SharedSobsCS());
272 }else if (Estimators[i] == "sharedchao") {
273 vennCalculators.push_back(new SharedChao1());
274 }else if (Estimators[i] == "sharedace") {
275 vennCalculators.push_back(new SharedAce());
281 //if the users entered no valid calculators don't execute command
282 if (vennCalculators.size() == 0) { m->mothurOut("No valid calculators given, please correct."); m->mothurOutEndLine(); return 0; }
284 venn = new Venn(outputDir, nseqs, inputfile, fontsize, sharedOtus);
285 input = new InputData(inputfile, format);
289 if (format == "sharedfile") {
290 lookup = input->getSharedRAbundVectors();
291 lastLabel = lookup[0]->getLabel();
293 if ((lookup.size() > 4)) { combos = findCombinations(lookup.size()); }
294 }else if (format == "list") {
295 sabund = input->getSAbundVector();
296 lastLabel = sabund->getLabel();
299 //if the users enters label "0.06" and there is no "0.06" in their file use the next lowest label.
300 set<string> processedLabels;
301 set<string> userLabels = labels;
303 if (format != "list") {
305 //as long as you are not at the end of the file or done wih the lines you want
306 while((lookup[0] != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
308 if (m->control_pressed) {
309 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
310 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
311 m->clearGroups(); delete venn; delete input;
312 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
316 if(allLines == 1 || labels.count(lookup[0]->getLabel()) == 1){
317 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
318 processedLabels.insert(lookup[0]->getLabel());
319 userLabels.erase(lookup[0]->getLabel());
323 if (lookup.size() > 4) {
324 set< set<int> >::iterator it3;
325 set<int>::iterator it2;
326 for (it3 = combos.begin(); it3 != combos.end(); it3++) {
328 set<int> poss = *it3;
329 vector<SharedRAbundVector*> subset;
330 for (it2 = poss.begin(); it2 != poss.end(); it2++) { subset.push_back(lookup[*it2]); }
332 vector<string> outfilenames = venn->getPic(subset, vennCalculators);
333 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
336 vector<string> outfilenames = venn->getPic(lookup, vennCalculators);
337 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
341 if ((m->anyLabelsToProcess(lookup[0]->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
342 string saveLabel = lookup[0]->getLabel();
344 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
345 lookup = input->getSharedRAbundVectors(lastLabel);
347 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
348 processedLabels.insert(lookup[0]->getLabel());
349 userLabels.erase(lookup[0]->getLabel());
351 if (lookup.size() > 4) {
352 set< set<int> >::iterator it3;
353 set<int>::iterator it2;
354 for (it3 = combos.begin(); it3 != combos.end(); it3++) {
356 set<int> poss = *it3;
357 vector<SharedRAbundVector*> subset;
358 for (it2 = poss.begin(); it2 != poss.end(); it2++) { subset.push_back(lookup[*it2]); }
360 vector<string> outfilenames = venn->getPic(subset, vennCalculators);
361 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
364 vector<string> outfilenames = venn->getPic(lookup, vennCalculators);
365 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
368 //restore real lastlabel to save below
369 lookup[0]->setLabel(saveLabel);
373 lastLabel = lookup[0]->getLabel();
375 //get next line to process
376 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
377 lookup = input->getSharedRAbundVectors();
380 if (m->control_pressed) {
381 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
382 m->clearGroups(); delete venn; delete input;
383 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
388 //output error messages about any remaining user labels
389 set<string>::iterator it;
390 bool needToRun = false;
391 for (it = userLabels.begin(); it != userLabels.end(); it++) {
392 m->mothurOut("Your file does not include the label " + *it);
393 if (processedLabels.count(lastLabel) != 1) {
394 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
397 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
401 //run last label if you need to
402 if (needToRun == true) {
403 for (int i = 0; i < lookup.size(); i++) { if (lookup[i] != NULL) { delete lookup[i]; } }
404 lookup = input->getSharedRAbundVectors(lastLabel);
406 m->mothurOut(lookup[0]->getLabel()); m->mothurOutEndLine();
407 processedLabels.insert(lookup[0]->getLabel());
408 userLabels.erase(lookup[0]->getLabel());
410 if (lookup.size() > 4) {
411 set< set<int> >::iterator it3;
412 set<int>::iterator it2;
413 for (it3 = combos.begin(); it3 != combos.end(); it3++) {
415 set<int> poss = *it3;
416 vector<SharedRAbundVector*> subset;
417 for (it2 = poss.begin(); it2 != poss.end(); it2++) { subset.push_back(lookup[*it2]); }
419 vector<string> outfilenames = venn->getPic(subset, vennCalculators);
420 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
423 vector<string> outfilenames = venn->getPic(lookup, vennCalculators);
424 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
427 for (int i = 0; i < lookup.size(); i++) { delete lookup[i]; }
431 //reset groups parameter
434 if (m->control_pressed) {
435 m->clearGroups(); delete venn; delete input;
436 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
437 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
444 while((sabund != NULL) && ((allLines == 1) || (userLabels.size() != 0))) {
446 if (m->control_pressed) {
447 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
448 delete sabund; delete venn; delete input;
449 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
453 if(allLines == 1 || labels.count(sabund->getLabel()) == 1){
455 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
456 vector<string> outfilenames = venn->getPic(sabund, vennCalculators);
457 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
460 processedLabels.insert(sabund->getLabel());
461 userLabels.erase(sabund->getLabel());
464 if ((m->anyLabelsToProcess(sabund->getLabel(), userLabels, "") == true) && (processedLabels.count(lastLabel) != 1)) {
465 string saveLabel = sabund->getLabel();
468 sabund = input->getSAbundVector(lastLabel);
470 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
471 vector<string> outfilenames = venn->getPic(sabund, vennCalculators);
472 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
475 processedLabels.insert(sabund->getLabel());
476 userLabels.erase(sabund->getLabel());
478 //restore real lastlabel to save below
479 sabund->setLabel(saveLabel);
482 lastLabel = sabund->getLabel();
485 sabund = input->getSAbundVector();
488 if (m->control_pressed) {
489 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
490 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
491 delete venn; delete input;
495 //output error messages about any remaining user labels
496 set<string>::iterator it;
497 bool needToRun = false;
498 for (it = userLabels.begin(); it != userLabels.end(); it++) {
499 m->mothurOut("Your file does not include the label " + *it);
500 if (processedLabels.count(lastLabel) != 1) {
501 m->mothurOut(". I will use " + lastLabel + "."); m->mothurOutEndLine();
504 m->mothurOut(". Please refer to " + lastLabel + "."); m->mothurOutEndLine();
508 //run last label if you need to
509 if (needToRun == true) {
510 if (sabund != NULL) { delete sabund; }
511 sabund = input->getSAbundVector(lastLabel);
513 m->mothurOut(sabund->getLabel()); m->mothurOutEndLine();
514 vector<string> outfilenames = venn->getPic(sabund, vennCalculators);
515 for(int i = 0; i < outfilenames.size(); i++) { if (outfilenames[i] != "control" ) { outputNames.push_back(outfilenames[i]); outputTypes["svg"].push_back(outfilenames[i]); } }
521 if (m->control_pressed) {
522 delete venn; delete input;
523 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
524 for (int i = 0; i < outputNames.size(); i++) { m->mothurRemove(outputNames[i]); }
529 for (int i = 0; i < vennCalculators.size(); i++) { delete vennCalculators[i]; }
530 delete venn; delete input;
532 m->mothurOutEndLine();
533 m->mothurOut("Output File Names: "); m->mothurOutEndLine();
534 for (int i = 0; i < outputNames.size(); i++) { m->mothurOut(outputNames[i]); m->mothurOutEndLine(); }
535 m->mothurOutEndLine();
540 catch(exception& e) {
541 m->errorOut(e, "VennCommand", "execute");
545 //**********************************************************************************************************************
546 //returns a vector of sets containing the group combinations
547 set< set<int> > VennCommand::findCombinations(int lookupSize){
549 set< set<int> > combos;
552 for (int i = 0; i < lookupSize; i++) { possibles.insert(i); }
554 getCombos(possibles, combos);
559 catch(exception& e) {
560 m->errorOut(e, "VennCommand", "findCombinations");
564 //**********************************************************************************************************************
565 //recusively finds combos of length perm
566 int VennCommand::getCombos(set<int> possibles, set< set<int> >& combos){
569 if (possibles.size() == perm) { //done
570 if (combos.count(possibles) == 0) { //no dups
571 combos.insert(possibles);
573 }else { //we still have work to do
574 set<int>::iterator it;
575 set<int>::iterator it2;
576 for (it = possibles.begin(); it != possibles.end(); it++) {
578 set<int> newPossibles;
579 for (it2 = possibles.begin(); it2 != possibles.end(); it2++) { //all possible combos of one length smaller
581 newPossibles.insert(*it2);
584 getCombos(newPossibles, combos);
590 catch(exception& e) {
591 m->errorOut(e, "VennCommand", "getCombos");
596 //**********************************************************************************************************************