@Override
    public double calculate_E_step(_Doc d) {
      // Step 1: pre-compute emission probability
      if (m_collectCorpusStats) // indicates this is training
      ComputeEmissionProbsForDoc(d);

      // Step 2: use forword/backword algorithm to compute the posterior
      double logLikelihood = m_hmm.ForwardBackward(d, emission);

      // Step 3: collection expectations from the posterior distribution
      m_hmm.collectExpectations(p_dwzpsi); // expectations will be in the original space
      accTheta(d);
      estThetaInDoc(d); // get the posterior of theta

      if (m_collectCorpusStats) {
        accEpsilonStat(d);
        accSigmaStat(d);
        accPhiStat(d);
      }

      return logLikelihood + docThetaLikelihood(d);
    }
 int[] get_MAP_topic_assignment(_Doc d) {
   int path[] = new int[d.getSenetenceSize()];
   m_hmm.BackTrackBestPath(d, emission, path);
   return path;
 }