package yi.iu.region;

import yi.ds.*;
import yi.stat.em.*;
import yi.graph.polygon.GenericPolygon;

/**
 * PolygonRegionFeatureStat representes the statistical infromation of a region.
 * The mean and covariance of the feature will be kept as well as the shape of
 * the region which will be kept in both statistical (ellipse) format and
 * polygon format.  Typical implementations of PolygonRegionFeatureStat include
 * color regions and texture regions.
 */

public class PolygonRegionFeatureStat implements java.io.Serializable {
  public double[] m_mean;
  public double[][] m_covariance;
  protected GenericPolygon m_region;

  /**
   * This constructor is for castor only.  Don't call it directly
   */
  public PolygonRegionFeatureStat() {
  }

  public PolygonRegionFeatureStat(double[] mean, double[][] covariance, GenericPolygon region) {
    m_mean = mean;
    m_covariance = covariance;
    m_region = region;
  }

  public void setPolygonRegion(GenericPolygon r) {
    m_region = r;
  }

  public GenericPolygon getPolygonRegion() {
    return m_region;
  }

  public double[] getMean() {
    return m_mean;
  }

  public void setMean(double[] mean) {
    m_mean = mean;
  }

  public double[][] getCovariance() {
    return m_covariance;
  }

  public void setCovariance(double[][] covariance) {
    m_covariance = covariance;
  }

  private double[] covariance2;  // this variable is only used for un-marshall purpose
  public double[] getCovariance2() {
    if (m_covariance != null) {
      int n = getFeatureLength();
      covariance2 = new double[n * n];
      for (int i = 0, index = 0; i < n; i++) {
        for (int j = 0; j < n; j++, index++) {
          covariance2[index] = m_covariance[i][j];
        }
      }
    }
    return covariance2;
  }

  public void setCovariance2(double[] covariance) {
    covariance2 = covariance;
    int n = getFeatureLength();
    if (n*n == covariance.length) {
      m_covariance = new double[n][n];
      for (int i=0, index=0; i<n; i++) {
        for (int j=0; j<n; j++, index++) {
          m_covariance[i][j] = covariance[index];
        }
      }
    }
  }

  public int getFeatureLength() {
    return (m_mean==null)? 0: m_mean.length;
  }

  /**
   * Calculate the multiple rgb color polygon regions from an image
   * @param rgb
   * @param labels
   * @return
   */
  public static PolygonRegionFeatureStat[] createPolygonRegionFeatureStats(double[][] data, int[] labels, int width, int height, boolean ignore_zero) {
    GaussianComponent[] cumulators = GaussianComponent.createEMCumulators(data, labels, null);
    int n = (cumulators == null)? 0: cumulators.length;

    GenericPolygon[] polygon_regions = GenericPolygon.getPolygons(labels, width, height, ignore_zero);
    PolygonRegionFeatureStat[] feature_regions = new PolygonRegionFeatureStat[n];
    for (int i=0; i<n; i++) {
      double[] mean = null;
      try {
        mean = cumulators[i].getMeans();
      } catch (GaussianModelSingularException e) {
        feature_regions[i] = null;
        continue;
      }
      double[][] covariance = null;
      try {
        covariance = cumulators[i].getCovariance();
      } catch (GaussianModelSingularException e) {
        covariance = new double[mean.length][mean.length]; // make covariance = 0;
      }
      feature_regions[i] = new PolygonRegionFeatureStat(mean, covariance, polygon_regions[i]);
    }
    return feature_regions;
  }

}
