5 // Created by SarahsWork on 6/17/13.
6 // Copyright (c) 2013 Schloss Lab. All rights reserved.
11 /************************************************************/
12 DesignMap::DesignMap(string file) {
14 m = MothurOut::getInstance();
15 defaultClass = "not found";
19 m->errorOut(e, "DesignMap", "DesignMap");
23 /************************************************************/
24 int DesignMap::read(string file) {
27 m->openInputFile(file, in);
29 string headers = m->getline(in); m->gobble(in);
30 vector<string> columnHeaders = m->splitWhiteSpace(headers);
32 namesOfCategories.clear();
33 indexCategoryMap.clear();
36 map<int, string> originalGroupIndexes;
37 for (int i = 1; i < columnHeaders.size(); i++) { namesOfCategories.push_back(columnHeaders[i]); originalGroupIndexes[i-1] = columnHeaders[i]; }
38 if (columnHeaders.size() > 1) { defaultClass = columnHeaders[1]; }
40 //sort groups to keep consistent with how we store the groups in groupmap
41 sort(namesOfCategories.begin(), namesOfCategories.end());
42 for (int i = 0; i < namesOfCategories.size(); i++) { indexCategoryMap[namesOfCategories[i]] = i; }
43 int numCategories = namesOfCategories.size();
47 totalCategories.resize(numCategories);
51 if (m->control_pressed) { break; }
53 in >> group; m->gobble(in);
54 if (m->debug) { m->mothurOut("[DEBUG]: group = " + group + "\n"); }
56 //if group info, then read it
57 vector<string> categoryValues; categoryValues.resize(numCategories, "not found");
58 for (int i = 0; i < numCategories; i++) {
59 int thisIndex = indexCategoryMap[originalGroupIndexes[i]]; //find index of this category because we sort the values.
60 string temp = "not found";
61 in >> temp; categoryValues[thisIndex] = temp; m->gobble(in);
63 if (m->debug) { m->mothurOut("[DEBUG]: value = " + temp + "\n"); }
65 //do we have this value for this category already
66 map<string, int>::iterator it = totalCategories[thisIndex].find(temp);
67 if (it == totalCategories[thisIndex].end()) { totalCategories[thisIndex][temp] = 1; }
68 else { totalCategories[thisIndex][temp]++; }
72 map<string, int>::iterator it = indexNameMap.find(group);
73 if (it == indexNameMap.end()) {
74 indexNameMap[group] = count;
75 designMap.push_back(categoryValues);
79 m->mothurOut("[ERROR]: Your design file contains more than 1 group named " + group + ", group names must be unique. Please correct."); m->mothurOutEndLine();
85 for (int i = 0; i < totalCategories.size(); i++) {
86 map<string, int>::iterator it = totalCategories[i].find(namesOfCategories[i]);
87 if (it != totalCategories[i].end()) { //we may have an old style design file since category name matches a value
88 m->mothurOut("\n[WARNING]: Your design file has a category and value for that category named " + namesOfCategories[i] + ". Perhaps you are using an old style design file without headers? If so, please correct."); m->mothurOutEndLine();
92 if (error) { m->control_pressed = true; }
97 m->errorOut(e, "DesignMap", "read");
101 /************************************************************/
102 ////groupName, returns first categories value.
103 string DesignMap::get(string groupName) {
105 string value = "not found";
107 map<string, int>::iterator it2 = indexNameMap.find(groupName);
108 if (it2 == indexNameMap.end()) {
109 m->mothurOut("[ERROR]: group " + groupName + " is not in your design file. Please correct.\n"); m->control_pressed = true;
111 return designMap[it2->second][0];
116 catch(exception& e) {
117 m->errorOut(e, "DesignMap", "get");
121 /************************************************************/
122 ////categoryName, returns category values.
123 vector<string> DesignMap::getValues(string catName) {
125 vector<string> values;
127 map<string, int>::iterator it2 = indexCategoryMap.find(catName);
128 if (it2 == indexCategoryMap.end()) {
129 m->mothurOut("[ERROR]: category " + catName + " is not in your design file. Please correct.\n"); m->control_pressed = true;
131 for (map<string, int>::iterator it = totalCategories[it2->second].begin(); it != totalCategories[it2->second].end(); it++) {
132 values.push_back(it->first);
138 catch(exception& e) {
139 m->errorOut(e, "DesignMap", "getValues");
144 /************************************************************/
145 ////groupName, category returns value. example F000132, sex -> male
146 string DesignMap::get(string groupName, string categoryName) {
148 string value = "not found";
149 map<string, int>::iterator it = indexCategoryMap.find(categoryName);
150 if (it == indexCategoryMap.end()) {
151 m->mothurOut("[ERROR]: category " + categoryName + " is not in your design file. Please correct.\n"); m->control_pressed = true;
153 map<string, int>::iterator it2 = indexNameMap.find(groupName);
154 if (it2 == indexNameMap.end()) {
155 m->mothurOut("[ERROR]: group " + groupName + " is not in your design file. Please correct.\n"); m->control_pressed = true;
157 return designMap[it2->second][it->second];
162 catch(exception& e) {
163 m->errorOut(e, "DesignMap", "get");
167 /************************************************************/
168 //add group, assumes order is correct
169 int DesignMap::push_back(string group, vector<string> values) {
171 map<string, int>::iterator it = indexNameMap.find(group);
172 if (it == indexNameMap.end()) {
173 if (values.size() != getNumCategories()) { m->mothurOut("[ERROR]: Your design file has a " + toString(getNumCategories()) + " categories and " + group + " has " + toString(values.size()) + ", please correct."); m->mothurOutEndLine(); m->control_pressed = true; return 0; }
175 for (int i = 0; i < values.size(); i++) {
176 //do we have this value for this category already
177 map<string, int>::iterator it = totalCategories[i].find(values[i]);
178 if (it == totalCategories[i].end()) { totalCategories[i][values[i]] = 1; }
179 else { totalCategories[i][values[i]]++; }
181 int count = indexNameMap.size();
182 indexNameMap[group] = count;
183 designMap.push_back(values);
185 m->mothurOut("[ERROR]: Your design file contains more than 1 group named " + group + ", group names must be unique. Please correct."); m->mothurOutEndLine(); m->control_pressed = true;
190 catch(exception& e) {
191 m->errorOut(e, "DesignMap", "push_back");
195 /************************************************************/
196 //set values for group, does not need to set all values. assumes group is in table already
197 int DesignMap::set(string group, map<string, string> values) {
199 map<string, int>::iterator it = indexNameMap.find(group);
200 if (it != indexNameMap.end()) {
201 for (map<string, string>::iterator it2 = values.begin(); it2 != values.end(); it2++) {
203 map<string, int>::iterator it3 = indexCategoryMap.find(it2->first); //do we have this category
204 if (it3 == indexCategoryMap.end()) {
205 m->mothurOut("[ERROR]: Your design file does not contain a category called " + it2->first + ". Please correct."); m->mothurOutEndLine(); m->control_pressed = true;
207 string oldCategory = designMap[it->second][it3->second];
208 //adjust totals for old category
209 int oldCount = totalCategories[it3->second][oldCategory];
210 if (oldCount == 1) { totalCategories[it3->second].erase(oldCategory); }
211 else { totalCategories[it3->second][oldCategory]--; }
213 designMap[it->second][it3->second] = it2->second; //reset value
215 //adjust totals for new category
216 map<string, int>::iterator it4 = totalCategories[it3->second].find(it2->second);
217 if (it4 == totalCategories[it3->second].end()) { totalCategories[it3->second][it2->second] = 1; }
218 else { totalCategories[it3->second][it2->second]++; }
222 m->mothurOut("[ERROR]: Your design file does not contain a group named " + group + ". Please correct."); m->mothurOutEndLine(); m->control_pressed = true;
227 catch(exception& e) {
228 m->errorOut(e, "DesignMap", "set");
232 /************************************************************/
233 //get number of groups belonging to a category or set of categories, with value or a set of values. Must have all categories and values. Example:
234 // map<treatment - > early, late>, <sex -> male> would return 1. Only one group is male and from early or late.
235 int DesignMap::getNumUnique(map<string, vector<string> > selected) {
239 //get indexes of categories
241 for (map<string, vector<string> >::iterator it = selected.begin(); it != selected.end(); it++) {
242 map<string, int>::iterator it2 = indexCategoryMap.find(it->first);
243 if (it2 == indexCategoryMap.end()) {
244 m->mothurOut("[ERROR]: Your design file does not contain a category named " + it->first + ". Please correct."); m->mothurOutEndLine(); m->control_pressed = true; return 0;
245 }else { indexes.push_back(it2->second); }
248 for (int i = 0; i < designMap.size(); i++) {
249 bool hasAll = true; //innocent til proven guilty
251 for (map<string, vector<string> >::iterator it = selected.begin(); it != selected.end(); it++) { //loop through each
252 //check category to see if this group meets the requirements
253 if (!m->inUsersGroups(designMap[i][indexes[count]], it->second)) { hasAll = false; it = selected.end(); }
256 if (hasAll) { num++; }
261 catch(exception& e) {
262 m->errorOut(e, "DesignMap", "getNumUnique");
266 /************************************************************/
267 //get number of groups belonging to a category or set of categories, with value or a set of values. Must have at least one categories and values. Example:
268 // map<treatment - > early, late>, <sex -> male> would return 3. All three group have are either male or from early or late.
269 int DesignMap::getNumShared(map<string, vector<string> > selected) {
273 //get indexes of categories
275 for (map<string, vector<string> >::iterator it = selected.begin(); it != selected.end(); it++) {
276 map<string, int>::iterator it2 = indexCategoryMap.find(it->first);
277 if (it2 == indexCategoryMap.end()) {
278 m->mothurOut("[ERROR]: Your design file does not contain a category named " + it->first + ". Please correct."); m->mothurOutEndLine(); m->control_pressed = true; return 0;
279 }else { indexes.push_back(it2->second); }
282 for (int i = 0; i < designMap.size(); i++) {
283 bool hasAny = false; //guilty til proven innocent
285 for (map<string, vector<string> >::iterator it = selected.begin(); it != selected.end(); it++) { //loop through each
286 //check category to see if this group meets the requirements
287 if (m->inUsersGroups(designMap[i][indexes[count]], it->second)) { hasAny = true; it = selected.end(); }
290 if (hasAny) { num++; }
296 catch(exception& e) {
297 m->errorOut(e, "DesignMap", "getNumShared");
302 /************************************************************/
303 //get names of groups belonging to a category or set of categories, with value or a set of values. Must have all categories and values. Example:
304 // map<treatment - > early, late>, <sex -> male> would return F000132. F000132 is the only group which is male and from early or late.
305 vector<string> DesignMap::getNamesUnique(map<string, vector<string> > selected) {
307 vector<string> names;
309 //get indexes of categories
311 for (map<string, vector<string> >::iterator it = selected.begin(); it != selected.end(); it++) {
312 map<string, int>::iterator it2 = indexCategoryMap.find(it->first);
313 if (it2 == indexCategoryMap.end()) {
314 m->mothurOut("[ERROR]: Your design file does not contain a category named " + it->first + ". Please correct."); m->mothurOutEndLine(); m->control_pressed = true; return names;
315 }else { indexes.push_back(it2->second); }
319 map<int, string> reverse;
320 for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) {
321 reverse[it->second] = it->first;
324 for (int i = 0; i < designMap.size(); i++) {
325 bool hasAll = true; //innocent til proven guilty
327 for (map<string, vector<string> >::iterator it = selected.begin(); it != selected.end(); it++) { //loop through each
328 //check category to see if this group meets the requirements
329 if (!m->inUsersGroups(designMap[i][indexes[count]], it->second)) { hasAll = false; it = selected.end(); }
333 map<int, string>::iterator it = reverse.find(i);
334 if (it == reverse.end()) {
335 m->mothurOut("[ERROR]: should never get here, oops. Please correct."); m->mothurOutEndLine(); m->control_pressed = true; return names;
336 }else { names.push_back(it->second); }
343 catch(exception& e) {
344 m->errorOut(e, "DesignMap", "getNamesUnique");
348 /************************************************************/
349 //get names of groups belonging to a category or set of categories, with value or a set of values. Must have all categories and values. Example:
350 // map<treatment - > early, late>, <sex -> male> would return F000132. F000132 is the only group which is male and from early or late.
351 vector<string> DesignMap::getNamesShared(map<string, vector<string> > selected) {
353 vector<string> names;
355 //get indexes of categories
357 for (map<string, vector<string> >::iterator it = selected.begin(); it != selected.end(); it++) {
358 map<string, int>::iterator it2 = indexCategoryMap.find(it->first);
359 if (it2 == indexCategoryMap.end()) {
360 m->mothurOut("[ERROR]: Your design file does not contain a category named " + it->first + ". Please correct."); m->mothurOutEndLine(); m->control_pressed = true; return names;
361 }else { indexes.push_back(it2->second); }
365 map<int, string> reverse;
366 for (map<string, int>::iterator it = indexNameMap.begin(); it != indexNameMap.end(); it++) {
367 reverse[it->second] = it->first;
370 for (int i = 0; i < designMap.size(); i++) {
373 for (map<string, vector<string> >::iterator it = selected.begin(); it != selected.end(); it++) { //loop through each
374 //check category to see if this group meets the requirements
375 if (m->inUsersGroups(designMap[i][indexes[count]], it->second)) { hasAny = true; it = selected.end(); }
379 map<int, string>::iterator it = reverse.find(i);
380 if (it == reverse.end()) {
381 m->mothurOut("[ERROR]: should never get here, oops. Please correct."); m->mothurOutEndLine(); m->control_pressed = true; return names;
382 }else { names.push_back(it->second); }
389 catch(exception& e) {
390 m->errorOut(e, "DesignMap", "getNamesShared");
395 /************************************************************/
396 //get names of groups belonging to a category or set of categories, with value or a set of values. Must have at least one categories and values. Example:
397 // map<treatment - > early, late>, <sex -> male> would return F000132, F000142, F000138. All three group have are either male or from early or late.
399 vector<string> DesignMap::getNames(string category, string value) {
401 vector<string> names;
403 map<string, int>::iterator it = indexCategoryMap.find(category);
404 if (it == indexCategoryMap.end()) {
405 m->mothurOut("[ERROR]: category " + category + " is not in your design file. Please correct.\n"); m->control_pressed = true;
407 int column = it->second;
410 map<int, string> reverse;
411 for (map<string, int>::iterator it2 = indexNameMap.begin(); it2 != indexNameMap.end(); it2++) {
412 reverse[it2->second] = it2->first;
415 for (int i = 0; i < designMap.size(); i++) {
416 if (designMap[i][column] == value) {
417 map<int, string>::iterator it2 = reverse.find(i);
418 if (it2 == reverse.end()) {
419 m->mothurOut("[ERROR]: should never get here, oops. Please correct."); m->mothurOutEndLine(); m->control_pressed = true; return names;
420 }else { names.push_back(it2->second); }
427 catch(exception& e) {
428 m->errorOut(e, "DesignMap", "getNames");
433 /************************************************************/
434 int DesignMap::print(ofstream& out) {
438 for (int i = 0; i < namesOfCategories.size(); i++) { out << namesOfCategories[i] << '\t'; }
441 map<int, string> reverse; //use this to preserve order
442 for (map<string, int>::iterator it = indexNameMap.begin(); it !=indexNameMap.end(); it++) { reverse[it->second] = it->first; }
444 for (int i = 0; i < designMap.size(); i++) {
445 map<int, string>::iterator itR = reverse.find(i);
447 if (itR != reverse.end()) { //will equal end if seqs were removed because remove just removes from indexNameMap
448 out << itR->second << '\t';
450 for (int j = 0; j < namesOfCategories.size(); j++) {
451 out << designMap[i][j] << '\t';
460 catch(exception& e) {
461 m->errorOut(e, "DesignMap", "print");
465 /************************************************************/
466 //print specific categories
467 int DesignMap::print(ofstream& out, vector<string> cats) {
471 for (int i = 0; i < namesOfCategories.size(); i++) { if (m->inUsersGroups(namesOfCategories[i], cats)) { out << namesOfCategories[i] << '\t'; } }
474 map<int, string> reverse; //use this to preserve order
475 for (map<string, int>::iterator it = indexNameMap.begin(); it !=indexNameMap.end(); it++) { reverse[it->second] = it->first; }
477 for (int i = 0; i < designMap.size(); i++) {
478 map<int, string>::iterator itR = reverse.find(i);
480 if (itR != reverse.end()) { //will equal end if seqs were removed because remove just removes from indexNameMap
481 out << itR->second << '\t';
483 for (int j = 0; j < namesOfCategories.size(); j++) {
484 if (m->inUsersGroups(namesOfCategories[i], cats)) {
485 out << designMap[i][j] << '\t';
495 catch(exception& e) {
496 m->errorOut(e, "DesignMap", "print");
501 /************************************************************/