]> git.donarmstrong.com Git - mothur.git/blob - parsimony.cpp
rewrote metastats command in c++, added mothurRemove function to handle ~ error....
[mothur.git] / parsimony.cpp
1 /*
2  *  parsimony.cpp
3  *  Mothur
4  *
5  *  Created by Sarah Westcott on 1/26/09.
6  *  Copyright 2009 Schloss Lab UMASS Amherst. All rights reserved.
7  *
8  */
9
10 #include "parsimony.h"
11
12 /**************************************************************************************************/
13
14 EstOutput Parsimony::getValues(Tree* t, int p, string o) {
15         try {
16                 processors = p;
17                 outputDir = o;
18                 
19                 //if the users enters no groups then give them the score of all groups
20                 int numGroups = m->Groups.size();
21                 
22                 //calculate number of comparsions
23                 int numComp = 0;
24                 vector< vector<string> > namesOfGroupCombos;
25                 for (int r=0; r<numGroups; r++) { 
26                         for (int l = r+1; l < numGroups; l++) {
27                                 numComp++;
28                                 vector<string> groups; groups.push_back(m->Groups[r]); groups.push_back(m->Groups[l]);
29                                 //cout << globaldata->Groups[r] << '\t' << globaldata->Groups[l] << endl;
30                                 namesOfGroupCombos.push_back(groups);
31                         }
32                 }
33
34                 //numComp+1 for AB, AC, BC, ABC
35                 if (numComp != 1) {
36                         vector<string> groups;
37                         if (numGroups == 0) {
38                                 //get score for all users groups
39                                 for (int i = 0; i < tmap->namesOfGroups.size(); i++) {
40                                         if (tmap->namesOfGroups[i] != "xxx") {
41                                                 groups.push_back(tmap->namesOfGroups[i]);
42                                                 //cout << tmap->namesOfGroups[i] << endl;
43                                         }
44                                 }
45                                 namesOfGroupCombos.push_back(groups);
46                         }else {
47                                 for (int i = 0; i < m->Groups.size(); i++) {
48                                         groups.push_back(m->Groups[i]);
49                                         //cout << globaldata->Groups[i] << endl;
50                                 }
51                                 namesOfGroupCombos.push_back(groups);
52                         }
53                 }
54                 
55         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
56                 if(processors == 1){
57                         data = driver(t, namesOfGroupCombos, 0, namesOfGroupCombos.size());
58                 }else{
59                         lines.clear();
60                         int numPairs = namesOfGroupCombos.size();
61                         
62                         int numPairsPerProcessor = numPairs / processors;
63                         
64                         for (int i = 0; i < processors; i++) {
65                                 int startPos = i * numPairsPerProcessor;
66                                 
67                                 if(i == processors - 1){
68                                         numPairsPerProcessor = numPairs - i * numPairsPerProcessor;
69                                 }
70                                 
71                                 lines.push_back(linePair(startPos, numPairsPerProcessor));
72                         }
73                         
74                         data = createProcesses(t, namesOfGroupCombos);
75                 }
76         #else
77                 data = driver(t, namesOfGroupCombos, 0, namesOfGroupCombos.size());
78         #endif
79                 
80                 return data;
81                 
82         }
83         catch(exception& e) {
84                 m->errorOut(e, "Parsimony", "getValues");
85                 exit(1);
86         }
87 }
88 /**************************************************************************************************/
89
90 EstOutput Parsimony::createProcesses(Tree* t, vector< vector<string> > namesOfGroupCombos) {
91         try {
92 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
93                 int process = 1;
94                 vector<int> processIDS;
95                 
96                 EstOutput results;
97                 
98                 //loop through and create all the processes you want
99                 while (process != processors) {
100                         int pid = fork();
101                         
102                         if (pid > 0) {
103                                 processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
104                                 process++;
105                         }else if (pid == 0){
106                                 EstOutput myresults;
107                                 myresults = driver(t, namesOfGroupCombos, lines[process].start, lines[process].num);
108                                 
109                                 if (m->control_pressed) { exit(0); }
110                                 
111                                 //pass numSeqs to parent
112                                 ofstream out;
113                                 string tempFile = outputDir + toString(getpid()) + ".pars.results.temp";
114                                 m->openOutputFile(tempFile, out);
115                                 out << myresults.size() << endl;
116                                 for (int i = 0; i < myresults.size(); i++) {  out << myresults[i] << '\t';  } out << endl;
117                                 out.close();
118                                 
119                                 exit(0);
120                         }else { 
121                                 m->mothurOut("[ERROR]: unable to spawn the necessary processes."); m->mothurOutEndLine(); 
122                                 for (int i = 0; i < processIDS.size(); i++) { kill (processIDS[i], SIGINT); }
123                                 exit(0); 
124                         }
125                 }
126                 
127                 results = driver(t, namesOfGroupCombos, lines[0].start, lines[0].num);
128                 
129                 //force parent to wait until all the processes are done
130                 for (int i=0;i<processIDS.size();i++) { 
131                         int temp = processIDS[i];
132                         wait(&temp);
133                 }
134                 
135                 if (m->control_pressed) { return results; }
136                         
137                 //get data created by processes
138                 for (int i=0;i<processIDS.size();i++) { 
139                         ifstream in;
140                         string s = outputDir + toString(processIDS[i]) + ".pars.results.temp";
141                         m->openInputFile(s, in);
142                         
143                         //get scores
144                         if (!in.eof()) {
145                                 int num;
146                                 in >> num; m->gobble(in);
147                                 
148                                 if (m->control_pressed) { break; }
149                                 
150                                 double w; 
151                                 for (int j = 0; j < num; j++) {
152                                         in >> w;
153                                         results.push_back(w);
154                                 }
155                                 m->gobble(in);
156                         }
157                         in.close();
158                         m->mothurRemove(s);
159                 }
160                 
161                 return results;
162 #endif          
163         }
164         catch(exception& e) {
165                 m->errorOut(e, "Parsimony", "createProcesses");
166                 exit(1);
167         }
168 }
169 /**************************************************************************************************/
170 EstOutput Parsimony::driver(Tree* t, vector< vector<string> > namesOfGroupCombos, int start, int num) { 
171         try {
172                 
173                 EstOutput results; results.resize(num);
174                 
175                 Tree* copyTree = new Tree(tmap);
176                 int count = 0;
177                 
178                 for (int h = start; h < (start+num); h++) {
179                                         
180                         if (m->control_pressed) { delete copyTree; return results; }
181         
182                         int score = 0;
183                         
184                         //groups in this combo
185                         vector<string> groups = namesOfGroupCombos[h];
186                         
187                         //copy users tree so that you can redo pgroups 
188                         copyTree->getCopy(t);
189                         
190                         //create pgroups that reflect the groups the user want to use
191                         for(int i=copyTree->getNumLeaves();i<copyTree->getNumNodes();i++){
192                                 copyTree->tree[i].pGroups = (copyTree->mergeUserGroups(i, groups));
193                         }
194                         
195                         for(int i=copyTree->getNumLeaves();i<copyTree->getNumNodes();i++){
196                                 
197                                 if (m->control_pressed) { return data; }
198                                 
199                                 int lc = copyTree->tree[i].getLChild();
200                                 int rc = copyTree->tree[i].getRChild();
201                                 
202                                 int iSize = copyTree->tree[i].pGroups.size();
203                                 int rcSize = copyTree->tree[rc].pGroups.size();
204                                 int lcSize = copyTree->tree[lc].pGroups.size();
205                                 
206                                 //if isize are 0 then that branch is to be ignored
207                                 if (iSize == 0) { }
208                                 else if ((rcSize == 0) || (lcSize == 0)) { }
209                                 //if you have more groups than either of your kids then theres been a change.
210                                 else if(iSize > rcSize || iSize > lcSize){
211                                         score++;
212                                 }
213                         } 
214                         
215                         results[count] = score;
216                         count++;
217                 }
218                                         
219                 delete copyTree;
220                         
221                 return results; 
222         }
223         catch(exception& e) {
224                 m->errorOut(e, "Parsimony", "driver");
225                 exit(1);
226         }
227 }
228
229 /**************************************************************************************************/
230