private double[] pruneEM(Tree tree,NodeRef node,ColourChangeMatrix mm,MetaPopulation mp){
  double[] p=new double[colourCount];
  if (tree.isExternal(node)) {
    p[getColour(node)]=1.0;
  }
 else {
    NodeRef leftChild=tree.getChild(node,0);
    NodeRef rightChild=tree.getChild(node,1);
    double[] left=pruneEM(tree,leftChild,mm,mp);
    double[] right=pruneEM(tree,rightChild,mm,mp);
    double[] leftBranchPartials=pruneBranchEM(mm,left,node,leftChild,tree,mp);
    double[] rightBranchPartials=pruneBranchEM(mm,right,node,rightChild,tree,mp);
    double maxp=0.0;
    for (int i=0; i < colourCount; i++) {
      p[i]=leftBranchPartials[i] * rightBranchPartials[i];
      if (useNodeBias) {
        p[i]*=mm.getEquilibrium(i) / mp.getDemographic(tree.getNodeHeight(node) - tinyTime,i);
      }
      if (p[i] > maxp) {
        maxp=p[i];
      }
    }
    if (maxp < 1.0e-100) {
      for (int i=0; i < colourCount; i++) {
        p[i]*=1.0e+100;
      }
      logNodePartialsRescaling-=Math.log(1.0e+100);
    }
  }
  nodePartials[node.getNumber()]=p;
  if (debugNodePartials) {
    prettyPrint("Node " + node.getNumber() + " pruneEM=",p);
  }
  return p;
}

private double [ ] pruneEM ( Tree tree , NodeRef node , ColourChangeMatrix mm , MetaPopulation mp ) { double [ ] p = new double [ colourCount ] ; if ( tree . isExternal ( node ) ) { p [ getColour ( node ) ] = 1.0 ; } else { NodeRef leftChild = tree . getChild ( node , 0 ) ; NodeRef rightChild = tree . getChild ( node , 1 ) ; double [ ] left = pruneEM ( tree , leftChild , mm , mp ) ; double [ ] right = pruneEM ( tree , rightChild , mm , mp ) ; double [ ] leftBranchPartials = pruneBranchEM ( mm , left , node , leftChild , tree , mp ) ; double [ ] rightBranchPartials = pruneBranchEM ( mm , right , node , rightChild , tree , mp ) ; double maxp = 0.0 ; for ( int i = 0 ; i < colourCount ; i ++ ) { p [ i ] = leftBranchPartials [ i ] * rightBranchPartials [ i ] ; if ( useNodeBias ) { p [ i ] *= mm . getEquilibrium ( i ) / mp . getDemographic ( tree . getNodeHeight ( node ) - tinyTime , i ) ; } if ( p [ i ] > maxp ) { maxp = p [ i ] ; } } if ( maxp < 1.0e-100 ) { for ( int i = 0 ; i < colourCount ; i ++ ) { p [ i ] *= 1.0e+100 ; } logNodePartialsRescaling -= Math . log ( 1.0e+100 ) ; } } nodePartials [ node . getNumber ( ) ] = p ; if ( debugNodePartials ) { prettyPrint ( "Node " + node . getNumber ( ) + " pruneEM=" , p ) ; } return p ; }
calculate probability of data at descendants from node , given a color at the node ( ' partials ' ) , by a felsenstein - like pruning algorithm . ( first step in the color sampling algorithm ) side effect : updates nodepartials [ ] and nodepartialsem [ ] [ ] for this node and all its descendants . this version uses mean - field coalescence correction and formal variable correction
