package yi.iu.imgdb.learn;

/**
 * Basically the same as GMMNNAdapter.  But the
 * p(Image, component) = max(p(region_i, component) * weight(region_i))
 */

import java.util.*;
import yi.stat.em.*;

public class GMMNNAdapterWeightedMax extends GMMNNAdapter{
  public GMMNNAdapterWeightedMax(ImgDataCenter data_center, LinkedList img_list, LinkedList ft_list, LinkedList obj_list) {
    super(data_center, img_list, ft_list, obj_list);
  }


  /**
   * Return the score or probability of having those mixture components for
   * the given image for the given feature.  GMMNNAdapterWeightedMax uses the
   * max of weighted p(region_i, component)
   * It will fix the low probability anyway even the pass-in parameter "fix_low_prob"
   * is false since the fix procedure can't be delayed as the case of using "max"
   * @param gmm
   * @param images
   * @param feature
   * @param fix_low_prob change low prob (like prob(0) to the smallest
   *        valid probability finded in the training stage
   * @return
   */
  double[] scoreOnComponents(GaussianMixtureModel gmm, String img, String feature, String obj) {
    // get the feature vectors
    FeatureRepresentationList features_frl = m_imgDataCenter.getImgFeatureList(
        img, // image name
        feature);

    if (!(features_frl instanceof EllipseFeatureRepresentationList)) {
      System.err.println("GMMNNAdapterWeightedMax can only handle EllipseFeatureRepresentationList!");
      System.exit(1);
    }
    EllipseFeatureRepresentationList features = (EllipseFeatureRepresentationList)features_frl;

    // save the score
    double[] scores = new double[gmm.getRstNumComponents()];

    double img_size = features.imgHeight * features.imgWidth;

    double minimum = ((Double)m_gmmUniformDensity.get(obj, feature)).doubleValue();

    // scores are set to 0 first to summarize
    if (features.size() == 0) {
      return scores;
    }

    int i_index = 0;
    for (Iterator i=features.iterator(); i.hasNext(); i_index++) {
      EllipseFeatureRepresentation ft = (EllipseFeatureRepresentation)i.next();
      double[] d = ft.data;
      HashMap scores_map = gmm.getDensitiesUnderComponents(d, false, false);

      // print out the probabilities under different components
      // since some components may be deleted due to singularity.  its
      // key doesn't continuous any more.  So I sorted them and use that as
      // index
      double[] scores_data = new double[scores_map.size()];
      ArrayList keys = new ArrayList(scores_map.keySet());
      java.util.Collections.sort(keys);
      int j_index = 0;
      for (Iterator j = keys.iterator(); j.hasNext(); j_index++) {
        Object key = j.next();
        double p = ((Double)scores_map.get(key)).doubleValue();
        if (p < minimum) p = minimum;
        scores_data[j_index] = Math.log(p);
      }

      // add weight
      double area = ft.getAbstractRegion().size();
      double weight = getWeight(img_size, area);
      for (int k=0; k<scores_data.length; k++) {
         scores_data[k] *= weight;
      }
      for (int k = 0; k < scores_data.length; k++) {
        if (scores[k] < scores_data[k]) {
          scores[k] = scores_data[k];
        }
      }
    }

    return scores;

  }

  double getWeight(double img_size, double region_size) {
    return region_size /img_size;
  }

}

