private double calculateEMProposal(Tree tree,NodeRef node,ColourChangeMatrix mm,MetaPopulation mp,TreeColouring colouring){
  double[] forward;
  int colour;
  BranchColouring history=null;
  double logLikelihood=0.0;
  if (tree.isRoot(node)) {
    forward=mm.getEquilibrium();
    colour=colouring.getNodeColour(node);
    logLikelihood+=Math.log(forward[colour]);
  }
 else {
    int nodeNum=node.getNumber();
    double[][] backward=nodePartialsEM[nodeNum];
    int bottomInterval=node2Interval[nodeNum];
    history=colouring.getBranchColouring(node);
    for (int relinterval=backward.length - 1; relinterval >= 0; relinterval--) {
      int interval=relinterval + bottomInterval;
      double childHeight=interval2Height[interval];
      double uppertime=interval2Height[interval + 1];
      double time=uppertime - childHeight;
      double[] mxElts=calculateMatrixElts(interval,node,tree,time,avgN0[interval],avgN1[interval],mm);
      logLikelihood+=calculateConditionalBranchColouringEM(node,time,childHeight,mxElts,history);
    }
    colour=colouring.getNodeColour(node);
  }
  if (!tree.isExternal(node) && useNodeBias) {
    double childTime=tree.getNodeHeight(node);
    logLikelihood+=Math.log(mm.getEquilibrium(colour) / mp.getDemographic(childTime - tinyTime,colour));
  }
  for (int i=0; i < tree.getChildCount(node); i++) {
    NodeRef child=tree.getChild(node,i);
    logLikelihood+=calculateEMProposal(tree,child,mm,mp,colouring);
  }
  return logLikelihood;
}

private double calculateEMProposal ( Tree tree , NodeRef node , ColourChangeMatrix mm , MetaPopulation mp , TreeColouring colouring ) { double [ ] forward ; int colour ; BranchColouring history = null ; double logLikelihood = 0.0 ; if ( tree . isRoot ( node ) ) { forward = mm . getEquilibrium ( ) ; colour = colouring . getNodeColour ( node ) ; logLikelihood += Math . log ( forward [ colour ] ) ; } else { int nodeNum = node . getNumber ( ) ; double [ ] [ ] backward = nodePartialsEM [ nodeNum ] ; int bottomInterval = node2Interval [ nodeNum ] ; history = colouring . getBranchColouring ( node ) ; for ( int relinterval = backward . length - 1 ; relinterval >= 0 ; relinterval -- ) { int interval = relinterval + bottomInterval ; double childHeight = interval2Height [ interval ] ; double uppertime = interval2Height [ interval + 1 ] ; double time = uppertime - childHeight ; double [ ] mxElts = calculateMatrixElts ( interval , node , tree , time , avgN0 [ interval ] , avgN1 [ interval ] , mm ) ; logLikelihood += calculateConditionalBranchColouringEM ( node , time , childHeight , mxElts , history ) ; } colour = colouring . getNodeColour ( node ) ; } if ( ! tree . isExternal ( node ) && useNodeBias ) { double childTime = tree . getNodeHeight ( node ) ; logLikelihood += Math . log ( mm . getEquilibrium ( colour ) / mp . getDemographic ( childTime - tinyTime , colour ) ) ; } for ( int i = 0 ; i < tree . getChildCount ( node ) ; i ++ ) { NodeRef child = tree . getChild ( node , i ) ; logLikelihood += calculateEMProposal ( tree , child , mm , mp , colouring ) ; } return logLikelihood ; }
calculates proposal density for given colouring requires the results from felsenstein backwards pruning , in nodepartials ( em ) [ ] ( see pruneem ( ) )
