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