def calculateProbableRootOfGeneTree(speciesTree, geneTree, processID=lambda x : x):
    """
    Goes through each root possible branch making it the root. 
    Returns tree that requires the minimum number of duplications.
    """
    #get all rooted trees
    #run dup calc on each tree
    #return tree with fewest number of dups
    if geneTree.traversalID.midEnd <= 3:
        return (0, 0, geneTree)
    checkGeneTreeMatchesSpeciesTree(speciesTree, geneTree, processID)
    l = []
    def fn(tree):
        if tree.traversalID.mid != geneTree.left.traversalID.mid and tree.traversalID.mid != geneTree.right.traversalID.mid:
            newGeneTree = moveRoot(geneTree, tree.traversalID.mid)
            binaryTree_depthFirstNumbers(newGeneTree)
            dupCount, lossCount = calculateDupsAndLossesByReconcilingTrees(speciesTree, newGeneTree, processID)
            l.append((dupCount, lossCount, newGeneTree))
        if tree.internal:
            fn(tree.left)
            fn(tree.right)
    fn(geneTree)
    l.sort()
    return l[0][2], l[0][0], l[0][1]
def calculateProbableRootOfGeneTree ( speciesTree , geneTree , processID = lambda x : x ) : if geneTree . traversalID . midEnd <= 3 : return ( 0 , 0 , geneTree ) checkGeneTreeMatchesSpeciesTree ( speciesTree , geneTree , processID ) l = [ ] def fn ( tree ) : if tree . traversalID . mid != geneTree . left . traversalID . mid and tree . traversalID . mid != geneTree . right . traversalID . mid : newGeneTree = moveRoot ( geneTree , tree . traversalID . mid ) binaryTree_depthFirstNumbers ( newGeneTree ) dupCount , lossCount = calculateDupsAndLossesByReconcilingTrees ( speciesTree , newGeneTree , processID ) l . append ( ( dupCount , lossCount , newGeneTree ) ) if tree . internal : fn ( tree . left ) fn ( tree . right ) fn ( geneTree ) l . sort ( ) return l [ 0 ] [ 2 ] , l [ 0 ] [ 0 ] , l [ 0 ] [ 1 ]
Goes through each root possible branch making it the root. 
    Returns tree that requires the minimum number of duplications.