]> git.donarmstrong.com Git - mothur.git/blob - parsimony.cpp
1b08e8a3fe8470e5d34944722e186fdca7e0731b
[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         CountTable* ct = t->getCountTable();
19                 
20                 //if the users enters no groups then give them the score of all groups
21                 vector<string> mGroups = m->getGroups();
22                 int numGroups = mGroups.size();
23                 
24                 //calculate number of comparsions
25                 int numComp = 0;
26                 vector< vector<string> > namesOfGroupCombos;
27                 for (int r=0; r<numGroups; r++) { 
28                         for (int l = 0; l < r; l++) {
29                                 numComp++;
30                                 vector<string> groups; groups.push_back(mGroups[r]); groups.push_back(mGroups[l]);
31                                 //cout << globaldata->Groups[r] << '\t' << globaldata->Groups[l] << endl;
32                                 namesOfGroupCombos.push_back(groups);
33                         }
34                 }
35
36                 //numComp+1 for AB, AC, BC, ABC
37                 if (numComp != 1) {
38                         vector<string> groups;
39                         if (numGroups == 0) {
40                                 //get score for all users groups
41                                 vector<string> tGroups = ct->getNamesOfGroups();
42                                 for (int i = 0; i < tGroups.size(); i++) {
43                                         if (tGroups[i] != "xxx") {
44                                                 groups.push_back(tGroups[i]);
45                                                 //cout << tmap->namesOfGroups[i] << endl;
46                                         }
47                                 }
48                                 namesOfGroupCombos.push_back(groups);
49                         }else {
50                                 for (int i = 0; i < mGroups.size(); i++) {
51                                         groups.push_back(mGroups[i]);
52                                         //cout << globaldata->Groups[i] << endl;
53                                 }
54                                 namesOfGroupCombos.push_back(groups);
55                         }
56                 }
57         
58         lines.clear();
59         int remainingPairs = namesOfGroupCombos.size();
60         int startIndex = 0;
61         for (int remainingProcessors = processors; remainingProcessors > 0; remainingProcessors--) {
62             int numPairs = remainingPairs; //case for last processor
63             if (remainingProcessors != 1) { numPairs = ceil(remainingPairs / remainingProcessors); }
64             lines.push_back(linePair(startIndex, numPairs)); //startIndex, numPairs
65             startIndex = startIndex + numPairs;
66             remainingPairs = remainingPairs - numPairs;
67         }
68         
69         data = createProcesses(t, namesOfGroupCombos, ct);
70                 
71                 return data;
72                 
73         }
74         catch(exception& e) {
75                 m->errorOut(e, "Parsimony", "getValues");
76                 exit(1);
77         }
78 }
79 /**************************************************************************************************/
80
81 EstOutput Parsimony::createProcesses(Tree* t, vector< vector<string> > namesOfGroupCombos, CountTable* ct) {
82         try {
83         int process = 1;
84                 vector<int> processIDS;
85                 
86                 EstOutput results;
87
88 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
89                                 
90                 //loop through and create all the processes you want
91                 while (process != processors) {
92                         int pid = fork();
93                         
94                         if (pid > 0) {
95                                 processIDS.push_back(pid);  //create map from line number to pid so you can append files in correct order later
96                                 process++;
97                         }else if (pid == 0){
98                                 EstOutput myresults;
99                                 myresults = driver(t, namesOfGroupCombos, lines[process].start, lines[process].num, ct);
100                                 
101                                 if (m->control_pressed) { exit(0); }
102                                 
103                                 //pass numSeqs to parent
104                                 ofstream out;
105                                 string tempFile = outputDir + toString(getpid()) + ".pars.results.temp";
106                                 m->openOutputFile(tempFile, out);
107                                 out << myresults.size() << endl;
108                                 for (int i = 0; i < myresults.size(); i++) {  out << myresults[i] << '\t';  } out << endl;
109                                 out.close();
110                                 
111                                 exit(0);
112                         }else { 
113                                 m->mothurOut("[ERROR]: unable to spawn the necessary processes."); m->mothurOutEndLine(); 
114                                 for (int i = 0; i < processIDS.size(); i++) { kill (processIDS[i], SIGINT); }
115                                 exit(0); 
116                         }
117                 }
118                 
119                 results = driver(t, namesOfGroupCombos, lines[0].start, lines[0].num, ct);
120                 
121                 //force parent to wait until all the processes are done
122                 for (int i=0;i<processIDS.size();i++) { 
123                         int temp = processIDS[i];
124                         wait(&temp);
125                 }
126                 
127                 if (m->control_pressed) { return results; }
128                         
129                 //get data created by processes
130                 for (int i=0;i<processIDS.size();i++) { 
131                         ifstream in;
132                         string s = outputDir + toString(processIDS[i]) + ".pars.results.temp";
133                         m->openInputFile(s, in);
134                         
135                         //get scores
136                         if (!in.eof()) {
137                                 int num;
138                                 in >> num; m->gobble(in);
139                                 
140                                 if (m->control_pressed) { break; }
141                                 
142                                 double w; 
143                                 for (int j = 0; j < num; j++) {
144                                         in >> w;
145                                         results.push_back(w);
146                                 }
147                                 m->gobble(in);
148                         }
149                         in.close();
150                         m->mothurRemove(s);
151                 }
152 #else
153         //fill in functions
154         vector<parsData*> pDataArray;
155                 DWORD   dwThreadIdArray[processors-1];
156                 HANDLE  hThreadArray[processors-1];
157         vector<CountTable*> cts;
158         vector<Tree*> trees;
159                 
160                 //Create processor worker threads.
161                 for( int i=1; i<processors; i++ ){
162             CountTable* copyCount = new CountTable();
163             copyCount->copy(ct);
164             Tree* copyTree = new Tree(copyCount);
165             copyTree->getCopy(t);
166             
167             cts.push_back(copyCount);
168             trees.push_back(copyTree);
169             
170             parsData* temppars = new parsData(m, lines[i].start, lines[i].num, namesOfGroupCombos, copyTree, copyCount);
171                         pDataArray.push_back(temppars);
172                         processIDS.push_back(i);
173             
174                         hThreadArray[i-1] = CreateThread(NULL, 0, MyParsimonyThreadFunction, pDataArray[i-1], 0, &dwThreadIdArray[i-1]);
175                 }
176                 
177                 results = driver(t, namesOfGroupCombos, lines[0].start, lines[0].num, ct);
178                 
179                 //Wait until all threads have terminated.
180                 WaitForMultipleObjects(processors-1, hThreadArray, TRUE, INFINITE);
181                 
182                 //Close all thread handles and free memory allocations.
183                 for(int i=0; i < pDataArray.size(); i++){
184             for (int j = 0; j < pDataArray[i]->results.size(); j++) {  results.push_back(pDataArray[i]->results[j]);  }
185                         delete cts[i];
186             delete trees[i];
187                         CloseHandle(hThreadArray[i]);
188                         delete pDataArray[i];
189                 }
190                 
191 #endif          
192         return results;
193         }
194         catch(exception& e) {
195                 m->errorOut(e, "Parsimony", "createProcesses");
196                 exit(1);
197         }
198 }
199 /**************************************************************************************************/
200 EstOutput Parsimony::driver(Tree* t, vector< vector<string> > namesOfGroupCombos, int start, int num, CountTable* ct) { 
201         try {
202                 
203                 EstOutput results; results.resize(num);
204                 
205                 Tree* copyTree = new Tree(ct);
206                 int count = 0;
207                 
208                 for (int h = start; h < (start+num); h++) {
209                                         
210                         if (m->control_pressed) { delete copyTree; return results; }
211         
212                         int score = 0;
213                         
214                         //groups in this combo
215                         vector<string> groups = namesOfGroupCombos[h];
216                         
217                         //copy users tree so that you can redo pgroups 
218                         copyTree->getCopy(t);
219                         
220                         //create pgroups that reflect the groups the user want to use
221                         for(int i=copyTree->getNumLeaves();i<copyTree->getNumNodes();i++){
222                                 copyTree->tree[i].pGroups = (copyTree->mergeUserGroups(i, groups));
223                         }
224                         
225                         for(int i=copyTree->getNumLeaves();i<copyTree->getNumNodes();i++){
226                                 
227                                 if (m->control_pressed) { return data; }
228                                 
229                                 int lc = copyTree->tree[i].getLChild();
230                                 int rc = copyTree->tree[i].getRChild();
231                                 
232                                 int iSize = copyTree->tree[i].pGroups.size();
233                                 int rcSize = copyTree->tree[rc].pGroups.size();
234                                 int lcSize = copyTree->tree[lc].pGroups.size();
235                                 
236                                 //if isize are 0 then that branch is to be ignored
237                                 if (iSize == 0) { }
238                                 else if ((rcSize == 0) || (lcSize == 0)) { }
239                                 //if you have more groups than either of your kids then theres been a change.
240                                 else if(iSize > rcSize || iSize > lcSize){
241                                         score++;
242                                 }
243                         } 
244                         
245                         results[count] = score;
246                         count++;
247                 }
248                                         
249                 delete copyTree;
250                         
251                 return results; 
252         }
253         catch(exception& e) {
254                 m->errorOut(e, "Parsimony", "driver");
255                 exit(1);
256         }
257 }
258
259 /**************************************************************************************************/
260