package yi.ai.classifiers;

import java.util.*;
import org.jmat.data.*;
import org.jmat.io.*;
import org.jmat.gui.*;

/**
 * Classification performance characterized by precision and recall
 */

public class ClassificationPerformance implements java.io.Serializable{
  public double precision;
  public double recall;

  public ClassificationPerformance(double precision, double recall) {
    this.precision = precision;
    this.recall = recall;
  }

  /**
   * Return the histogram of (precision, recall).  One cell corresponds to
   * (1%, 1%)
   * @param ClassificationPerformance
   * @return
   */
  public static int[][] get2DHistogram(Collection performances) {
    int[][] hist = new int[101][101];
    for (Iterator i=performances.iterator(); i.hasNext();) {
      ClassificationPerformance perf = (ClassificationPerformance)i.next();
      int precision = (int)Math.round(perf.precision * 100);
      int recall = (int)Math.round(perf.recall * 100);
      hist[precision][recall]++;
    }
    return hist;
  }

  public static Matrix toHistogramMatrix(Collection performances) {

    // the histogram
    int[][] hist = get2DHistogram(performances);

    // find the non-empty bins
    LinkedList elements = new LinkedList();
    for (int i=0; i<hist.length; i++) {
      for (int j=0; j<hist[i].length; j++) {
        if (hist[i][j] != 0) {
          elements.add(new double[]{i,j,hist[i][j]});
        }
      }
    }

    // make a matrix
    double[][] list = new double[elements.size()][3];
    Iterator i=elements.iterator();
    for (int count = 0; i.hasNext(); count++) {
      double[] perf = (double[])i.next();
      list[count] = perf;
    }
    return new Matrix(list);
  }

  public String toString() {
    return "precision = " + precision + ", recall = " + recall;
  }

  public static void main(String[] args) {
    LinkedList performance = new LinkedList();
    performance.add(new ClassificationPerformance(0.5, 0.5));
    performance.add(new ClassificationPerformance(0.5, 0.5));
    performance.add(new ClassificationPerformance(0.5, 0.5));
    performance.add(new ClassificationPerformance(0.5, 0.5));
    performance.add(new ClassificationPerformance(0.5, 0.5));
    performance.add(new ClassificationPerformance(0.5, 0.5));
    performance.add(new ClassificationPerformance(0.5, 0.5));
    performance.add(new ClassificationPerformance(0.6, 0.5));
    performance.add(new ClassificationPerformance(0.6, 0.5));
    performance.add(new ClassificationPerformance(0.6, 0.6));
    performance.add(new ClassificationPerformance(0.6, 0.6));
    performance.add(new ClassificationPerformance(0.8, 0.8));
    Matrix matrix = ClassificationPerformance.toHistogramMatrix(performance);
    //matrix.toPlot3DFrame("performance", "precision vs recall", Plot3DPanel.BAR);
    Plot3DPanel pp = matrix.toPlot3DPanel("precision vs recall", "SCATTER");
    new FrameView("performance", pp);
  }

}