/** calculates statstics and output for results on a given test sequence */
  public void calcResultIncrement(TrainingSequence training, int[] predictedHiddenSequence) {
    labeled.add(
        new TrainingSequence(
            training.getInputSequence(),
            predictedHiddenSequence)); // This is only place that labelled gets added to???
    // So I guess the results just get built up incrementally, both the actuall hidden sequences and
    // the stats?
    Assert.a(training.length() == predictedHiddenSequence.length);
    int[] actualHiddenSequence = new int[training.length()];
    for (int i = 0; i < training.length(); i++) {
      actualHiddenSequence[i] = training.getY(i);
    }
    boolean thisperfect = true;
    for (int i = 0; i < predictedHiddenSequence.length; ++i) {
      int predY = predictedHiddenSequence[i];
      int realY = actualHiddenSequence[i];

      if (realY == predY) {
        correct += 1;
      } else {
        incorrect += 1;
        thisperfect = false;
      }

      ctCodingNucleotide.increment(isCodingPlus(predY), isCodingPlus(realY));
      ctCodingNucleotide.increment(isCodingMinus(predY), isCodingMinus(realY));

      for (int s = 0; s < nStates; s++) {
        ctStates.get(s).increment((predY == s), (realY == s));
      }
    }
    if (thisperfect) {
      perfect++;
    } else {
      imperfect++;
    }
    for (int i = 1; i < predictedHiddenSequence.length; ++i) {
      int predY = predictedHiddenSequence[i];
      int realY = actualHiddenSequence[i];
      int predYp = predictedHiddenSequence[i - 1];
      int realYp = actualHiddenSequence[i - 1];

      for (int t = 0; t < nTransitions; t++) {
        boolean bPred = ((predYp == fromInd.get(t)) && (predY == toInd.get(t)));
        boolean bReal = ((realYp == fromInd.get(t)) && (realY == toInd.get(t)));
        ctTransitions.get(t).increment(bPred, bReal);
      }
    }

    // Now let's increment the contingency table for exons; note that here not counting TN's
    RangeMap predExonsPlus = new RangeMap();
    RangeMap predExonsMinus = new RangeMap();
    RangeMap realExonsPlus = new RangeMap();
    RangeMap realExonsMinus = new RangeMap();
    makeExonRangeMapFrom13SV(predictedHiddenSequence, predExonsPlus, predExonsMinus);
    makeExonRangeMapFrom13SV(actualHiddenSequence, realExonsPlus, realExonsMinus);
    incrementCTFromRangeMaps(ctExons, predExonsPlus, realExonsPlus);
    incrementCTFromRangeMaps(ctExons, predExonsMinus, realExonsMinus);
  }
  @Override
  public String toString() {
    String ret = "";

    for (int s = 0; s < nStates; s++) {
      ret += "[State=" + manager.getStateName(s) + "] ";
      ctStates.get(s).freeze();
      ret += "Predicted: " + ctStates.get(s).pp();
      ret += "\n";
    }

    for (int t = 0; t < nTransitions; t++) {
      ret +=
          "[Transition "
              + manager.getStateName(fromInd.get(t))
              + " --> "
              + manager.getStateName(toInd.get(t))
              + " ] ";
      ctTransitions.get(t).freeze();
      ret += "Predicted: " + ctTransitions.get(t).pp();
      ret += "\n";
    }

    ctCodingNucleotide.freeze();
    ret += "[Coding nucleotides] Predicted: " + ctCodingNucleotide.pp() + "\n";

    ctExons.freeze();
    ret += "[Coding exons] Predicted: " + ctExons.pp() + "\n";

    if (lla > 0) {
      ret += "LLA:" + lla + "  LLV:" + llv + "  " + "\n";
    }

    // ret += String.format("Perfectly predicted hidden sequences: %d/%d %.2f
    // %%",perfect,perfect+imperfect,perfect*100.0/(float) (perfect+imperfect))+ "\n";

    // ret += String.format("Nucleotide Hidden State Agreement: %d/%d %.2f %%",correct, correct +
    // incorrect, correct * 100.0 / (float) (correct + incorrect)) + "\n";

    return ret;
  }
 private void incrementCTFromRangeMaps(
     PredictedActualBinaryContingencyTable ct, RangeMap pred, RangeMap real) {
   // By looping through the predictions, can get at TP and FP
   Set<IntervalRangeMapValue> pv = pred.values();
   Iterator<IntervalRangeMapValue> pvi = pv.iterator();
   while (pvi.hasNext()) {
     IntervalRangeMapValue irmv = pvi.next();
     Set<IntervalRangeMapValue> vals = real.find(irmv.start, irmv.end);
     if (vals.size() == 0) {
       ct.incrementFP();
     } else {
       IntervalRangeMapValue val = vals.iterator().next();
       if (val.start == irmv.start && val.end == irmv.end) {
         ct.incrementTP();
       } else {
         ct.incrementFP();
       }
     }
   }
   Set<IntervalRangeMapValue> rv = real.values();
   Iterator<IntervalRangeMapValue> rvi = rv.iterator();
   while (rvi.hasNext()) {
     IntervalRangeMapValue irmv = rvi.next();
     if (!pred.hasEntry(irmv.start, irmv.end)) {
       ct.incrementFN();
     }
     Set<IntervalRangeMapValue> vals = pred.find(irmv.start, irmv.end);
     if (vals.size() == 0) {
       ct.incrementFN();
     } else {
       IntervalRangeMapValue val = vals.iterator().next();
       if (val.start == irmv.start && val.end == irmv.end) {
       } else {
         ct.incrementFN();
       }
     }
   }
 }