//Source file: D:\\Projects\\src\\yi\\iu\\imgdb\\learn\\MultiIndepFtAdapter.java

package yi.iu.imgdb.learn;

import java.util.*;
import yi.util.config.*;
import yi.util.io.*;
import org.jmat.gui.*;
import yi.ds.hash.*;
import java.io.IOException;

/**
 * Using multiple features, but treat them as independent
 */
public abstract class MultiIndepFtAdapter extends StatModelAdapter 
{
  HashMap m_objGMMAdapters = new HashMap ();
  static HashMap m_subModelResults = new HashMap ();
  
  /**
   * @param data_center
   * @param img_list
   * @param ft_list
   * @param obj_list
   */
  public MultiIndepFtAdapter(ImgDataCenter data_center, java.util.LinkedList img_list, java.util.LinkedList ft_list, java.util.LinkedList obj_list) 
  {
    super(data_center, img_list, ft_list, obj_list);

    // construct ObjGMMAdapters each of which deals with one feature
    for (Iterator i=ft_list.iterator(); i.hasNext();) {

      Object feature = i.next();

      // create the feature list containing only one feature
      LinkedList one_ft_list = new LinkedList();
      one_ft_list.add(feature);

      // construct  ObjGMMAdapter wot deal with that feature
      System.out.println("construct GMM model on " + feature);
      StatModelAdapter gmm_adapter = createStatModelAdapter(data_center, img_list, one_ft_list, obj_list);

      m_objGMMAdapters.put(feature, gmm_adapter);
    }   
  }
  
  /**
   * @param file
   * @throws java.io.IOException
   */
  public void writeToFile(String file) throws java.io.IOException 
  {
    super.writeToFile(file);
    for (Iterator i=m_subModelResults.keySet().iterator(); i.hasNext();) {
      String ft = i.next().toString();
      String ft_str = yi.util.data.StringUtil.getClassShortName(ft);
      StatTestRst rst = (StatTestRst)m_subModelResults.get(ft);
      rst.writeToFile(file + "." + ft_str);
    }   
  }
  
  /**
   * Create the StatModelAdapter combined under "independent" assumption.  Child
   * class may override this method to get "independent" actions.
   * @param data_center
   * @param img_list
   * @param ft_list
   * @param obj_list
   * @return
   */
  protected StatModelAdapter createStatModelAdapter(ImgDataCenter data_center, java.util.LinkedList img_list, java.util.LinkedList ft_list, java.util.LinkedList obj_list) 
  {
    return new ObjGMMAdapter(data_center, img_list, ft_list, obj_list);   
  }
  
  /**
   * Get the test results from each ObjGMMAdapter, then combine them
   * @param imgs
   * @return StatTestRst
   */
  public StatTestRst test(java.util.LinkedList imgs) 
  {

    // get the score for each ObjGMMAdapter
    StatTestRst[] ft_rsts = new StatTestRst[m_featureList.size()];
    int i_index = 0;
    for (Iterator i=m_featureList.iterator(); i.hasNext(); i_index++) {
      Object feature = i.next();
      StatModelAdapter gmm_adapter = (StatModelAdapter)m_objGMMAdapters.get(feature);
      ft_rsts[i_index] = gmm_adapter.test(imgs);
//      /** @todo output scores for compare */
//      try {
//        ft_rsts[i_index].writeToFile("combined" + i_index + ".rst");
//      }catch (Exception e) {
//        e.printStackTrace();
//      }

      // save the results for different folds
      if (!m_subModelResults.containsKey(feature)) {
        m_subModelResults.put(feature, new StatTestRst());
      }
      StatTestRst hist_rst = (StatTestRst)m_subModelResults.get(feature);
//      System.out.println("feature:" + feature);
//      System.out.println("objects already there: " + hist_rst.size());
//      for (Iterator j=hist_rst.keySet().iterator(); j.hasNext(); ) {
//        Object obj = j.next();
//        System.out.println("  object: " + obj + " ,images = " + ((HashMap)hist_rst.get(obj)).size());
//      }
      hist_rst.putAllInDeep(ft_rsts[i_index]);
//      System.out.println("after adding: " + hist_rst.size());
//      for (Iterator j=hist_rst.keySet().iterator(); j.hasNext(); ) {
//        Object obj = j.next();
//        System.out.println("  object: " + obj + " ,images = " + ((HashMap)hist_rst.get(obj)).size());
//      }
    }

    StatTestRst rst = new StatTestRst(); // save the combined result

    for (Iterator o = m_objectList.iterator(); o.hasNext(); ) {
      Object object = o.next();
      System.out.println(object);
      for (Iterator i=imgs.iterator(); i.hasNext(); ) {
        Object image = i.next();
        System.out.print(image);
        double score = 0;
        for (int j=0; j<ft_rsts.length; j++) {
          double s = ft_rsts[j].getScore(object, image);  // since the scores is after log already
          score += s;
          System.out.print(" " + s);
        }
        System.out.println(" = " + score);
        rst.putScore(object, image, score);
      }
    }

    try {
      rst.writeToFile("combined.rst");
    }
    catch (Exception e) {
      e.printStackTrace();
    }

    return rst;   
  }
  
  public static class Test 
  {
    public static final String USAGE = "Usage: [-d img_data_center_file] [-m model_file] [-i img_list_file] [-f feature] [-r rst_file_name]";
    
    /**
     * @param args
     */
    public static void main(String[] args) 
    {

      // init configuration
      Configuration.init(args);

      try {
        // read in an ObjGMMAdapter object
        String model_file = ReadArgu.getOption(
            'm', args,
            "model0.ser"
            );

        ObjGMMMultiFtAdapter gmm = (ObjGMMMultiFtAdapter)ObjGMMMultiFtAdapter.createFromFile(model_file);

        // init the datacenter
        String data_center_name = ReadArgu.getOption(
            'd', args,
            "groundtruth.ser"
            );

        ImgDataCenter data_center = ImgDataCenter.createFromFile(
            data_center_name);

        // get the image list file name
        String img_list_file = ReadArgu.getOption('i', args);

        // image list
        LinkedList img_list = null;
        if (img_list_file != null) {
          String[] images = yi.util.io.ReadArgu.readStrings(img_list_file);
          img_list = yi.util.data.Conversion.asLinkedList(images);
        }

        // System.out.println(gmm.m_models);

        StatTestRst rst = gmm.test(img_list);

        HashMap rpcs = rst.rpcAnalysis(data_center); // right positive curves

        DoubleScoreHashMap roc_scores = rst.getROCScores(rpcs);
        System.out.println("roc scores:");
        System.out.println(roc_scores.toStringBySkyOrder());

        Plot2DPanel pp = rst.drawROCs(rpcs);

        String rst_output_file = ReadArgu.getOption('r', args);
        if (rst_output_file != null) {
          pp.setFixedBounds(0,0,1);
          pp.setFixedBounds(1,0,1);
          pp.invalidate();
          pp.toGraphicFile(new java.io.File(rst_output_file + ".png"));
        }

        // print out the results from other features
        for (Iterator i=gmm.m_objGMMAdapters.keySet().iterator(); i.hasNext(); ) {
          String feature = (String)i.next();
          StatModelAdapter gmm_adapter = (StatModelAdapter)gmm.m_objGMMAdapters.get(feature);
          rst = gmm_adapter.test(img_list);

          rpcs = rst.rpcAnalysis(data_center); // right positive curves
          pp = rst.drawROCs(rpcs);

          if (rst_output_file != null) {
            pp.setFixedBounds(0, 0, 1);
            pp.setFixedBounds(1, 0, 1);
            pp.invalidate();

            String ft = yi.util.io.File.getShortName(feature);
            pp.toGraphicFile(new java.io.File(rst_output_file + "." + ft + ".png"));
          }
        }

      } catch (Exception e) {
        e.printStackTrace();
      }     
    }
  }
}
