https://github.com/trvrb/PACT
Revision a09d33b6e0370e4897c3fba6dc56645e5f7c37d3 authored by Trevor Bedford on 22 October 2013, 00:37:51 UTC, committed by Trevor Bedford on 22 October 2013, 00:37:51 UTC
1 parent d09b9b3
Raw File
Tip revision: a09d33b6e0370e4897c3fba6dc56645e5f7c37d3 authored by Trevor Bedford on 22 October 2013, 00:37:51 UTC
Include example.
Tip revision: a09d33b
coaltree.cpp
/* coaltree.cpp
Copyright 2009-2012 Trevor Bedford <t.bedford@ed.ac.uk>
Member function definitions for CoalescentTree class
*/

/*
This file is part of PACT.

PACT is free software: you can redistribute it and/or modify it under the terms of the GNU General 
Public License as published by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

PACT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the 
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General 
Public License for more details.

You should have received a copy of the GNU General Public License along with PACT.  If not, see 
<http://www.gnu.org/licenses/>.
*/

#include <iostream>
#include <sstream>
#include <fstream>
using std::ofstream;
using std::stringstream;
using std::cout;
using std::endl;
using std::flush;
using std::ios;
using std::fixed;

#include <string>
using std::string;

#include <set>
using std::set;

#include <vector>
using std::vector;

#include <stdexcept>
using std::runtime_error;
using std::out_of_range;

#include <cstdlib>
using std::atof;
using std::atoi;

#include <cmath>
using std::sqrt;
using std::pow;
using std::sin;
using std::cos;
using std::atan2;

#include "coaltree.h"
#include "node.h"
#include "tree.hh"

/* Constructor function to initialize private data */
/* Takes NEWICK parentheses tree as string input */
CoalescentTree::CoalescentTree(string paren) {

	string::iterator is;
	tree<Node>:: iterator it, jt;
	
	// make sure that parentheses are matched, counting '(' and counting ')'
	int leftcount = 0;
	int rightcount = 0;
	for ( is=paren.begin(); is < paren.end(); ++is ) {
		if (*is == '(') { leftcount++; }
		if (*is == ')') { rightcount++; }
	}
	if (leftcount != rightcount) {
		throw runtime_error("unmatched parentheses in in.trees");
	}

	// STARTING TREE /////////////////
	// starting point as single root node
	Node rootNode = Node(0);
	it = nodetree.set_head(rootNode);
	
	// WALK THROUGH NEWICK STRING ////
	// collect a substring, stop at ( ) , :
	
	string nameOrLength = "";
	string bracketed = "";
	int nodeCount = 1;
	bool lengthCheck = false;
	bool bracketCheck = false;
	bool braceCheck = false;
	
	// fill 'nameOrLength' with names and branch lengths
	// 'bracketed' placeholder for bracketed strings
	for (is = paren.begin(); is < paren.end(); ++is ) {
									
		// OUTSIDE OF BRACKETS
		// branch tree, update names, updates branch lengths
		if (!bracketCheck) {
		
			// filling nameOrLength
			if ( (*is >= '0' && *is <= '9') || (*is >= 'A' && *is <= 'Z') || (*is >= 'a' && *is <= 'z') || *is == '.' || *is == '-' || *is == '_' || *is == '/' || *is == '|' ) {
				nameOrLength += *is;
			}	
		
			// : --> name node, keep pointer where it is, prime loop to update a length, set as tip
			if (*is == ':') {
			
				if (nameOrLength.length() > 0) {
					(*it).setName(nameOrLength);
					(*it).setLeaf(true);
					(*it).setLabel(initialDigits(nameOrLength));
					if(initialDigits(nameOrLength) != "0") {
						labelset.insert(initialDigits(nameOrLength));
					}
					nameOrLength = "";
				}
				
				lengthCheck = true;
				
			}	
							
			if ( (*is == '[' || *is == '(' || *is == ')' || *is == ',') && nameOrLength.length() > 0) {
			
				//  update node length, if lengthCheck is flagged
				if (lengthCheck) {
					(*it).setLength(atof(nameOrLength.c_str()));
					lengthCheck = false;			
				}
				
				//  update node name, assuming branch lengths are absent, set as tip
				else {
					(*it).setName(nameOrLength);
					(*it).setLeaf(true);
					(*it).setLabel(initialDigits(nameOrLength));
					if(initialDigits(nameOrLength) != "0") {
						labelset.insert(initialDigits(nameOrLength));
					}
				}
				
				nameOrLength = "";
				
			}			
			
			// ( --> add child node, move pointer to this child node
			if (*is == '(') {
				Node thisNode(nodeCount);
				it = nodetree.append_child(it,thisNode);
				nodeCount++;
			}
	
			// , --> add sister node, move pointer to this sister node
			if (*is == ',') {
				Node thisNode(nodeCount);
				it = nodetree.insert_after(it,thisNode);
				nodeCount++;
			}
			
			// ) --> move pointer to parent node, need to inherit state when moving up the tree
			if (*is == ')') {
				string childLabel = (*it).getLabel();
				it = nodetree.parent(it);
				(*it).setLabel(childLabel);
			}		
		
		}
		
		// prime bracketed
		if (*is == '[') { 
			bracketCheck = true; 
			bracketed = "";
		}		
		
		// INSIDE OF BRACKETS
		// update labels, add migration events
		if (bracketCheck) {
		
			// fill bracketed
			if (bracketCheck && *is != '[' && *is != ']') {
				bracketed += *is;
			}

			if (*is == '{') { braceCheck = true; }
			if (*is == '}') { braceCheck = false; }			
			
		
			if (*is == ']' || (*is == ',' && braceCheck == false)) {
			
	//			cout << bracketed << endl;
			
				// fill 4 strings delimited by ' ', ':' and '=' 
				string::iterator ib;	
				string stringOne = "";
				string stringTwo = "";
				string stringThree = "";
				string stringFour = "";
				int counter = 1;
				
				ib = bracketed.begin();
				while (ib != bracketed.end()) {
					if (*ib != '&' && *ib != '{' && *ib != '}' && *ib != '"') {		// ignore these completely
						if (*ib != ' ' && *ib != '=' && *ib != ':' && *ib != ',') {				// ignore these and increment counter
							if (counter == 1) { stringOne += *ib; }
							if (counter == 2) { stringTwo += *ib; }
							if (counter == 3) { stringThree += *ib; }
							if (counter == 4) { stringFour += *ib; }
						}
						else {
							++counter;
						}
					}
				++ib;
				}
				
				// MIGRATION
				// insert an additional node up the tree
				if (stringOne == "M") {
				
					int fromInt = atoi(stringTwo.c_str()) + 1;
					int toInt = atoi(stringThree.c_str()) + 1;
					double migLength = atof(stringFour.c_str());
					
					stringstream fromStream;
					fromStream << fromInt;
					string from = fromStream.str();
					
					stringstream toStream;
					toStream << toInt;
					string to = toStream.str();					
										
					// push current node back by distance equal to migLength
					double newLength = (*it).getLength() - migLength;
					(*it).setLength(migLength);
		
					// create new intermediate node
					Node migNode(nodeCount);
					migNode.setLabel(from);
					labelset.insert(from);
					migNode.setLength(newLength);
					nodeCount++;
					
					// wrap this new node so that it inherits the old node
					it = nodetree.wrap(it,migNode);						
					
				}
				
				// STATE / LABEL
				// label current node
				if (stringOne == "states") {
					string loc = stringTwo.c_str();
					(*it).setLabel(loc);
					labelset.insert(loc);		
				}
				
				if (stringOne == "location") {
					string loc = stringTwo.c_str();
					(*it).setLabel(loc);
					labelset.insert(loc);		
				}				
				
				// ANTIGENIC
				if (stringOne == "antigenic") {
					double xloc = atof(stringTwo.c_str());
					double yloc = atof(stringThree.c_str());
					(*it).setX(xloc);
					(*it).setY(yloc);					
				}	
				
				// LAYOUT
				if (stringOne == "layout") {
					double xloc = atof(stringTwo.c_str());
					(*it).setX(xloc);				
				}	
				
				// LATITUDE
				if (stringOne == "latitude") {
					double xloc = atof(stringTwo.c_str());
					(*it).setX(xloc);				
				}					
				
				// DIFFUSION
				if (stringOne == "diffusion") {
					double xloc = atof(stringTwo.c_str());
					(*it).setX(xloc);				
				}	
				if (stringOne == "diffTrait") {
					double xloc = atof(stringTwo.c_str());
					(*it).setX(xloc);				
				}					
	
				// AHT
				if (stringOne == "AHT") {
					double xloc = atof(stringTwo.c_str());
					double yloc = atof(stringThree.c_str());
					(*it).setX(xloc);
					(*it).setY(yloc);					
				}	
				
				// ACX_R
				if (stringOne == "AC14_R") {
					double yloc = atof(stringTwo.c_str());
					(*it).setY(yloc);				
				}				
				
				// AHTL
				if (stringOne == "AHTL") {
					double xloc = atof(stringTwo.c_str());
					double yloc = atof(stringThree.c_str());
					double z = atof(stringFour.c_str());
					if (z < 0) {
						(*it).setLabel("south");
					} else {
						(*it).setLabel("north");
					}
					(*it).setX(xloc);
					(*it).setY(yloc);					
				}					
				
				// RATE
				if (stringOne == "rate") {
					double rate = atof(stringTwo.c_str());
					(*it).setRate(rate);
				}				
				
				
				bracketed = "";
				
				if (*is == ']') { 
					bracketCheck = false;
				}
				
			}
		
		}
			
	}
	
	// adding branch length to the parent node's time to get the node's time
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {
			double t = (*jt).getTime() + (*it).getLength();
			(*it).setTime(t);
		}
	}	
	  			  		
	/* go through tree and append to trunk set */
	/* only the last 1/100 of the time span is considered */
	double presentTime = getPresentTime();
	double trunkTime = presentTime / (double) 100;
	renewTrunk(trunkTime);
	
	/* pushing the most recent sample up to time = 0 */
	pushTimesBack(0);
			
}

/* return initial digits in a string, incremented by 1, return 0 on failure 34ATZ -> 35, 3454 -> 0 */
string CoalescentTree::initialDigits(string name) {

	// label is the first digit characters of node string
	int initial = -1;
	
	// if string contains a letter
	bool containsLetter = false;
	for (int i = 0; i < name.length(); ++i) {
		if ( (name[i] >= 'A' && name[i] <= 'Z') || (name[i] >= 'a' && name[i] <= 'z') ) {
			containsLetter = true;
		}
	}
					
	if (containsLetter) {
		// construct substring of initial numbers
		string labelString = "";
		int count = 0;
		while (name[count] >= '0' && name[count] <= '9') {
			labelString += name[count];
			++count;
		}
		// set label to this substring
		initial = atoi(labelString.c_str());
	}
	
	stringstream outStream;
	outStream << initial + 1;
	string out = outStream.str();
	
	return out;

}

/* push dates to agree with a most recent sample date at endTime */
void CoalescentTree::pushTimesBack(double endTime) {
		
	// need to adjust times by this amount
	double diff = endTime - getPresentTime();
		
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		double t = (*it).getTime();
		(*it).setTime(t + diff);
	}	
		  	
}

/* push dates to agree with a most recent sample date at endTime and oldest sample date is startTime */
/* will fail if used on contempory samples */
void CoalescentTree::pushTimesBack(double startTime, double endTime) {
	
	tree<Node>::iterator it, jt;
	double presentTime = getPresentTime();
	
	if (startTime < endTime) {
	
		// STRETCH OR SHRINK //////////////	 
			 
		// find oldest sample	
		double oldestSample = presentTime;
		for (tree<Node>::leaf_iterator lit = nodetree.begin_leaf(); lit != nodetree.end_leaf(); ++lit) {
			if ((*lit).getTime() < oldestSample) { 
				oldestSample = (*lit).getTime(); 
			}
		}
		
		double mp = (endTime - startTime) / (presentTime - oldestSample);
		
		// go through tree and multiple lengths by mp	
		for (it = nodetree.begin(); it != nodetree.end(); ++it) {
			double l = (*it).getLength();
			(*it).setLength(l * mp);
		}	
		
		// update times in tree
		for (it = nodetree.begin(); it != nodetree.end(); ++it) {
			jt = nodetree.parent(it);
			if (nodetree.is_valid(jt)) {
				double t = (*jt).getTime() + (*it).getLength();
				(*it).setTime(t);
			}
		}	
	
	}

	// PUSH BACK /////////////////////

	// need to adjust times by this amount
	double diff = endTime - getPresentTime();
		
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		double t = (*it).getTime();
		(*it).setTime(t + diff);
	}		
		 
}

/* old version of renewTrunk.  This peels back from all current nodes. */
void CoalescentTree::renewTrunk(double t) {

	/* go through tree and append to trunk set */
	double presentTime = getPresentTime();
	tree<Node>::iterator it, jt;
	
	for(it = nodetree.begin(); it != nodetree.end(); ++it) {
		(*it).setTrunk(false);
	}
	
	it = nodetree.begin();
	(*it).setTrunk(true);
	while(it != nodetree.end()) {
		/* find nodes at present */
		if ((*it).getTime() > presentTime - t) {
			jt = it;
			/* move up tree adding nodes to trunk set */
			while (nodetree.is_valid(jt)) {
				(*jt).setTrunk(true);
				jt = nodetree.parent(jt);
			}
		}
		++it;
	}	
}				


/* reduces a tree to a random subset of samples */
void CoalescentTree::reduceTips(double pro) {

	/* start by finding all tips with this label */
	set<int> tipset; 
	tree<Node>::iterator it, jt;
	
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( rgen.uniform(0,1) < pro && (*it).getLeaf() ) {
		
			/* move up tree adding nodes to label set */
			jt = it;
			while (nodetree.is_valid(jt)) {
				tipset.insert( (*jt).getNumber() );
				jt = nodetree.parent(jt);
			}
		
		}
	}
			
	/* erase other nodes from the tree */
	it = nodetree.begin();
	while(it != nodetree.end()) {
		if (tipset.end() == tipset.find( (*it).getNumber() )) {
			it = nodetree.erase(it);
		}
		else {
    		++it;
    	}
    }
        
   	peelBack();     
	reduce();
				
}

/* reduces a tree to just its trunk, takes a single random sample from "current" tips and works backward from this */
void CoalescentTree::renewTrunkRandom(double t) {

	/* go through tree and append to trunk set */
	double presentTime = getPresentTime();
	tree<Node>::iterator it, jt;
	
	/* count tips and set every node as non-trunk */
	int count = 0;	
	for(it = nodetree.begin(); it != nodetree.end(); ++it) {
		(*it).setTrunk(false);
		if ((*it).getTime() > presentTime - t && (*it).getLeaf()) {
			count++;
		}
	}

	int selection = rgen.uniform(0,count);
	count = 0;
	
	it = nodetree.begin();
	(*it).setTrunk(true);
	while(it != nodetree.end()) {
		/* find nodes at present */
		if ((*it).getTime() > presentTime - t && (*it).getLeaf()) {
			if (selection == count) {
				jt = it;
				/* move up tree adding nodes to trunk set */
				while (nodetree.is_valid(jt)) {
					(*jt).setTrunk(true);
					jt = nodetree.parent(jt);
				}
				break;
			}
			count++;
		}
		++it;
	}	
	
}

/* reduces a tree to just its trunk, takes most recent sample and works backward from this */
void CoalescentTree::pruneToTrunk() {
	
	/* erase other nodes from the tree */	
	tree<Node>::iterator it;
	it = nodetree.begin();
	while(it != nodetree.end()) {
		if ( !(*it).getTrunk() ) {
			it = nodetree.erase(it);
		}
		else {
    		++it;
    	}
    }
            
	peelBack();            
	reduce();
			
}


/* reduces a tree to samples with a single label */
void CoalescentTree::pruneToLabel(string label) {

	/* start by finding all tips with this label */
	set<int> nodeset; 
	tree<Node>::iterator it, jt;
	
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( (*it).getLabel() == label && (*it).getLeaf() ) {
		
			/* move up tree adding nodes to label set */
			jt = it;
			while (nodetree.is_valid(jt)) {
				nodeset.insert( (*jt).getNumber() );
				jt = nodetree.parent(jt);
			}
		
		}
	}
			
	/* erase other nodes from the tree */
	it = nodetree.begin();
	while(it != nodetree.end()) {
		if (nodeset.end() == nodeset.find( (*it).getNumber() )) {
			it = nodetree.erase(it);
		}
		else {
    		++it;
    	}
    }
        
//	peelBack();     
	reduce();
				
}

/* reduces a tree to ancestors of a single tip */
void CoalescentTree::pruneToName(string name) {

	/* start by finding all tips with this label */
	set<int> nodeset; 
	tree<Node>::iterator it, jt;
	
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( (*it).getName() == name ) {
		
			/* move up tree adding nodes to label set */
			jt = it;
			while (nodetree.is_valid(jt)) {
				nodeset.insert( (*jt).getNumber() );
				jt = nodetree.parent(jt);
			}
		
		}
	}
			
	/* erase other nodes from the tree */
	it = nodetree.begin();
	while(it != nodetree.end()) {
		if (nodeset.end() == nodeset.find( (*it).getNumber() )) {
			it = nodetree.erase(it);
		}
		else {
    		++it;
    	}
    }
        
//	peelBack();     
//	reduce();
				
}

/* reduces a tree to samples within a specific time frame */
void CoalescentTree::pruneToTime(double start, double stop) {

	/* start by finding all tips within this time frame */
	set<int> nodeset; 
	tree<Node>::iterator it, jt;
	
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( (*it).getTime() > start && (*it).getTime() < stop && (*it).getLeaf() ) {
		
			/* move up tree adding nodes to label set */
			jt = it;
			while (nodetree.is_valid(jt)) {
				nodeset.insert( (*jt).getNumber() );
				jt = nodetree.parent(jt);
			}
		
		}
	}
			
	/* erase other nodes from the tree */
	it = nodetree.begin();
	while(it != nodetree.end()) {
		if (nodeset.end() == nodeset.find( (*it).getNumber() )) {
			it = nodetree.erase(it);
		}
		else {
    		++it;
    	}
    }
        
//	peelBack();     
	reduce();
				
}

/* goes through an ancestral state tree and pads with migration events as an approximation of Markov jumps */
void CoalescentTree::padMigrationEvents() {

	int nodeCount = getMaxNumber();

	tree<Node>::iterator it, jt;
	it = nodetree.begin();
	while(it != nodetree.end()) {	
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {
		
			/* pads nodes which change state and parent shows a bifurcation */		
			if ( (*it).getLabel() != (*jt).getLabel() && nodetree.number_of_children(jt) == 2 ) {
			
				// find migration time and modify child node length
				double totalLength = (*it).getLength();
				double firstLength = rgen.uniform(0, totalLength);
				double secondLength = totalLength - firstLength;
				(*it).setLength(secondLength);	
				
				// create new intermediate node
				Node migNode(nodeCount);
				migNode.setLabel((*jt).getLabel());
				migNode.setLength(firstLength);
				migNode.setTime((*it).getTime() - secondLength);
				nodeCount++;						
				
				// wrap this new node so that it inherits the old node
				it = nodetree.wrap(it, migNode);					
			
			}
			
		}	
		
		++it;
		
	}

}

/* sets all labels in tree to 1 */
void CoalescentTree::collapseLabels() {

	labelset.clear();
	labelset.insert("1");

	tree<Node>::iterator it, jt;
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		(*it).setLabel("1");
	}
							
}

/* trims a tree at its edges 

   		   |-------	 			 |-----
from  ------			 	to	--
   		   |----------		 	 |-----

*/
void CoalescentTree::trimEnds(double start, double stop) {
			
	/* erase nodes from the tree where neither the node nor its parent are between start and stop */
	tree<Node>::iterator it, jt;
	it = nodetree.begin();
	while(it != nodetree.end()) {	
	
		jt = nodetree.parent(it);
	
		if (nodetree.is_valid(jt)) {
	
			/* if node > stop and parent < stop, erase children and prune node back to stop */
			/* this pruning causes an internal node to become an leaf node */
			if ((*it).getTime() > stop && (*jt).getTime() < stop) {
			
				(*it).setTime( stop );
				(*it).setLength( (*it).getTime() - (*jt).getTime() );
				//(*it).setLeaf(false);
				(*it).setLeaf(true);
				nodetree.erase_children(it);
				it = nodetree.begin();
			
			}
			
			/* if node > start and parent < start, push parent up to start */
			/* and reparent anc[node] to be a child of root */
			/* neither node nore anc[node] can be root */
			else if ((*it).getTime() > start && (*jt).getTime() < start) {
			
				(*jt).setTime(start);
				(*jt).setLength(0.0);
				(*jt).setInclude(false);
				nodetree.move_after(nodetree.begin(),jt);
				it = nodetree.begin();
			
			}
			
			else {
				++it;
			}
		
		}
		
		else {
    		++it;
    	}
    }
        
    /* second pass for nodes < start */
    it = nodetree.begin();   
	while(it != nodetree.end()) {	
		if ((*it).getTime() < start) {
			it = nodetree.erase(it);
		}
		else {
    		++it;
    	}
    }
        
	// go through tree and update lengths based on times
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {
			(*it).setLength( (*it).getTime() - (*jt).getTime() );
		}
	}	               
               
	reduce();
					
}

/* cuts up tree into multiple sections */
void CoalescentTree::sectionTree(double start, double window, double step) {

	tree<Node>::iterator it, jt;
	tree<Node> holdtree = nodetree;
	int current = 1;

	double rootTime = getRootTime();
	double presentTime = getPresentTime();

	/* newtree holds the growing tree structure */
	tree<Node> newtree;
	Node tempNode(-1);	
	newtree.set_head(tempNode);

	/* move window forward in time, make sure there are nodes in this window */
	for (double t = start; t < presentTime; t += step) {
		if (t > rootTime) {
		
			// operations all affect nodetree
			nodetree = holdtree;
			trimEnds(t,t + window);	
			current = renumber(current);			// need unique node numbers
			
			//	printTree();
					
			// need to move multiple sibling branches
			// need four sibling iterators, to1 to2 from1 from2
			tree<Node>::sibling_iterator to1, to2, from1, from2;
	
			from1 = nodetree.begin();
			from2 = nodetree.begin();
			while ( nodetree.is_valid(nodetree.next_sibling(from2)) ){
				from2 = nodetree.next_sibling(from2);
			}

			to1 = newtree.begin();
			to2 = newtree.begin();
			while ( newtree.is_valid(newtree.next_sibling(to2)) ){
				to2 = newtree.next_sibling(to2);
			}
					
			newtree.merge(to1,to2,from1,from2,true);
	
		}
	}

	nodetree = newtree;
	
}

/* Reduces tree to just the ancestors of a single slice in time */
/* Used to calcuate diversity, TMRCA and Tajima's D at a particular time */
void CoalescentTree::timeSlice(double slice) {

	/* desire only nodes spanning the time slice */
	/* find these nodes and add them and their ancestors to a set */
	set<int> sliceset; 
	tree<Node>::iterator it, jt, kt;
	it = nodetree.begin();
	while(it != nodetree.end()) {	
	
		jt = nodetree.parent(it);
		
		if (nodetree.is_valid(jt)) {
	
			/* if node > slice and parent < slice, erase children and prune node back to stop */
			/* this pruning causes an internal node to become a leaf node */
			if ((*it).getTime() > slice && (*jt).getTime() <= slice) {
			
			
				// finding rate of location change
				double xlocdiff = (*it).getX() - (*jt).getX();
				double ylocdiff = (*it).getY() - (*jt).getY();
				double xcoorddiff = (*it).getXCoord() - (*jt).getXCoord();
				double ycoorddiff = (*it).getYCoord() - (*jt).getYCoord();				
				double timediff = (*it).getTime() - (*jt).getTime();
				double xlocrate = xlocdiff / timediff;
				double ylocrate = ylocdiff / timediff;
				double xcoordrate = xcoorddiff / timediff;;
				double ycoordrate = ycoorddiff / timediff;;				
			
				// adjusting node
				(*it).setTime( slice );
				(*it).setLength( (*it).getTime() - (*jt).getTime() );
				(*it).setX( (*jt).getX() + (*it).getLength() * xlocrate );
				(*it).setY( (*jt).getY() + (*it).getLength() * ylocrate );
				(*it).setXCoord( (*jt).getXCoord() + (*it).getLength() * xcoordrate );
				(*it).setYCoord( (*jt).getYCoord() + (*it).getLength() * ycoordrate );
				(*it).setLeaf(true);
				nodetree.erase_children(it);
				
				// move up tree adding nodes to sliceset
				jt = it;
				while (nodetree.is_valid(jt)) {
					sliceset.insert( (*jt).getNumber() );
					jt = nodetree.parent(jt);
				}
				
				it = nodetree.begin();
			
			}
			else { ++it; }
    	
    	}
    	else { ++it; }
    	
    }
        
	/* erase other nodes from the tree */
	it = nodetree.begin();
	while(it != nodetree.end()) {
		if (sliceset.end() == sliceset.find( (*it).getNumber() )) {
			it = nodetree.erase(it);
		}
		else {
	   		++it;
    	}
	}    
    
	peelBack();
	reduce();

}

/* Removes descendents of trunk from tree at a single slice in time */
/* Used to calcuate time to fixation */
void CoalescentTree::trunkSlice(double slice) {

	/* desire only nodes spanning the time slice */
	/* these nodes must be trunk nodes */
	tree<Node>::iterator it, jt, kt;
	it = nodetree.begin();
	while(it != nodetree.end()) {	
	
		jt = nodetree.parent(it);
	
		/* if node > slice AND parent < slice AND node is trunk AND parent is trunk */
		/* erase children and prune node back to stop */
		/* this pruning causes an internal node to become a leaf node */
		if ((*it).getTime() > slice && (*jt).getTime() <= slice && (*it).getTrunk() && (*jt).getTrunk()) {
		
			// adjusting node
			(*it).setTime( slice );
			(*it).setLength( (*it).getTime() - (*jt).getTime() );
			(*it).setLeaf(true);
			nodetree.erase_children(it);
		
			it = nodetree.begin();
		
		}
		
		else {
    		++it;
    	}
    	
    }
        
}

/* Reduces tree to just the ancestors of leaf nodes existing in a particular window of time */
/* Used to calcuate diversity, TMRCA and Tajima's D for a window of time */
void CoalescentTree::leafSlice(double start, double stop) {

	/* desire only nodes spanning the time slice */
	/* find these nodes and add them and their ancestors to a set */
	set<int> sliceset; 
	tree<Node>::iterator it, jt, kt;
	it = nodetree.begin();
	while(it != nodetree.end()) {	
	
		/* if node > start AND node < stop && node is leaf */
		/* add ancestors to sliceset */
		/* there will be no children to erase */
		if ((*it).getTime() > start && (*it).getTime() <= stop && (*it).getLeaf()) {
		
			// move up tree adding nodes to sliceset
			jt = it;
			while (nodetree.is_valid(jt)) {
				sliceset.insert( (*jt).getNumber() );
				jt = nodetree.parent(jt);
			}
				
		}
		
		++it;
    	
    }
    
	/* erase other nodes from the tree */
	it = nodetree.begin();
	while(it != nodetree.end()) {
		if (sliceset.end() == sliceset.find( (*it).getNumber() )) {
			it = nodetree.erase(it);
		}
		else {
    		++it;
    	}
    }    
    
	peelBack();
	reduce();

}


/* padded with extra nodes at coalescent time points */
/* causing problems with migration tree */
void CoalescentTree::padTree() { 

	int current = getMaxNumber() + 1;

	tree<Node>::iterator it, end, iterTemp, iterN;
	
	/* construct set of coalescent times */
	set<double>::const_iterator is;
	set<double> tset;
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		tset.insert( (*it).getTime() );
	}
	
	/* pad tree with extra nodes, make sure there is a node at each time slice correspoding to coalescent event */
	it = nodetree.begin();
	while(it != nodetree.end()) {
	
		/* finding what the correct depth of the node should be */
		int newDepth = -1;
		for (is = tset.begin(); is != tset.find( (*it).getTime() ); ++is) {
    		newDepth++;
    	}
    	
    	is++;
	
		if (newDepth > nodetree.depth(it)) {
		
			/* padding with number of nodes equal to the difference in depth levels */
			for(int i = 0; i < newDepth - nodetree.depth(it); i++) {

				Node newNode(current);
				newNode.setLabel( (*it).getLabel() );
				newNode.setTime( *is );
				newNode.setLength( *is - (*it).getTime() );
				
				nodetree.wrap(it,newNode);
	
				current++;
				it = nodetree.begin();
				
			}
	
		}
		
		++it;
	
	}
			  	
}

/* rotate X&Y locations around origin with degrees in radians */
void CoalescentTree::rotateLoc(double deg) {

	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it ) {
		double xloc = (*it).getX();
		double yloc = (*it).getY();
		xloc = xloc * cos(deg) - yloc * sin(deg);
		yloc = xloc * sin(deg) + yloc * cos(deg);
		(*it).setX(xloc);
		(*it).setY(yloc);
	}	

}

/* adds an additional node prior to root, takes all attributes from root accept time */
void CoalescentTree::addTail(double setback) {

	tree<Node>::iterator it, rt;
	
	// Pointer to root node
	rt = nodetree.begin();

	// create new root node
	Node newNode(-1);
	newNode.setLabel( (*rt).getLabel() );
	newNode.setTime( (*rt).getTime() - setback );
	newNode.setLength(0.0);
	newNode.setX( (*rt).getX() );
	newNode.setY( (*rt).getY() );
	newNode.setXCoord( (*rt).getXCoord() );	
	newNode.setYCoord( (*rt).getYCoord() );		
	newNode.setLeaf(false);	
	newNode.setTrunk(true);		
	
	// modify old root node
	(*rt).setLength(setback);
		
	// wrap this new node so that it inherits the old node
	nodetree.wrap(rt,newNode);	
	
}

/* Print indented tree */
void CoalescentTree::printTree() { 

	int rootdepth = nodetree.depth(nodetree.begin());
		
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		for(int i=0; i<nodetree.depth(it)-rootdepth; ++i) 
			cout << "  ";
		cout << (*it).getNumber();
		if ((*it).getName() != "") { 
			cout << " " << (*it).getName();
		}
		cout << " (" << (*it).getTime() << ")";
		cout << " [" << (*it).getLabel() << "]";			
		cout << " {" << (*it).getLength() << "}";	
		cout << " <" << (*it).getX() << "," << (*it).getY() << ">";			
		cout << " |" << (*it).getRate() << "|";			
		if ( !(*it).getInclude()) { 
			cout << " *";
		}		
		cout << endl << flush;
	}
		
}

/* print tree in Mathematica suitable format
Output is:
	leaf list
	trunk list
	tree rules
	label rules
	coordinate rules 
	tip name rules
*/	
void CoalescentTree::printRuleList(string outputFile, bool isCircular) {

//	printTree();

	/* initializing output stream */
	ofstream outStream;
	outStream.open( outputFile.c_str(),ios::app);

	/* setting up y-axis ordering, x-axis is date */
	if (isCircular) {
		adjustCircularCoords();
	}
	else {
		adjustCoords();
	}
	
	tree<Node>::iterator it, jt;
	
	/* print leaf nodes */
	/* a node may be a leaf on the current tree, but not a leaf on the original tree */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getLeaf()) {
			outStream << fixed << (*it).getNumber() << " ";
		}
	}
	outStream << endl;	
	
	/* print trunk nodes */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getTrunk()) {
			outStream << (*it).getNumber() << " ";
		}
	}
	outStream << endl;	
			
	/* print the tree in rule list (Mathematica-ready) format */
	/* print only upward links */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {		// increment past root
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {
			outStream << (*it).getNumber() << "->" << (*jt).getNumber() << " ";
		}
	}
	outStream << endl;
	
	
	/* print mapping of nodes to labels */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {	
		outStream << (*it).getNumber() << "->" << (*it).getLabel() << " ";
	}
	outStream << endl;
	
	/* print mapping of nodes to coordinates */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		outStream << (*it).getNumber() << "->{" << (*it).getXCoord() << "," << (*it).getYCoord() << "} ";
	}
	outStream << endl;
		  	  	
	/* print mapping of nodes to names */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {	
		if ((*it).getName() != "")
			outStream << (*it).getNumber() << "->" << (*it).getName() << " ";
	}
	outStream << endl;  
	
	/* print mapping of nodes to X and Y locations */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {	
		outStream << (*it).getNumber() << "->{" << (*it).getX() << "," << (*it).getY() << "} ";	
	}
	outStream << endl;  	
	  	  	
	outStream.close();
	  	  	
}

void CoalescentTree::printRuleListWithOrdering(string outputFile, vector<string> tipOrdering) {

//	printTree();

	/* initializing output stream */
	ofstream outStream;
	outStream.open( outputFile.c_str(),ios::app);

	/* setting up y-axis ordering, x-axis is date */
	setCoords(tipOrdering);
	
	tree<Node>::iterator it, jt;
	
	/* print leaf nodes */
	/* a node may be a leaf on the current tree, but not a leaf on the original tree */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getLeaf()) {
			outStream << (*it).getNumber() << " ";
		}
	}
	outStream << endl;	
	
	/* print trunk nodes */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getTrunk()) {
			outStream << (*it).getNumber() << " ";
		}
	}
	outStream << endl;	
			
	/* print the tree in rule list (Mathematica-ready) format */
	/* print only upward links */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {		// increment past root
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {
			outStream << (*it).getNumber() << "->" << (*jt).getNumber() << " ";
		}
	}
	outStream << endl;
	
	
	/* print mapping of nodes to labels */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {	
		outStream << (*it).getNumber() << "->\"" << (*it).getLabel() << "\" ";
	}
	outStream << endl;
	
	/* print mapping of nodes to coordinates */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		outStream << (*it).getNumber() << "->{" << (*it).getXCoord() << "," << (*it).getYCoord() << "} ";	
	}
	outStream << endl;
		  	  	
	/* print mapping of nodes to names */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {	
		if ((*it).getName() != "")
			outStream << (*it).getNumber() << "->\"" << (*it).getName() << "\" ";
	}
	outStream << endl;  
	
	/* print mapping of nodes to X and Y locations */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {	
		outStream << (*it).getNumber() << "->{" << (*it).getX() << "," << (*it).getY() << "} ";	
	}
	outStream << endl;  	
	  	  	
	outStream.close();
	  	  	
}

/* Print parentheses tree */
void CoalescentTree::printParen() { 

	tree<Node>::post_order_iterator it;
	it = nodetree.begin_post();
   	
	int currentDepth = nodetree.depth(it);
	for (int i = 0; i < currentDepth; i++) { 
		cout << "("; 
	} 
	cout << (*it).getNumber() << ":" << (*it).getLength(); 
	++it;
	
	/* need to add a '(' whenever the depth increases and a ')' whenever the depth decreases */
	/* only print leaf nodes */
	while(it != nodetree.end_post()) {
		if (nodetree.depth(it) > currentDepth) { 
			cout << ", ("; 
			for (int i = 0; i < nodetree.depth(it) - currentDepth - 1; i++) { 
				cout << "("; 
			}
			if (nodetree.number_of_children(it) == 0) { 
				cout << (*it).getNumber() << ":" << (*it).getLength(); 
			}
		}
		if (nodetree.depth(it) == currentDepth) { 
			if (nodetree.number_of_children(it) == 0) { 
				cout << ", " << (*it).getNumber() << ":" << (*it).getLength(); ; 
			}
		}
		if (nodetree.depth(it) < currentDepth) {
			if (nodetree.number_of_children(it) == 0) { 
				cout << (*it).getNumber() << ":" << (*it).getLength(); 
				cout << ")";		
			}
			else {
				cout << ")";	
				cout << ":" << (*it).getLength();
			}
		}
		currentDepth = nodetree.depth(it);
		++it;
		
	}
	
	cout << endl;

	
}


/* most recent node in tree, will always be a leaf */
double CoalescentTree::getPresentTime() {
	
	double t = (*nodetree.begin()).getTime();
	for (tree<Node>::leaf_iterator it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		if ((*it).getTime() > t) { 
			t = (*it).getTime(); 
		}
	}
	return t;

}

/* most ancient node in tree */
double CoalescentTree::getRootTime() {

	double t = (*nodetree.begin()).getTime();
	for (tree<Node>::leaf_iterator it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		if ((*it).getTime() < t) { 
			t = (*it).getTime(); 
		}
	}
	return t;
}

/* amount of time it takes for all samples to coalesce */
double CoalescentTree::getTMRCA() {
	
	int leafcount = 0;
	for (tree<Node>::leaf_iterator it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		leafcount++;
	}
	
	double tmrca = 0.0;
	if (leafcount > 1) {
		tmrca = getPresentTime() - getRootTime();
	}
	else {
		tmrca /= tmrca;
	}
	
	return tmrca;
	
}

/* number of labels 1 to n */
//int CoalescentTree::getMaxLabel() {
//
//	double n = 0;
//	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it ) {
//		if ( (*it).getLabel() > n ) {
//			n = (*it).getLabel();
//		}
//	}	
//	return n;
//
//}

/* number of leaf nodes */
int CoalescentTree::getLeafCount() {

	double n = 0;
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it ) {
		if ( (*it).getLeaf() ) {
			n++;
		}
	}	
	return n;

}

/* total number of nodes */
int CoalescentTree::getNodeCount() {
	return nodetree.size();
}

/* total length of the tree */
double CoalescentTree::getLength() {

	double length = 0.0;
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it ) {
		if ( (*it).getInclude() ) {
			length += (*it).getLength();
		}
	}	
	return length;

}

/* length of the tree with label l */
double CoalescentTree::getLength(string l) {

	double length = 0.0;
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it ) {
		if ( (*it).getInclude() && (*it).getLabel() == l ) {
			length += (*it).getLength();
		}
	}	
	return length;

}

/* get proportion of root with label */
double CoalescentTree::getRootLabelPro(string l) { 
	
	double pro = 0.0;
	tree<Node>::iterator rt = nodetree.begin();
	if ( (*rt).getLabel() == l) {
		pro = 1.0;
	}
	return pro;
	
}

/* get proportion of tree with label */
double CoalescentTree::getLabelPro(string l) { 

	return getLength(l) / getLength();
	
}

/* proportion of tree that can trace its history forward to present day samples */
/* trunk traced back from the last 1/100 of the time width */
double CoalescentTree::getTrunkPro() { 

	double totalLength = getLength();

	double trunkLength = 0.0;
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it ) {
		if ( (*it).getInclude() && (*it).getTrunk()) {
			trunkLength += (*it).getLength();
		}
	}	
	
	return trunkLength / totalLength;
    	
}

set<string> CoalescentTree::getLabelSet() {
	return labelset;
}

/* returns the proportion of branches with a particular label back from tips */
double CoalescentTree::getLabelProFromTips(string l, double timeWindow) {

	double pro = 0;	
	double count = 0;
	
	/* walk through every tip in the tree and step back to appropriate point */	
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( (*it).getLeaf() ) {
		
			tree<Node>::iterator jt = getNodeBackFromTip(it, timeWindow);
			string label = (*jt).getLabel();
		
			if (l == label) {
				pro += 1.0;
			}
			count += 1.0;
			
		}
	}
		
	pro /= count;
	return pro;

}

/* returns the proportion of branches with a particular label back from tips */
double CoalescentTree::getLabelProFromTips(string l, double timeWindow, string startingLabel) {

	double pro = 0;	
	double count = 0;
	
	/* walk through every tip in the tree and step back to appropriate point */	
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( (*it).getLeaf()  && (*it).getLabel() == startingLabel ) {
		
			tree<Node>::iterator jt = getNodeBackFromTip(it, timeWindow);
			string label = (*jt).getLabel();
		
			if (l == label) {
				pro += 1.0;
			}
			count += 1.0;
			
		}
	}
		
	pro /= count;
	return pro;

}

/* returns the count of coalescent events */
int CoalescentTree::getCoalCount() {

	/* count coalescent events, these are nodes with two children */
	int count = 0;
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getInclude() && nodetree.number_of_children(it) == 2) {		
			count++;
		}
	}
	
	return count;

}

/* returns the count of coalescent events between side branch and trunk */
int CoalescentTree::getCoalCountTrunk() {

	/* count coalescent events, these are nodes with two children */
	/* only include situations where one node is trunk and one node is side branch */
	int count = 0;
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getInclude() && nodetree.number_of_children(it) == 2) {	
			tree<Node>::iterator jt,kt;
			jt = nodetree.child(it,0);
			kt = nodetree.child(it,1);
			if ( ((*jt).getTrunk() && !(*kt).getTrunk()) || (!(*jt).getTrunk() && (*kt).getTrunk())  ) {
				count++;
			}
		}
	}
	
	return count;

}

/* returns the count of coalescent events with label */
int CoalescentTree::getCoalCount(string l) {

	/* count coalescent events, these are nodes with two children */
	int count = 0;
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getInclude() && nodetree.number_of_children(it) == 2 && (*it).getLabel() == l ) {		
			count++;
		}
	}
	return count;

}

/* returns the opportunity for coalescence over the whole tree */
/* running this will padTree() may be faster and more accurate */
double CoalescentTree::getCoalWeight() {

	// setting step to be 1/1000 of the total length of the tree
	double start = getRootTime();
	double stop = getPresentTime();
	double step = (stop - start) / (double) 1000;
	
	// step through tree counting concurrent lineages
	double weight = 0.0;
	for (double t = start; t <= stop; t += step) {
	
		int lineages = 0;
		tree<Node>::iterator it, jt;
		for (it = nodetree.begin(); it != nodetree.end(); ++it) {
			jt = nodetree.parent(it);
			if ( (*it).getInclude() && nodetree.is_valid(jt) && (*it).getTime() >= t && (*jt).getTime() < t) {		
				lineages++;
			}
		}
		
		if (lineages > 0) {
			weight += ( ( lineages * (lineages - 1) ) / 2 ) * step;
		}
		
	}	
		
	return weight;

}

/* returns the opportunity for coalescence over the whole tree */
/* running this will padTree() may be faster and more accurate */
double CoalescentTree::getCoalWeightTrunk() {

	// setting step to be 1/1000 of the total length of the tree
	double start = getRootTime();
	double stop = getPresentTime();
	double step = (stop - start) / (double) 1000;
	
	// step through tree counting concurrent lineages
	double weight = 0.0;
	for (double t = start; t <= stop; t += step) {
	
		int lineages = 0;
		tree<Node>::iterator it, jt;
		for (it = nodetree.begin(); it != nodetree.end(); ++it) {
			jt = nodetree.parent(it);
			if ( (*it).getInclude() && nodetree.is_valid(jt) && (*it).getTime() >= t && (*jt).getTime() < t) {		
				lineages++;
			}
		}
		
		if (lineages > 0) {
			weight += lineages * step;
		}
		
	}	
		
	return weight;

}

/* returns the opportunity for coalescence for label */
double CoalescentTree::getCoalWeight(string l) {

	// setting step to be 1/1000 of the total length of the tree
	double start = getRootTime();
	double stop = getPresentTime();
	double step = (stop - start) / (double) 1000;
		
	// step through tree counting concurrent lineages
	double weight = 0.0;
	for (double t = start; t <= stop; t += step) {
	
		int lineages = 0;
		tree<Node>::iterator it, jt;
		for (it = nodetree.begin(); it != nodetree.end(); ++it) {
			jt = nodetree.parent(it);
			if ( (*it).getInclude() && nodetree.is_valid(jt) && (*it).getTime() >= t && (*jt).getTime() < t && (*it).getLabel() == l ) {		
				lineages++;
			}
		}
				
		if (lineages > 0) {
			weight += ( ( lineages * (lineages - 1) ) / 2 ) * step;
		}
		
	}	
	
	return weight;

}

double CoalescentTree::getCoalRate() {
	return getCoalCount() / getCoalWeight();
}

double CoalescentTree::getCoalRate(string l) {
	return getCoalCount(l) / getCoalWeight(l);
}

/* returns the count of migration events over entire tree */
int CoalescentTree::getMigCount() {

	/* count migration events, these are nodes in which the parent label differs from child label */
	tree<Node>::iterator it, jt;
	int count = 0;
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {		
			if ( (*it).getInclude() && (*jt).getInclude() && (*it).getLabel() != (*jt).getLabel() ) {		
				count++;
			}
		}
	}
	return count;

}

/* returns the count of migration events from label to label */
int CoalescentTree::getMigCount(string from, string to) {

	/* count migration events, these are nodes in which the parent label differs from child label */
	tree<Node>::iterator it, jt;
	int count = 0;
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {
			if ( (*it).getInclude() && (*jt).getInclude() && (*it).getLabel() == to && (*jt).getLabel() == from ) {		
				count++;
			}
		}
	}
	return count;

}

/* returns the overall rate of migration */
double CoalescentTree::getMigRate() {
	return getMigCount() / getLength();
}

/* returns the rate of migration from label to label */
/* this is important to check on */
/* currently, this is set up as calculating the rate from working backwards in time */
/* i.e. the migration rate from 1->2 is measured from the count going backwards on 2->1 divided */
/* by the backward opportunity of 2 */
/* getMigCount(from,to) / getLength(to) */
/* this needs attention */
/* seems to match with empirical estimates with getMigCount(from,to) / getLength() */
/* seems wrong however */
double CoalescentTree::getMigRate(string from, string to) {
	return getMigCount(from,to) / getLength(to);
}

/* return average time from a tip to a node with different label */
double CoalescentTree::getPersistence() {
	
	double persist = 0.0;
	double total = 0.0;
	tree<Node>::leaf_iterator it;	
	tree<Node>::iterator jt;
	
	// walk back from each tip in the tree
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		bool compare = false;	
		double tipTime;
		double ancTime;
		jt = nodetree.parent(it);
		while ( nodetree.is_valid(jt) ) {
			if ( (*it).getLabel() != (*jt).getLabel() ) {
				compare = true;
				tipTime = (*it).getTime();
				ancTime = (*jt).getTime();
				break;
			}
			jt = nodetree.parent(jt);
		}
		if (compare == true) {
			persist += (tipTime - ancTime);
			total += 1.0;
		}
	}
	
	persist /= total;
	return persist;
	
}

/* return average time from a tip with particular label to a node with different label */
double CoalescentTree::getPersistence(string l) {
	
	double persist = 0.0;
	double total = 0.0;
	tree<Node>::leaf_iterator it;	
	tree<Node>::iterator jt;
	
	// walk back from each tip in the tree
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		if ( (*it).getLabel() == l ) {
			bool compare = false;	
			double tipTime;
			double ancTime;
			jt = nodetree.parent(it);
			while ( nodetree.is_valid(jt) ) {
				if ( (*it).getLabel() != (*jt).getLabel() ) {
					compare = true;
					tipTime = (*it).getTime();
					ancTime = (*jt).getTime();
					break;
				}
				jt = nodetree.parent(jt);
			}
			if (compare == true) {
				persist += (tipTime - ancTime);
				total += 1.0;
			}
		}
	}
	
	persist /= total;
	return persist;
	
}

/* return distance from tip A to tip B */
double CoalescentTree::getDiversity(string tipA, string tipB) {

	double div = 0.0;
	tree<Node>::leaf_iterator it, jt, kt;	

	/* find tipA */
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		if ( (*it).getName() == tipA ) {
			break;
		}
	}
	
	/* find tipB */
	for (jt = nodetree.begin_leaf(); jt != nodetree.end_leaf(); ++jt) {
		if ( (*jt).getName() == tipB ) {
			break;
		}
	}	

	/* find common ancestor and calculate time from it to jt via common ancestor */
	kt = commonAncestor(it,jt);
	div = ( (*it).getTime() - (*kt).getTime() ) + ( (*jt).getTime() - (*kt).getTime() );

	return div;	
}

/* return mean of (2 * time to common ancestor) for every pair of leaf nodes */
double CoalescentTree::getDiversity() {

	double div = 0.0;
	int count = 0;

	/* iterating over every pair of leaf nodes */
	tree<Node>::leaf_iterator it, jt, kt;
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		for (jt = it; jt != nodetree.end_leaf(); ++jt) {
			if ((*it).getInclude() && (*jt).getInclude() && it != jt) {
	
				/* find common ancestor and calculate time from it to jt via common ancestor */
				kt = commonAncestor(it,jt);
				div += ( (*it).getTime() - (*kt).getTime() ) + ( (*jt).getTime() - (*kt).getTime() );
				count++;
			
			}
		}
	}
	
	div /= (double) count;
	return div;
	
}

/* return mean of (2 * time to common ancestor) for pairs of leaf nodes with labels a and b */
double CoalescentTree::getDiversity(string l) {

	double div = 0.0;
	int count = 0;

	/* iterating over every pair of leaf nodes */
	tree<Node>::leaf_iterator it, jt, kt;
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		for (jt = it; jt != nodetree.end_leaf(); ++jt) {
			if ((*it).getInclude() && (*jt).getInclude() && it != jt && (*it).getLabel() == l && (*jt).getLabel() == l ) {
	
				/* find common ancestor and calculate time from it to jt via common ancestor */
				kt = commonAncestor(it,jt);
				div += ( (*it).getTime() - (*kt).getTime() ) + ( (*jt).getTime() - (*kt).getTime() );
				count++;
			
			}
		}
	}
	
	div /= (double) count;
	return div;
	
}

/* return mean of (2 * time to common ancestor) for pairs of leaf nodes with identical labels */
double CoalescentTree::getDiversityWithin() {

	double div = 0.0;
	int count = 0;

	/* iterating over every pair of leaf nodes */
	tree<Node>::leaf_iterator it, jt, kt;
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		for (jt = it; jt != nodetree.end_leaf(); ++jt) {
			if ((*it).getInclude() && (*jt).getInclude() && it != jt && (*it).getLabel() == (*jt).getLabel() ) {
	
				/* find common ancestor and calculate time from it to jt via common ancestor */
				kt = commonAncestor(it,jt);
				div += ( (*it).getTime() - (*kt).getTime() ) + ( (*jt).getTime() - (*kt).getTime() );
				count++;
			
			}
		}
	}
	
	div /= (double) count;
	return div;
	
}

/* return mean of (2 * time to common ancestor) for pairs of leaf nodes with different labels */
double CoalescentTree::getDiversityBetween() {

	double div = 0.0;
	int count = 0;

	/* iterating over every pair of leaf nodes */
	tree<Node>::leaf_iterator it, jt, kt;
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		for (jt = it; jt != nodetree.end_leaf(); ++jt) {
			if ((*it).getInclude() && (*jt).getInclude() && it != jt && (*it).getLabel() != (*jt).getLabel() ) {
	
				/* find common ancestor and calculate time from it to jt via common ancestor */
				kt = commonAncestor(it,jt);
				div += ( (*it).getTime() - (*kt).getTime() ) + ( (*jt).getTime() - (*kt).getTime() );
				count++;
			
			}
		}
	}
	
	div /= (double) count;
	return div;
	
}

/* returns population subdivision Fst = (divBetween - divWithin) / divBetween */
double CoalescentTree::getFst() {

	double divWithin = getDiversityWithin();
	double divBetween = getDiversityBetween();
	double fst = (divBetween - divWithin) / divBetween;
	return fst;

}

/* return D = pi - S/a1, where pi is diversity, S is the total tree length, and a1 is a normalization factor */
/* expect D = 0 under neutrality */
double CoalescentTree::getTajimaD() {

	double div = getDiversity();
	double S = getLength();
	
	double a1 = 0.0;
	double a2 = 0.0;	
	int n = getLeafCount();
	for (int i = 1; i < n; i++) {
		a1 += 1 / (double) i;
		a2 += 1 / (double) (i*i);		
	}
				
	double e1 = (1.0/a1) * ((double)(n+1) / (3*(n-1)) - (1.0/a1));	
	double e2 = (1.0 / (a1*a1 + a2) ) * ( (double)(2*(n*n+n+3)) / (9*n*(n-1)) - (double)(n+2) / (n*a1) + a2/(a1*a1) );
	double denom = sqrt(e1*S + e2*S*(S-1));
	double tajima = (div - S/a1) / denom;	
	
	return tajima;

}

/* returns the coefficient of diffusion across the tree */
double CoalescentTree::getDiffusionCoefficient() {

	/* compare Euclidean distance between parent and child nodes */
	tree<Node>::iterator it, jt;
	double coefficient = 0;	
	double count = 0;
	double totalSqDist = 0;
	double totalTime = 0;		
		
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {	
		
			double diffX = (*it).getX() - (*jt).getX();
			double diffY = (*it).getY() - (*jt).getY();
			double sqDistX = diffX * diffX;
			double sqDistY = diffY * diffY;			
			double sqDist = sqDistX + sqDistY;
			double time = (*it).getTime() - (*jt).getTime();
			
			// first estimate drift coefficient
			double mu = diffX / time;
			
			// then estimate diffusion coefficient			
			coefficient += sqDist / (4.0*time);
//			coefficient += ( sqDist - mu*mu*time*time ) / (time);
				
			totalSqDist += sqDist;
			totalTime += time;					
			count += 1;
	
		}
	}
	
	coefficient /= count;
	coefficient = totalSqDist / (4.0*totalTime);	
	return coefficient;

}

/* returns the coefficient of diffusion across the trunk */
double CoalescentTree::getDiffusionCoefficientTrunk() {

	/* compare Euclidean distance between parent and child nodes */
	tree<Node>::iterator it, jt;
	double coefficient = 0;	
	double count = 0;
	double totalSqDist = 0;
	double totalTime = 0;	
		
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {	
			if ( (*it).getTrunk() && (*jt).getTrunk() ) {
		
				double diffX = (*it).getX() - (*jt).getX();
				double diffY = (*it).getY() - (*jt).getY();
				double sqDistX = diffX * diffX;
				double sqDistY = diffY * diffY;			
				double sqDist = sqDistX + sqDistY;
				double time = (*it).getTime() - (*jt).getTime();
				
				// first estimate drift coefficient
				double mu = diffX / time;
				
				// then estimate diffusion coefficient			
				coefficient += sqDist / (4.0*time);
//				coefficient += ( sqDist - mu*mu*time*time ) / (time);
					
				totalSqDist += sqDist;
				totalTime += time;					
				count += 1;
	
			}
		}
	}
	
	coefficient /= count;
	coefficient = totalSqDist / (4.0*totalTime);	
	return coefficient;

}

/* returns the coefficient of diffusion across side branches */
double CoalescentTree::getDiffusionCoefficientSideBranches() {

	/* compare Euclidean distance between parent and child nodes */
	tree<Node>::iterator it, jt;
	double coefficient = 0;	
	double count = 0;
	double totalSqDist = 0;
	double totalTime = 0;		
		
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {	
			if ( !(*it).getTrunk() && !(*jt).getTrunk() ) {
		
				double diffX = (*it).getX() - (*jt).getX();
				double diffY = (*it).getY() - (*jt).getY();
				double sqDistX = diffX * diffX;
				double sqDistY = diffY * diffY;			
				double sqDist = sqDistX + sqDistY;
				double time = (*it).getTime() - (*jt).getTime();
				
				// first estimate drift coefficient
				double mu = diffX / time;
				
				// then estimate diffusion coefficient			
				coefficient += sqDist / (4.0*time);
//				coefficient += ( sqDist - mu*mu*time*time ) / (time);
					
				totalSqDist += sqDist;
				totalTime += time;					
				count += 1;
	
			}
		}
	}
	
	coefficient /= count;
	coefficient = totalSqDist / (4.0*totalTime);
	return coefficient;

}

/* returns the coefficient of diffusion across side branches */
double CoalescentTree::getDiffusionCoefficientInternalBranches() {

	/* compare Euclidean distance between parent and child nodes */
	tree<Node>::iterator it, jt;
	double coefficient = 0;	
	double count = 0;
	double totalSqDist = 0;
	double totalTime = 0;		
		
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {	
			if ( !(*it).getLeaf() && !(*it).getTrunk() && !(*jt).getTrunk() ) {
		
				double diffX = (*it).getX() - (*jt).getX();
				double diffY = (*it).getY() - (*jt).getY();
				double sqDistX = diffX * diffX;
				double sqDistY = diffY * diffY;			
				double sqDist = sqDistX + sqDistY;
				double time = (*it).getTime() - (*jt).getTime();
				
				// first estimate drift coefficient
				double mu = diffX / time;
				
				// then estimate diffusion coefficient			
				coefficient += sqDist / (4.0*time);
	//			coefficient += ( sqDist - mu*mu*time*time ) / (time);
					
				totalSqDist += sqDist;
				totalTime += time;					
				count += 1;
	
			}
		}
	}
	
	coefficient /= count;	
	coefficient = totalSqDist / (4.0*totalTime);	
	return coefficient;

}

/* returns the rate of drift of x location across the tree */
double CoalescentTree::getDriftRate() {

	/* compare Euclidean distance between parent and child nodes */
	tree<Node>::iterator it, jt;
	double rate = 0;	
	double count = 0;
	double totalDist = 0;
	double totalTime = 0;		
		
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {	
		
			double dist = (*it).getX() - (*jt).getX();			
			double time = (*it).getTime() - (*jt).getTime();
					
			rate += dist / time;
			count += 1;
			totalDist += dist;
			totalTime += time;
	
		}
	}
	
	rate /= count;
	rate = totalDist / totalTime;
	return rate;

}

/* returns the rate of drift of x location across the tree */
double CoalescentTree::getDriftRateTrunk() {

	/* compare Euclidean distance between parent and child nodes */
	tree<Node>::iterator it, jt;
	double rate = 0;	
	double count = 0;
	double totalDist = 0;
	double totalTime = 0;		
		
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {	
			if ( (*it).getTrunk() && (*jt).getTrunk() ) {
		
				double dist = (*it).getX() - (*jt).getX();			
				double time = (*it).getTime() - (*jt).getTime();
								
				rate += dist / time;
				count += 1;
				totalDist += dist;
				totalTime += time;				
	
			}
		}
	}
	
	rate /= count;
	rate = totalDist / totalTime;	
	return rate;

}

/* returns the rate of drift of x location across the tree */
double CoalescentTree::getDriftRateSideBranches() {

	/* compare Euclidean distance between parent and child nodes */
	tree<Node>::iterator it, jt;
	double rate = 0;	
	double count = 0;
	double totalDist = 0;
	double totalTime = 0;		
	
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {	
			if ( !(*it).getTrunk() && !(*jt).getTrunk() ) {
		
				double dist = (*it).getX() - (*jt).getX();			
				double time = (*it).getTime() - (*jt).getTime();
								
				rate += dist / time;
				count += 1;
				totalDist += dist;
				totalTime += time;					
	
			}
		}
	}
	
	rate /= count;	
	rate = totalDist / totalTime;	
	return rate;

}

/* returns the rate of drift of x location across the tree */
double CoalescentTree::getDriftRateInternalBranches() {

	/* compare Euclidean distance between parent and child nodes */
	tree<Node>::iterator it, jt;
	double rate = 0;	
	double count = 0;
	double totalDist = 0;
	double totalTime = 0;		
		
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {	
			if ( !(*it).getLeaf() && !(*it).getTrunk() && !(*jt).getTrunk() ) {
		
				double dist = (*it).getX() - (*jt).getX();			
				double time = (*it).getTime() - (*jt).getTime();
									
				rate += dist / time;
				count += 1;
				totalDist += dist;
				totalTime += time;					
	
			}
		}
	}
	
	rate /= count;		
	rate = totalDist / totalTime;	
	return rate;

}

/* walk back from a particular tip a particular amount of time and return child node whose parent spans this amount of time */
tree<Node>::iterator CoalescentTree::getNodeBackFromTip (tree<Node>::iterator it, double timeWindow) {

	double initialTime = (*it).getTime();
	double finalTime = initialTime - timeWindow;	// timeWindow gives desired time
				
	// walk back through tree and return the first node whose parent has a time earlier than this time
	tree<Node>::iterator jt = nodetree.parent(it);
	while ( (*jt).getTime() > finalTime ) {
		it = jt;
		jt = nodetree.parent(it);
		if (!nodetree.is_valid(jt)) {		// if we cannot reach a node with this criteria, return last child possible
			break;
		}
	}

	return it;

}

/* walk back from a particular tip, t amount of time and retrieve x location, interpolate as necessary */
double CoalescentTree::getXBackFromTip (tree<Node>::iterator it, double timeWindow) {

	double initialTime = (*it).getTime();
	double finalTime = initialTime - timeWindow;	// timeWindow gives desired time
		
	it = getNodeBackFromTip(it, timeWindow);
	tree<Node>::iterator jt = nodetree.parent(it);
	
	double xValue = 0;
		
	if (nodetree.is_valid(jt)) {
	
		double childTime = (*it).getTime();
		double parentTime = (*jt).getTime();		
		double childX = (*it).getX();
		double parentX = (*jt).getX();		
		double xRate = (childX - parentX) / (childTime - parentTime);
		
		double remainder = (finalTime - parentTime);
		xValue = parentX + remainder * xRate;
	
	}
		
	return xValue;

}

/* walk back from a particular tip, t amount of time and retrieve x location, interpolate as necessary */
double CoalescentTree::getYBackFromTip (tree<Node>::iterator it, double timeWindow) {

	double initialTime = (*it).getTime();
	double finalTime = initialTime - timeWindow;	// timeWindow gives desired time
	
	it = getNodeBackFromTip(it, timeWindow);
	tree<Node>::iterator jt = nodetree.parent(it);
	
	double yValue = 0;
		
	if (nodetree.is_valid(jt)) {
	
		double childTime = (*it).getTime();
		double parentTime = (*jt).getTime();		
		double childY = (*it).getY();
		double parentY = (*jt).getY();		
		double yRate = (childY - parentY) / (childTime - parentTime);
		
		double remainder = (finalTime - parentTime);
		yValue = parentY + remainder * yRate;
	
	}
	
	return yValue;

}

/* returns the rate of 1D drift of x location measured at a distance of offset from each tip */
double CoalescentTree::get1DRateFromTips(double offset, double window) {

	/* compare Euclidean distance between parent and child nodes */
	double rate = 0;	
	double count = 0;
	
	/* walk through every tip in the tree and step back to appropriate point */	
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( (*it).getLeaf() ) {
		
			double startX = getXBackFromTip(it, offset);
			double endX = getXBackFromTip(it, offset + window);
			
			if (startX != 0 && endX != 0) {
		
				double dist = startX - endX;	
				rate += dist / window;
				count += 1;
			
			}
			
		}
	}
		
	rate /= count;
	return rate;

}

/* returns the rate of Euclidean drift of xy location measured at a distance of offset from each tip */
double CoalescentTree::get2DRateFromTips(double offset, double window) {

	/* compare Euclidean distance between parent and child nodes */
	double rate = 0;	
	double count = 0;
	
	/* walk through every tip in the tree and step back to appropriate point */	
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( (*it).getLeaf() ) {
		
			double startX = getXBackFromTip(it, offset);
			double startY = getYBackFromTip(it, offset);
			double endX = getXBackFromTip(it, offset + window);
			double endY = getYBackFromTip(it, offset + window);	
			
			if (startX != 0 && endX != 0 && startY != 0 && endY != 0) {
		
				double sqDistX = (startX - endX) * (startX - endX);
				double sqDistY = (startY - endY) * (startY - endY);
				double euclideanDist = sqrt(sqDistX + sqDistY);	
		
				if (euclideanDist > -0.00001) {
				
					rate += euclideanDist / window;
					count += 1;
				
				}
			
			}
			
		}
	}
		
	rate /= count;
	return rate;

}

/* return mean X location across all tips in the tree */
double CoalescentTree::getMeanX() {

	double xloc = 0.0;
	int count = 0;

	/* iterating over every leaf node */
	tree<Node>::leaf_iterator it;
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		xloc += (*it).getX();
		count++;
	}
	
	xloc /= (double) count;
	return xloc;
	
}

/* return mean Y location across all tips in the tree */
double CoalescentTree::getMeanY() {

	double yloc = 0.0;
	int count = 0;

	/* iterating over every leaf node */
	tree<Node>::leaf_iterator it;
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		yloc += (*it).getY();
		count++;
	}
	
	yloc /= (double) count;
	return yloc;
	
}

/* return mean rate across all tips in the tree */
double CoalescentTree::getMeanRate() {

	double rate = 0.0;
	int count = 0;

	/* iterating over every leaf node */
	tree<Node>::leaf_iterator it;
	for (it = nodetree.begin_leaf(); it != nodetree.end_leaf(); ++it) {
		rate += (*it).getRate();
		count++;
	}
	
	rate /= (double) count;
	return rate;
	
}

vector<double> CoalescentTree::getTipsX() {

	vector<double> tiplocs;
	for (tree<Node>::leaf_iterator lit = nodetree.begin_leaf(); lit != nodetree.end_leaf(); ++lit) {
		double x = (*lit).getX();
		tiplocs.push_back(x);
	}
	return tiplocs;

}

vector<double> CoalescentTree::getTipsY() {

	vector<double> tiplocs;
	for (tree<Node>::leaf_iterator lit = nodetree.begin_leaf(); lit != nodetree.end_leaf(); ++lit) {
		double y = (*lit).getY();
		tiplocs.push_back(y);
	}
	return tiplocs;

}

void CoalescentTree::assignLocation() {

	tree<Node>::iterator it;
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		string loc = (*it).getLabel();
//		japan_korea, europe, southeast_asia, south_america, north_america, south_china, north_china, australasia, south_asia, africa, russia		
//		if (loc == "africa" || loc == "australasia" || loc == "europe" || loc == "japan_korea" || loc == "north_america" || loc == "russia" || loc == "south_america" ) {
		if (loc == "japan_korea") {
			(*it).setY(1.0);
		}
		else {
			(*it).setY(0.0);
		}
	}

}

/* returns vector of tip names */
vector<string> CoalescentTree::getTipNames() {

	vector<string> names;
	for (tree<Node>::leaf_iterator lit = nodetree.begin_leaf(); lit != nodetree.end_leaf(); ++lit) {
		names.push_back( (*lit).getName() );
	}
	return names;

}

double CoalescentTree::getTime(string name) {
	tree<Node>::iterator it = findNode(name);	
	return (*it).getTime();
}

string CoalescentTree::getLabel(string name) {
	tree<Node>::iterator it = findNode(name);	
	return (*it).getLabel();
}

/* time it takes for a named tip to coalesce with the trunk */
double CoalescentTree::timeToTrunk(string name) {

	tree<Node>::iterator it, jt;
	it = findNode(name);
	jt = it;
	
	/* walk back from this node until trunk is reached */
	while ( !(*jt).getTrunk() ) {
		jt = nodetree.parent(jt);
	}
	
	return (*it).getTime() - (*jt).getTime();	

}

/* removes extraneous nodes from tree */
void CoalescentTree::reduce() {

	tree<Node>::iterator it, jt, kt;

	/* removing pointless nodes, ie nodes that have no coalecent
	events or migration events associated with them */
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if (nodetree.is_valid(jt)) {
			if (nodetree.number_of_children(it) == 1) {								// no coalescence	
				kt = nodetree.child(it,0);
				if ((*kt).getLabel() == (*it).getLabel()) { 						// mo migration
	//				cout << "it = " << *it << ", kt = " << *kt << endl;
					(*kt).setLength( (*kt).getLength() + (*it).getLength() );	
					nodetree.reparent(jt,it);										// push child node up to be sibling of node
					nodetree.erase(it);												// erase node									
					it = nodetree.begin();
				}
			}
		}
	}

}

/* peels back trunk. works from root forward, stopping when first split is reached */
void CoalescentTree::peelBack() {

	tree<Node>::iterator it, jt, kt;

	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		jt = nodetree.parent(it);
		if ( nodetree.is_valid(jt) && nodetree.number_of_children(it) == 1) {	
			kt = nodetree.child(it,0);
			(*kt).setLength( (*kt).getLength() + (*it).getLength() );	
			nodetree.reparent(jt,it);								// push child node up to be sibling of node
			nodetree.erase(it);										// erase node									
			it = nodetree.begin();
		}
		if (nodetree.number_of_children(it) == 2) {
			break;
		}
	}

	// adjust root    
	it = nodetree.begin();
	if (nodetree.number_of_children(it) == 1) {
		nodetree.move_after(nodetree.begin(),++nodetree.begin());
		nodetree.erase(nodetree.begin());
		(*nodetree.begin()).setLength(0.0);
	}
	
}
	
void CoalescentTree::adjustCoords() {

	tree<Node>::iterator it, jt;

	/* reorder tree so that the bottom node of two sister nodes always has the most recent child more children */
	/* this combined with preorder traversal will insure the trunk follows a rough diagonal */
	it = nodetree.begin();
	while(it != nodetree.end()) {
		jt = nodetree.next_sibling(it);
		if (nodetree.is_valid(jt)) {
			int cit = nodetree.size(it);
			int cjt = nodetree.size(jt);
			if (cit > cjt) {
				nodetree.swap(jt,it);
				it = nodetree.begin();
			}
		}
		++it;
	}

	/* set coords of tips according to preorder traversal */
	/* set x coords to match time */
  	int count = 0;
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ( (*it).getLeaf() ) {
			(*it).setYCoord(count);	
			count++;
		}
		double t = (*it).getTime();
		(*it).setXCoord(t);
	}
	
	/* revise coords of internal nodes according to postorder traversal */
  	tree<Node>::post_order_iterator post_it, post_jt, post_kt;
  	for (post_it = nodetree.begin_post(); post_it != nodetree.end_post(); post_it++) {
  		int childcount = nodetree.number_of_children(post_it);
  		if (childcount == 1) {
  			post_jt = nodetree.child(post_it,0);
  			(*post_it).setYCoord((*post_jt).getYCoord());	
  		}  		  	
  		// ancestor is mean of children
  		if (childcount > 1) {
  			double avg = 0.0;
  			for (int i = 0; i < childcount; i++) {
  				post_jt = nodetree.child(post_it,i);
  				avg += (*post_jt).getYCoord();
  			}
  			avg /= (double) childcount;
  			(*post_it).setYCoord(avg);
  		}
	}	

}	

// go through tree and perform equal-angle algorithm to adjust ciruclar coordinates
void CoalescentTree::adjustCircularCoords() {

	tree<Node>::iterator it, jt;	

	// start at root, it has coordinate {0,0}
	it = nodetree.begin();
	(*it).setXCoord(0);
	(*it).setYCoord(0);	
	
	int numberOfTips = 0; 
	for (tree<Node>::leaf_iterator lit = nodetree.begin_leaf(); lit != nodetree.end_leaf(); ++lit) {
		numberOfTips++;
	}
	double angleForEachTip = 6.28318531 / numberOfTips;
			
	while(it != nodetree.end()) {
		jt = nodetree.next_sibling(it);
		if (nodetree.is_valid(jt)) {		// it left sibling and jt is right sibling
		
			double basis = 0;
			double parentX = 0;
			double parentY = 0;			
			tree<Node>::iterator pt = nodetree.parent(it);
			tree<Node>::iterator ppt = nodetree.parent(pt);
			if (nodetree.is_valid(pt)) { 	
				parentX = (*pt).getXCoord();	
				parentY = (*pt).getYCoord();					
			}
			if (nodetree.is_valid(pt) && nodetree.is_valid(ppt)) { 
				double deltaX = (*pt).getXCoord() - (*ppt).getXCoord();
				double deltaY = (*pt).getYCoord() - (*ppt).getYCoord();
				if (deltaX != 0) {
					basis = atan2(deltaY,deltaX);
				}
			}
		
			double leftSector = angleForEachTip * (double) countDescendants(it);
			double rightSector = angleForEachTip * (double) countDescendants(jt);			
			double totalSector = leftSector + rightSector;
			double leftAngle = basis + 0.5*totalSector - 0.5*leftSector; 
			double rightAngle = basis - 0.5*totalSector + 0.5*rightSector; 			
			double leftX = parentX + (*it).getLength() * cos(leftAngle);
			double leftY = parentY + (*it).getLength() * sin(leftAngle);	
			double rightX = parentX + (*jt).getLength() * cos(rightAngle);
			double rightY = parentY + (*jt).getLength() * sin(rightAngle);
					
			(*it).setXCoord(leftX);
			(*it).setYCoord(leftY);
			(*jt).setXCoord(rightX);
			(*jt).setYCoord(rightY);			
			
		}
		// else, it is right sibling, do nothing						
		++it;
	}


}

// count tip descendended from a node
int CoalescentTree::countDescendants(tree<Node>::iterator top) {
	int descendants = 0;
   	tree<Node>::pre_order_iterator it=top, eit=top;
   	eit.skip_children();
   	++eit;
   	while (it!=eit) {
   		if ((*it).getLeaf()) {
      		++descendants;
      	}
      	++it;
    }
	return descendants;
}

/* Setting tip coordinates based on input vector of tip names */
void CoalescentTree::setCoords(vector<string> tipOrdering) {

	tree<Node>::iterator it, jt;

	/* set coords of tips according to supplied vector of names */
  	for (int i = 0; i < tipOrdering.size(); i++) {
  		it = findNode(tipOrdering[i]);
  		(*it).setYCoord(i);
  	}
  		
	/* revise coords of internal nodes according to postorder traversal */
  	tree<Node>::post_order_iterator post_it, post_jt, post_kt;
  	for (post_it = nodetree.begin_post(); post_it != nodetree.end_post(); post_it++) {
  		if (nodetree.number_of_children(post_it) == 1) {
  			post_jt = nodetree.child(post_it,0);
  			(*post_it).setYCoord((*post_jt).getYCoord());	
  		}  		  	
  		if (nodetree.number_of_children(post_it) == 2) {
  			post_jt = nodetree.child(post_it,0);
  			post_kt = nodetree.child(post_it,1);
  			double avg = ( (*post_jt).getYCoord() + (*post_kt).getYCoord() ) / (double) 2;
  			(*post_it).setYCoord(avg);	
  		}
	}	

}	
	
/* returns maximium node associated with a node in the tree */
int CoalescentTree::getMaxNumber() {

	int n = 0;
	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getNumber() > n) {
			n = (*it).getNumber();
		}
	}
	return n;

}

/* renumber tree via preorder traversal starting from n */
int CoalescentTree::renumber(int n) {

	for (tree<Node>::iterator it = nodetree.begin(); it != nodetree.end(); ++it) {
		(*it).setNumber(n);
		n++;
	}
	return n;

}

/* given a number, returns iterator to associated node, or if not found, returns iterator to end of tree */
tree<Node>::iterator CoalescentTree::findNode(int n) {
	
	tree<Node>::iterator it;
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getNumber() == n)
			break;
	}
	return it;
	
}

/* given a name, returns iterator to associated node, or if not found, returns iterator to end of tree */
tree<Node>::iterator CoalescentTree::findNode(string name) {
	
	tree<Node>::iterator it;
	for (it = nodetree.begin(); it != nodetree.end(); ++it) {
		if ((*it).getName() == name)
			break;
	}
	return it;
	
}

/* given two iterators, returns an iterator to their most recent common ancestor */
tree<Node>::iterator CoalescentTree::commonAncestor(tree<Node>::iterator ia, tree<Node>::iterator ib) {

	/* make a set */
	set<int> nodeSet;
	
	/* walk down from first node to root, appending to nodeSet */
	tree<Node>::iterator it;
	it = ia;
	while (nodetree.is_valid(it)) {
		nodeSet.insert( (*it).getNumber() );
		it = nodetree.parent(it);
	}
	
	/* walk down from second node, stopping when a member of nodeSet is encountered */
	it = ib;	
	while (nodetree.is_valid(it)) {
		if (nodeSet.end() == nodeSet.find( (*it).getNumber() )) {
			it = nodetree.parent(it);
		}
		else {
			break;
		}
	}

//	cout << "a = " << (*ia).getNumber() << ", b = " << (*ib).getNumber() << ", anc = " << (*it).getNumber() << endl;
	
	return it;
	
}
back to top