+int PhyloDiversityCommand::createProcesses(vector<int>& procIters, Tree* t, map< string, vector<float> >& div, map<string, vector<float> >& sumDiv, int numIters, int increment, vector<int>& randomLeaf, set<int>& numSampledList, ofstream& outCollect, ofstream& outSum){
+ try {
+ int process = 1;
+
+ vector<int> processIDS;
+ map< string, vector<float> >::iterator itSum;
+
+ #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
+
+ //loop through and create all the processes you want
+ while (process != processors) {
+ int pid = fork();
+
+ if (pid > 0) {
+ processIDS.push_back(pid); //create map from line number to pid so you can append files in correct order later
+ process++;
+ }else if (pid == 0){
+ driver(t, div, sumDiv, procIters[process], increment, randomLeaf, numSampledList, outCollect, outSum, false);
+
+ string outTemp = outputDir + toString(getpid()) + ".sumDiv.temp";
+ ofstream out;
+ m->openOutputFile(outTemp, out);
+
+ //output the sumDIversity
+ for (itSum = sumDiv.begin(); itSum != sumDiv.end(); itSum++) {
+ out << itSum->first << '\t' << (itSum->second).size() << '\t';
+ for (int k = 0; k < (itSum->second).size(); k++) {
+ out << (itSum->second)[k] << '\t';
+ }
+ out << endl;
+ }
+
+ out.close();
+
+ exit(0);
+ }else {
+ m->mothurOut("[ERROR]: unable to spawn the necessary processes."); m->mothurOutEndLine();
+ for (int i = 0; i < processIDS.size(); i++) { kill (processIDS[i], SIGINT); }
+ exit(0);
+ }
+ }
+
+ driver(t, div, sumDiv, procIters[0], increment, randomLeaf, numSampledList, outCollect, outSum, true);
+
+ //force parent to wait until all the processes are done
+ for (int i=0;i<(processors-1);i++) {
+ int temp = processIDS[i];
+ wait(&temp);
+ }
+
+ //get data created by processes
+ for (int i=0;i<(processors-1);i++) {
+
+ //input the sumDIversity
+ string inTemp = outputDir + toString(processIDS[i]) + ".sumDiv.temp";
+ ifstream in;
+ m->openInputFile(inTemp, in);
+
+ //output the sumDIversity
+ for (int j = 0; j < sumDiv.size(); j++) {
+ string group = "";
+ int size = 0;
+
+ in >> group >> size; m->gobble(in);
+
+ for (int k = 0; k < size; k++) {
+ float tempVal;
+ in >> tempVal;
+
+ sumDiv[group][k] += tempVal;
+ }
+ m->gobble(in);
+ }
+
+ in.close();
+ m->mothurRemove(inTemp);
+ }
+#else
+
+ //fill in functions
+ vector<phylodivData*> pDataArray;
+ DWORD dwThreadIdArray[processors-1];
+ HANDLE hThreadArray[processors-1];
+ vector<CountTable*> cts;
+ vector<Tree*> trees;
+ map<string, int> rootForGroup = getRootForGroups(t);
+
+ //Create processor worker threads.
+ for( int i=1; i<processors; i++ ){
+ CountTable* copyCount = new CountTable();
+ copyCount->copy(ct);
+ Tree* copyTree = new Tree(copyCount);
+ copyTree->getCopy(t);
+
+ cts.push_back(copyCount);
+ trees.push_back(copyTree);
+
+ map<string, vector<float> > copydiv = div;
+ map<string, vector<float> > copysumDiv = sumDiv;
+ vector<int> copyrandomLeaf = randomLeaf;
+ set<int> copynumSampledList = numSampledList;
+ map<string, int> copyRootForGrouping = rootForGroup;
+
+ phylodivData* temp = new phylodivData(m, procIters[i], copydiv, copysumDiv, copyTree, copyCount, increment, copyrandomLeaf, copynumSampledList, copyRootForGrouping);
+ pDataArray.push_back(temp);
+ processIDS.push_back(i);
+
+ hThreadArray[i-1] = CreateThread(NULL, 0, MyPhyloDivThreadFunction, pDataArray[i-1], 0, &dwThreadIdArray[i-1]);
+ }
+
+ driver(t, div, sumDiv, procIters[0], increment, randomLeaf, numSampledList, outCollect, outSum, true);
+
+ //Wait until all threads have terminated.
+ WaitForMultipleObjects(processors-1, hThreadArray, TRUE, INFINITE);
+
+ //Close all thread handles and free memory allocations.
+ for(int i=0; i < pDataArray.size(); i++){
+ for (itSum = pDataArray[i]->sumDiv.begin(); itSum != pDataArray[i]->sumDiv.end(); itSum++) {
+ for (int k = 0; k < (itSum->second).size(); k++) {
+ sumDiv[itSum->first][k] += (itSum->second)[k];
+ }
+ }
+ delete cts[i];
+ delete trees[i];
+ CloseHandle(hThreadArray[i]);
+ delete pDataArray[i];
+ }
+
+#endif
+
+ return 0;
+
+ }
+ catch(exception& e) {
+ m->errorOut(e, "PhyloDiversityCommand", "createProcesses");
+ exit(1);
+ }
+}
+//**********************************************************************************************************************
+int PhyloDiversityCommand::driver(Tree* t, map< string, vector<float> >& div, map<string, vector<float> >& sumDiv, int numIters, int increment, vector<int>& randomLeaf, set<int>& numSampledList, ofstream& outCollect, ofstream& outSum, bool doSumCollect){
+ try {
+ int numLeafNodes = randomLeaf.size();
+ vector<string> mGroups = m->getGroups();
+
+ map<string, int> rootForGroup = getRootForGroups(t); //maps groupName to root node in tree. "root" for group may not be the trees root and we don't want to include the extra branches.
+
+ for (int l = 0; l < numIters; l++) {
+ random_shuffle(randomLeaf.begin(), randomLeaf.end());
+
+ //initialize counts
+ map<string, int> counts;
+ vector< map<string, bool> > countedBranch;
+ for (int i = 0; i < t->getNumNodes(); i++) {
+ map<string, bool> temp;
+ for (int j = 0; j < mGroups.size(); j++) { temp[mGroups[j]] = false; }
+ countedBranch.push_back(temp);
+ }
+
+ for (int j = 0; j < mGroups.size(); j++) { counts[mGroups[j]] = 0; }
+
+ for(int k = 0; k < numLeafNodes; k++){
+
+ if (m->control_pressed) { return 0; }
+
+ //calc branch length of randomLeaf k
+ vector<float> br = calcBranchLength(t, randomLeaf[k], countedBranch, rootForGroup);
+
+ //for each group in the groups update the total branch length accounting for the names file
+ vector<string> groups = t->tree[randomLeaf[k]].getGroup();
+
+ for (int j = 0; j < groups.size(); j++) {
+
+ if (m->inUsersGroups(groups[j], mGroups)) {
+ int numSeqsInGroupJ = 0;
+ map<string, int>::iterator it;
+ it = t->tree[randomLeaf[k]].pcount.find(groups[j]);
+ if (it != t->tree[randomLeaf[k]].pcount.end()) { //this leaf node contains seqs from group j
+ numSeqsInGroupJ = it->second;
+ }
+
+ if (numSeqsInGroupJ != 0) { div[groups[j]][(counts[groups[j]]+1)] = div[groups[j]][counts[groups[j]]] + br[j]; }
+
+ for (int s = (counts[groups[j]]+2); s <= (counts[groups[j]]+numSeqsInGroupJ); s++) {
+ div[groups[j]][s] = div[groups[j]][s-1]; //update counts, but don't add in redundant branch lengths
+ }
+ counts[groups[j]] += numSeqsInGroupJ;
+ }
+ }
+ }
+
+ if (rarefy) {
+ //add this diversity to the sum
+ for (int j = 0; j < mGroups.size(); j++) {
+ for (int g = 0; g < div[mGroups[j]].size(); g++) {
+ sumDiv[mGroups[j]][g] += div[mGroups[j]][g];
+ }
+ }
+ }
+
+ if ((collect) && (l == 0) && doSumCollect) { printData(numSampledList, div, outCollect, 1); }
+ if ((summary) && (l == 0) && doSumCollect) { printSumData(div, outSum, 1); }
+ }
+
+ return 0;