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

package yi.iu.imgdb.learn;

import java.io.*;
import java.util.*;

import yi.ds.*;
import yi.iu.imgdb.desc.*;
import yi.util.config.*;
import yi.util.data.*;
import yi.util.io.*;
import yi.util.io.output.*;
import yi.stat.*;

/**
 * Image Data Center keeps the features and descriptions of a image set
 */
public class ImgDataCenter implements Serializable
{

   /**
    * HashMap with the image names as keys and linked object name lists as the values
    */
   protected LinkedListHashMap m_imgDescriptions = new LinkedListHashMap();

   /**
    * HashMap with feature names as keys, linked list hash maps (images->feature
    * vectors) as values
    */
   protected HashMapHashMap m_imgFeatures = new HashMapHashMap();

   /**
    * Linked name list of available feature data.
    */
   protected LinkedList m_featureList;

   /**
    * Linked name list of the objects
    */
   protected LinkedList m_objList;

   /**
    * Linked name list of the images
    */
   protected LinkedList m_imgList;

   /**
    * The length of each feature used
    */
   protected HashMap m_featureLengths = new HashMap();

   static final long serialVersionUID = 1529127804221156376L;

   protected ImgDataCenter()
   {

   }

   public static boolean VERBOSE = true;

   /**
    * Init the Image Data Center.  If want to get all the images in the
    * description file, pass in null as imgs.  If want to get all the objects
    * in the description file, pass in null as objs
    *
    * @param imgs
    * @param objs
    * @param desc_file
    * @param features
    * @param with_rgn_info whether to use the features with region information or without
    */
   public ImgDataCenter(String data_path, LinkedList imgs, LinkedList objs, String desc_file,
                        RepresentationDescriptor[] features)
   {

     // read the description file, and set description
     setDescriptions(imgs, objs, desc_file);

     // read the feature vectors
     m_featureList = new LinkedList();
     for (int i= 0; i<features.length; i++) {
       String generator = features[i].generator;
       generator = yi.util.data.StringUtil.getClassShortName(generator);
       m_featureList.add(generator);

       // create an instance of the specified feature
       try {

         // feature length
         int length = 0;

         // read the features vectors for each image
         int j_index = 0;
         for (Iterator j = m_imgList.iterator(); j.hasNext(); j_index++) {
           String img = (String) j.next();
           System.out.println("read representation #" + j_index + "/" +
                              m_imgList.size() + "  " +
                              data_path + img + ":");
           // read the feature
           try {
             FeatureRepresentationList data = FeatureUtil.readRepresentation(
                img, features[i]);
             m_imgFeatures.put(generator, img, data);
             length = data.featureDimension;
             if (VERBOSE) {
                double[][] vectors = data.as2DDoubleArray();
               if (vectors != null) {
                 System.out.println("" + vectors.length + "x" + length);
               }
               yi.util.io.OutputResult.print(System.out, vectors);
             }
           }
           catch (Exception e) {
             System.err.println("read representation " + data_path + img + " on " + generator + " error!");
             e.printStackTrace();
             continue;
           }

         }
         m_featureLengths.put(generator, new Integer(length));
       } catch (Exception e) {
         e.printStackTrace();
         continue;
       }
     }

   }

   /**
    * Initialize image data center with specified feature vectors
    * @param data_path
    * @param imgs
    * @param objs
    * @param desc_file
    * @param generator
    * @param data_list
    */
   public ImgDataCenter(LinkedList imgs, LinkedList objs, String desc_file,
                        String generator, FeatureRepresentationList[] data_list)
   {

     // read the description file, and set description
     setDescriptions(imgs, objs, desc_file);

     // read the feature vectors
     m_featureList = new LinkedList();
     m_featureList.add(generator);

     // create an instance of the specified feature
     try {

       // feature length
       int length = 0;

       // read the features vectors for each image
       int j_index = 0;
       for (Iterator j = m_imgList.iterator(); j.hasNext(); j_index++) {
         String img = (String) j.next();
         System.out.println("#" + j_index + "/" + m_imgList.size() + "  " +
                            img + ":");
         // read the feature
         try {
           FeatureRepresentationList data = data_list[j_index];
           m_imgFeatures.put(generator, img, data);
           length = data.featureDimension;
           double[][] vectors = data.as2DDoubleArray();
           yi.util.io.OutputResult.print(System.out, vectors);
         }
         catch (Exception e) {
           e.printStackTrace();
           continue;
         }

       }
       m_featureLengths.put(generator, new Integer(length));
     }
     catch (Exception e) {
       e.printStackTrace();
     }

   }

   void setDescriptions(LinkedList imgs, LinkedList objs, String desc_file) {
     // read the description file
     ImgDescManager img_manager = new ImgDescManager();
     img_manager.readFromFile(desc_file);

     // get the image name list
     m_imgList = (imgs == null)?
         new LinkedList(img_manager.getFiles()) :
         (LinkedList) imgs.clone();
//     java.util.Collections.sort(m_imgList);

     // get the object name list
     m_objList = (objs == null) ?
         new LinkedList(img_manager.getObjects()) :
         (LinkedList) objs.clone();
     java.util.Collections.sort(m_objList);
     // construct a hash set of the objects for quick check
     HashSet obj_set = (m_objList == null) ? null : new HashSet(m_objList);

     // contruct img->descriptions map
     m_imgDescriptions.clear();
     for (Iterator i= m_imgList.iterator(); i.hasNext(); ) {
       String img = (String)i.next();
       System.out.println(img + ":" );
       HashSet descriptions = img_manager.getDesc(img);
       ArrayList sorted_desc = new ArrayList(descriptions);
       java.util.Collections.sort(sorted_desc);
       for (Iterator j= descriptions.iterator(); j.hasNext(); ) {
         Object obj = j.next();
         if (obj_set.contains(obj)) {  // only add the object when it is in the specified list
           m_imgDescriptions.addToList(img, obj);
           System.out.println(" " + obj);
         }
       }
     }

   }

   /**
    * Return the image names in the data center
    * @return java.util.LinkedList
    */
   public LinkedList getImageList()
   {
    return m_imgList;
   }

   /**
    * Return the object descriptions in a list
    * @return LinkedList
    */
   public LinkedList getObjectList()
   {
    return m_objList;
   }

   /**
    * Returned the feature name list
    * @return LinkedList
    */
   public LinkedList getFeatureList()
   {
    return m_featureList;
   }

   /**
    * return the length of a feature
    * @return
    */
   public int getFeatureLength(Object feature) {
     int len = ((Integer)m_featureLengths.get(feature)).intValue();
     return len;
   }

   /**
    * Select specified attributes for features.  Eg. {"color"->[0,4,5]} means
    * only use the 1st, 5th, and 6th attributes for "color" feature.  After
    * this method is called, the
    * @param ft_attr_sel
    */
   public void selectAttributes(HashMap ft_attr_sel) {
     // if null is passed in, just ignore it
     if (ft_attr_sel == null) return;

     // loop through each features defined in the selector
     for (Iterator i=ft_attr_sel.keySet().iterator(); i.hasNext();) {
       String ft = (String)i.next();
       int[] selector = (int[])ft_attr_sel.get(ft);
       if (selector == null || selector.length <= 0) continue;

       // loop through each image in the data center
       LinkedList imgs = getImageList();
       for (Iterator j=imgs.iterator(); j.hasNext(); ) {
         String img = (String)j.next();

         // select attributes on the FeatureRepresentationList for each image
         // and for each feature
         FeatureRepresentationList ft_list = getImgFeatureList(img, ft);
         ft_list.selectAttributes(selector);
       }

       // change the feature dimension information
       m_featureLengths.put(ft, new Integer(selector.length));
     }
   }

   /**
    * Convert the first 3 componet of data from CIELab to HSI
    */
   public void convertCIELabtoHSI() {
     // loop through each features defined in the selector
     for (Iterator i=m_featureList.iterator(); i.hasNext();) {
       String ft = (String)i.next();

       // loop through each image in the data center
       LinkedList imgs = getImageList();
       for (Iterator j=imgs.iterator(); j.hasNext(); ) {
         String img = (String)j.next();

         // select attributes on the FeatureRepresentationList for each image
         // and for each feature
         FeatureRepresentationList ft_list = getImgFeatureList(img, ft);
         for (Iterator f = ft_list.iterator(); f.hasNext(); ) {
           FeatureRepresentation fr = (FeatureRepresentation)f.next();
           double[] data = fr.data;
           int rgb = yi.iu.processor.color.CIELab.lab2rgb(data[0], data[1], data[2]);
           int[] rgb2 = yi.iu.processor.color.ColorUtil.RGB2IntArray(rgb);
           float[] hsb = new float[3];
           java.awt.Color.RGBtoHSB(rgb2[0], rgb2[1], rgb2[2], hsb);
           data[0] = hsb[0]; data[1] = hsb[1]; data[2] = hsb[2];
         }
       }

     }
   }


   /**
    * Return the image object descriptions of a particular image
    * @param img
    * @return LinkedList
    */
   public LinkedList getImgDescriptions(String img)
   {
     LinkedList desc = (LinkedList)m_imgDescriptions.get(img);
     if (desc == null) return new LinkedList();
     else return desc;
   }

   /**
    * Write the image data center as a java object to file
    * @param file
    */
   public void writeToFile (String file) throws java.io.IOException
   {
     DOU_Ser.output(file, this);
   }

   /**
    * create a image data center reading from a file
    *
    * @param file
    * @return ImgDataCenter
    */
   public static ImgDataCenter createFromFile(String file) throws Exception
   {
    return (ImgDataCenter)yi.util.io.input.DIU_Ser.input(file);
   }

   /**
    * Return the feature list of a specified feature of a given image
    * @param img
    * @param feature
    * @return FeatureRepresentationList
    */
   public FeatureRepresentationList getImgFeatureList(String img, String generator)
   {
    return (FeatureRepresentationList)m_imgFeatures.get(generator, img);
   }

   public void setImgFeatureList(String img, String generator, FeatureRepresentationList data)
   {
     if (!m_imgList.contains(img)) {
       System.out.println("add new image " + img);
       m_imgList.add(img);
     }
     m_imgFeatures.put(generator, img, data);
     if (!m_featureLengths.containsKey(generator)) {
       m_featureLengths.put(generator, new Integer(data.featureDimension));
     } else {
       assert(((Integer)m_featureLengths.get(generator)).intValue() == data.featureDimension);
     }
   }


   /**
    * Group the feature vectors from all images on the specified feature.
    * The data is useful for data analysis.  (eg. to see whether they are
    * Gaussian distribution)
    * @param feature
    * @return
    */
   public double[][] groupFeatureVectors(String feature) {
     return groupFeatureVectors(m_imgList, feature);
   }

   /**
    * Add noise to the feature vectors so that the covariance matrix will not
    * be singular.  The noise will follow normal distribution and the unit
    * will be normalized to ratio_to_deviation * deviation for each dimension
    */
   public void addNoise(double ratio_to_deviation) {
     Random r = new Random();
     for (Iterator i=m_featureList.iterator(); i.hasNext(); ) {
       String feature = (String)i.next();
       System.out.println("add noise to " + feature);
       double[][] data = groupFeatureVectors(feature);
       double[] variances = StatUtil.varianceOnCol(data);
       double[] maximums = StatUtil.maximumOnCol(data);
       double[] minimums = StatUtil.minimumOnCol(data);
       double[] norm_unit = new double[variances.length];
       for (int j=0; j<variances.length; j++) {
         norm_unit[j] = Math.sqrt(variances[j]) * ratio_to_deviation;
         System.out.println("dim " + j + ": " + norm_unit[j] +
                            ", var = " + variances[j] +
                            ", max = " + maximums[j] +
                            ", min = " + minimums[j]);
       }
       for (int j=0; j<data.length; j++) {
         for (int k=0; k<data[j].length; k++) {
           double noise = r.nextGaussian() * norm_unit[k];
           data[j][k] += noise;
         }
       }
     }
   }

   /**
    * Group the feature vectors from all the specified images on the specified
    * feature.  The data is useful for data analysis.  (eg. to see whether they are
    * Gaussian distribution)
    * @param images
    * @param feature
    * @return
    */
   public double[][] groupFeatureVectors(LinkedList images, String feature) {
     int ft_dim = getFeatureLength(feature);
     FeatureRepresentationList data_list = new FeatureRepresentationList(ft_dim);
     for (Iterator j = images.iterator(); j.hasNext(); ) {
       FeatureRepresentationList fts = getImgFeatureList(
           (String) j.next(), // image name
           feature);
       data_list.addAll(fts);
     }
     double[][] data = data_list.as2DDoubleArray();
     return data;
   }

//   /**
//    * Init an image data center by combining the features in another image data
//    * center
//    * @param data_center
//    */
//   public void combineRegionFeatures(ImgDataCenter data_center, String ft_name, int size_threshold) {
//     if (m_featureList.size() <= 1) return;
//
//     // get the first two features to combine
//     String ft1 = (String)m_featureList.removeFirst();
//     String ft2 = (String)m_featureList.removeFirst();
//
//     for (Iterator i=m_imgList.iterator(); i.hasNext();) {
//       String img = (String)i.next();
//
//       LabeledRgnFtRepList ft_list1 = (LabeledRgnFtRepList)m_imgFeatures.remove(ft1, img);
//       LabeledRgnFtRepList ft_list2 = (LabeledRgnFtRepList)m_imgFeatures.remove(ft2, img);
//
//       LabeledRgnFtRepList new_ft_list = LabeledRgnFtRepList.combineTwoRegionFeature(ft_list1, ft_list2, size_threshold);
//
//       m_imgFeatures.put(ft_name, img, new_ft_list);
//
//       System.out.println("img = " + img + ": " + ft_list1.size() + "+" +
//                          ft_list2.size() + "=" + new_ft_list.size() + "(dim = " +
//                          new_ft_list.featureDimension + ")");
//     }
//
//     // remove the old features
//     m_imgFeatures.remove(ft1);
//     m_imgFeatures.remove(ft2);
//
//     m_featureList.addFirst(ft_name);
//     int len1 =  ((Integer)m_featureLengths.remove(ft1)).intValue();
//     int len2 =  ((Integer)m_featureLengths.remove(ft2)).intValue();
//     m_featureLengths.put(ft_name, new Integer(len1 + len2));
//   }

   /**
    * Merge two String linked list.  If the strings are equal, then there will
    * be only one instance in the merged list
    * @param list1
    * @param list2
    * @return
    */
   protected LinkedList mergeStringList(LinkedList list1, LinkedList list2) {
     HashSet set1 = new HashSet(list1);
     HashSet set2 = new HashSet(list2);
     set1.addAll(set2);
     return new LinkedList(set1);
   }

   public void merge(ImgDataCenter idc2) {
     System.out.println("features # " + m_featureList.size());
     System.out.println("features # " + idc2.m_featureList.size());
     m_featureList = mergeStringList(m_featureList, idc2.m_featureList);
     System.out.println("merged features # " + m_featureList.size());

     System.out.println("object # " + m_objList.size());
     System.out.println("object # " + idc2.m_objList.size());
     m_objList = mergeStringList(m_objList, idc2.m_objList);
     System.out.println("merged object # " + m_objList.size());

     System.out.println("image # " + m_imgList.size());
     System.out.println("image # " + idc2.m_imgList.size());
     m_imgList = mergeStringList(m_imgList, idc2.m_imgList);
     System.out.println("merged image # " + m_imgList.size());

     // merge descriptions
     // the description of the same image will be merged too
     System.out.println("image description # " + m_imgDescriptions.deepSize());
     System.out.println("image description # " + idc2.m_imgDescriptions.deepSize());
     for (Iterator i=idc2.m_imgDescriptions.keySet().iterator(); i.hasNext(); ) {
       Object key1 = i.next();
       LinkedList list2 = idc2.m_imgDescriptions.getList(key1);
       if (m_imgDescriptions.containsKey(key1)) {
         LinkedList list1 = m_imgDescriptions.getList(key1);
         list1 = mergeStringList(list1, list2);
         m_imgDescriptions.put(key1, list1);
       } else {
         m_imgDescriptions.put(key1, list2);
       }
     }
     System.out.println("merged image description # " + m_imgDescriptions.deepSize());

     // merge image features
     // if feature vector from the second one will overwrite the first one if
     // it belongs to the same image and same feature.
     System.out.println("image features # " + m_imgFeatures.deepSize());
     System.out.println("image features # " + idc2.m_imgFeatures.deepSize());
     m_imgFeatures.putAllInDeep (idc2.m_imgFeatures);
     System.out.println("merged image features # " + m_imgFeatures.deepSize());

     m_featureLengths.putAll(idc2.m_featureLengths);
   }

   /**
    * Merge two image data centers.  This is useful specially when you want to
    * combine different image features
    */
   public static class MergeImgDataCenters {
     public final static String USAGE = "Usage: -d data_center_1 -m data_center_2 -o output_data_center";

     public static void main(String[] args) {
       try {

         // init configuration
         Configuration.init(args);

         String data_center_name_1 = ReadArgu.getOption('d', args);
         String data_center_name_2 = ReadArgu.getOption('m', args);
         String output_file = ReadArgu.getOption('o', args);
         if (data_center_name_1 == null || data_center_name_2 == null || output_file == null) {
           System.err.println(USAGE);
           System.exit(1);
         }

         String rep_path = Configuration.getParameter("REPRESENTATION_PATH", "");

         ImgDataCenter data_center_1 = ImgDataCenter.createFromFile(
             rep_path + data_center_name_1);

         ImgDataCenter data_center_2 = ImgDataCenter.createFromFile(
             rep_path + data_center_name_2);

         data_center_1.merge(data_center_2);

         data_center_1.writeToFile(rep_path + output_file);
        }
       catch (Exception e) {
         e.printStackTrace();
       }
     }
   }

   /**
    * Set new description to a data center
    */
   public static class SetDescription {
     public final static String USAGE = "Usage: -d data_center_1 -m desc_file -o output_data_center";

     public static void main(String[] args) {
       try {

         // init configuration
         Configuration.init(args);

         String data_center_name_1 = ReadArgu.getOption('d', args);
         String desc_file = ReadArgu.getOption('m', args);
         String output_file = ReadArgu.getOption('o', args);
         if (data_center_name_1 == null || desc_file == null || output_file == null) {
           System.err.println(USAGE);
           System.exit(1);
         }

         String rep_path = Configuration.getParameter("REPRESENTATION_PATH", "");

         ImgDataCenter data_center_1 = ImgDataCenter.createFromFile(
             rep_path + data_center_name_1);

          data_center_1.setDescriptions(null, null, desc_file);

         data_center_1.writeToFile(rep_path + output_file);
        }
       catch (Exception e) {
         e.printStackTrace();
       }
     }
   }

   public void replaceDescriptions(String desc_file) {
     // read the description file
     ImgDescManager img_manager = new ImgDescManager();
     img_manager.readFromFile(desc_file);


     // merge descriptions
     // the description of the same image will be merged too
     System.out.println("image description # " + m_imgDescriptions.deepSize());
     System.out.println("files in new description # " + img_manager.getFiles().size());
     for (Iterator i= m_imgList.iterator(); i.hasNext(); ) {
       String img = (String)i.next();
       System.out.println(img + ":" );
       HashSet descriptions = img_manager.getDesc(img);
       System.out.println(" # desc = " + descriptions.size());
       if (descriptions != null) {
         m_imgDescriptions.remove(img);
         for (Iterator j = descriptions.iterator(); j.hasNext(); ) {
           Object obj = j.next();
           if (!m_objList.contains(obj)) {
             m_objList.add(obj);
             System.out.println("add object " + obj );
           }
           m_imgDescriptions.addToList(img, obj);
           System.out.println(" " + obj);
         }
       } else {
         System.out.println(" * unchanged" );
       }

     }
     System.out.println("merged image description # " + m_imgDescriptions.deepSize());

   }

   /**
    * Replace image decriptions in a image data center
    */
   public static class ReplaceDescriptions {
     public final static String USAGE = "Usage: -d desc_file -i image_data_center -o output_data_center -r (replace all)";

     public static void main(String[] args) {
       try {

         // init configuration
         Configuration.init(args);

         String data_center_name = ReadArgu.getOption(
             'i', args
             );
          if (data_center_name == null) {
            System.err.println(USAGE);
            System.exit(1);
          }

         String rep_path = Configuration.getParameter("REPRESENTATION_PATH", "");

         ImgDataCenter data_center = ImgDataCenter.createFromFile(
             rep_path + data_center_name);

         String desc_name = ReadArgu.getOption(
             'd', args);
          if (desc_name == null) {
            System.err.println(USAGE);
            System.exit(1);
          }

          boolean replace_all = (new Boolean((ReadArgu.getOption('r', args, "false")))).booleanValue();
          if (replace_all) {
            data_center.m_objList.clear();
          }

         data_center.replaceDescriptions(desc_name);

         // write the data center to disk
         String output_file = ReadArgu.getOption('o', args);
         if (output_file != null) {
           data_center.writeToFile(rep_path + output_file);
         }

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

//   /**
//    * Combine the features in the image data center
//    */
//   public static class CombineRegionFeatures {
//
//     public final static String USAGE = "Usage: -d data_center [-f combined_feature_name] [-o output_file_name] [-t size_threshold]";
//
//     public static void main(String[] args) {
//       try {
//
//         // init configuration
//         Configuration.init(args);
//
//         String data_center_name = ReadArgu.getOption(
//            'd', args,
//            "groundtruth.ser"
//         );
//
//         ImgDataCenter data_center = ImgDataCenter.createFromFile(
//            data_center_name);
//
//         // get the new feature name
//         String feature = ReadArgu.getOption('f', args, "combined");
//
//         // get the size threshold
//         String size_threshold_str = ReadArgu.getOption('t', args, "256");
//         int size_threshold = Integer.parseInt(size_threshold_str);
//
//         data_center.combineRegionFeatures(data_center, feature, size_threshold);
//
//         // write the data center to disk
//         String output_file = ReadArgu.getOption('o', args);
//         if (output_file != null) {
//           data_center.writeToFile(output_file);
//         }
//
//       }catch (Exception e) {
//         e.printStackTrace();
//       }
//     }
//   }


   public String toString() {
     StringWriter str = new StringWriter();
     PrintWriter out = new PrintWriter(str);

     // image list
     out.println("images:");
     ArrayList sorted_image_list = new ArrayList(m_imgList);
     Collections.sort(sorted_image_list);
     OutputResult.print(out, sorted_image_list);


     out.println("objects:");
     OutputResult.print(out, m_objList);

     out.println("features:");
     OutputResult.print(out, m_featureList);

     out.println("image descriptions:");
     out.print(m_imgDescriptions);

     out.println("image features:");
     out.print(m_imgFeatures);
     return str.toString();
   }

   /**
    * Print out the image data center for review
    */
   public static class Print {
     public final static String USAGE = "Usage: [-d data_center_serialized_file]";

     public static void main(String[] args) {

       // init configuration
       Configuration.init(args);

       try {

         // read in an ObjGMMAdapter object
         String img_data_center_file = ReadArgu.getOption(
             'd', args
             );

        if (img_data_center_file == null) {
          System.err.println(USAGE);
          System.exit(1);
        }

        String rep_path = Configuration.getParameter("REPRESENTATION_PATH", "");
        ImgDataCenter idc = ImgDataCenter.createFromFile(rep_path + img_data_center_file);
        System.out.print(idc);

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

   public void fixImageFileNames() {
     LinkedList new_imgList = new LinkedList();
     for (Iterator i=m_imgList.iterator(); i.hasNext(); ) {
       String img_name = (String)i.next();
       img_name = img_name.replaceFirst("f:/creatas/", "creatas/COMPS1/");
       img_name = img_name.replaceFirst("f:/groundtruth/", "groundtruth/");
       new_imgList.add(img_name);
     }
     m_imgList = new_imgList;

     LinkedListHashMap new_imgDescriptions = new LinkedListHashMap();
     for (Iterator i=m_imgDescriptions.keySet().iterator(); i.hasNext(); ) {
       String img_name = (String)i.next();
       Object desc = m_imgDescriptions.get(img_name);
       img_name = img_name.replaceFirst("f:/creatas/", "creatas/COMPS1/");
       img_name = img_name.replaceFirst("f:/groundtruth/", "groundtruth/");
       new_imgDescriptions.put(img_name, desc);
     }
     m_imgDescriptions = new_imgDescriptions;

     HashMapHashMap new_imgFeatures = new HashMapHashMap();
     for (Iterator i=m_imgFeatures.keySet().iterator(); i.hasNext(); ) {
       Object ft = i.next();
       HashMap img_features = (HashMap)m_imgFeatures.get(ft);
       for (Iterator j=img_features.keySet().iterator(); j.hasNext(); ) {
         String img_name = (String) j.next();
         Object obj = img_features.get(img_name);
         img_name = img_name.replaceFirst("f:/creatas/", "creatas/COMPS1/");
         img_name = img_name.replaceFirst("f:/groundtruth/", "groundtruth/");
         new_imgFeatures.put(ft, img_name, obj);
       }
     }
     m_imgFeatures = new_imgFeatures;
   }

   /**
    * Print out the image data center for review
    */
   public static class FixImageFileNames {
     public final static String USAGE = "Usage: [-d data_center_serialized_file] -o output_data_center_file";

     public static void main(String[] args) {

       // init configuration
       Configuration.init(args);

       try {

         // read in an ObjGMMAdapter object
         String img_data_center_file = ReadArgu.getOption(
             'd', args,
             "sd.ct1.bg.ser"
             );

          // read in an ObjGMMAdapter object
          String out_img_data_center_file = ReadArgu.getOption(
              'o', args);
          if (out_img_data_center_file == null) {
            System.err.println(USAGE);
            System.exit(0);
          }

         ImgDataCenter idc = ImgDataCenter.createFromFile(img_data_center_file);
         idc.fixImageFileNames();
         idc.writeToFile(out_img_data_center_file);

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

   /**
    * Group the vectors of one specified feature together.  The results are
    * useful for, say, data analysis
    */
   public static class GroupFeatureVectors {
     public final static String USAGE = "Usage: [-d img_data_center] [-f feature_class_name] [-o output_file_name]";
     public static void main(String[] args) {
       try {

         // init configuration
         Configuration.init(args);

         // init the datacenter
         String data_center_file = ReadArgu.getOption(
             'd', args,
             "groundtruth.ser"
             );
         ImgDataCenter data_center = ImgDataCenter.createFromFile(
             data_center_file);

         // get the feature data class names
         String feature = ReadArgu.getOption(
             'f', args,
             "yi.iu.processor.texture.reg.DS_PolygonRegionTextureStat"
             );

          String output_file = ReadArgu.getOption('o', args, "t.dat");

         double[][] data = data_center.groupFeatureVectors(feature);
         OutputResult.outputResult(output_file, data);
       }
       catch (Exception e) {
         e.printStackTrace();
       }

     }
   }

   /**
    * Show the regions of images.  You specify a feature to draw a color labeled
    * image (specially useful for combined features).  A html file having the
    * links to the images is generated for review.
    */
   public static class ShowRegions {

     public final static String USAGE = "Usage: [-d img_data_center_file] [-i img_list_file] [-f feature] [-p image_path]";

     public static void main(String[] args) {

       // init configuration
       Configuration.init(args);

       try {

         // init the datacenter
         String data_center_name = ReadArgu.getOption(
             'd', args,
             "groundtruth.rgn.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);
         }

         String path = ReadArgu.getOption(
             'p', args,
             ""
             );

         /** @todo custom the feature name */
         String feature = ReadArgu.getOption('f', args, "cltl");

         // loop through the image and their features
         int i_index = 0;
         for (Iterator i=img_list.iterator(); i.hasNext(); i_index++) {
           String img = (String)i.next();
           RgnFeatureRepresentationList rfrl =
               (RgnFeatureRepresentationList)data_center.getImgFeatureList(img, feature);
           int[] label_img =
               rfrl.drawScoreDemo(null, new FeatureScoringCapable() { // a inner class give sequence score
                 int count = 1;
                 public double getFeatureScore(double[] feature, Object object) {
                   return count++;
                 }
               }, 0, 1);
           int[] pixels_img = yi.util.ImageUtil.makeNewImageFromLabel(
               label_img, true);
           /** @todo make image suffix setable */
           OutputResult.outputGIFImage(path + img + "." + DOU.shortName(feature) + ".rgn.gif", pixels_img,
                                                  rfrl.imgWidth, rfrl.imgHeight); // color_cluster

          System.out.println("<P>" +
                             "<IMG SRC=\"" + img + "\" width=256>" +
                             "<IMG SRC=\"" + img + ".s256.color.rgn.gif\" width=256>" +
                             "<IMG SRC=\"" + img + ".s256.text.rgn.gif\" width=256>" +
                             "<IMG SRC=\"" + path + img + "." + DOU.shortName(feature) + ".rgn.gif" +" width=256>" +
                             "</P>");
         }
       } catch (Exception e) {
         e.printStackTrace();
       }
     }
   }

   /**
    * Demo the image scores.  Using RgnFeatureRepresentationList which provides
    * the function of drawScoreDemo and FeatureScoringCapable which provides
    * the function of getFeatureScore
    */
   public static class DemoRegionScores {

     public final static String USAGE = "Usage: [-d img_data_center_file] [-i img_list_file] [-f feature] [-a model_adapter] [-o object] [-t shift] [-c scale] [-s suffix]";

     public static void main(String[] args) {

       // init configuration
       Configuration.init(args);

       try {

         // init the datacenter
         String data_center_name = ReadArgu.getOption(
             'd', args,
             "groundtruth.rgn.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);
         }

         /** @todo custom the feature name */
         String feature = ReadArgu.getOption('f', args, "cltl");

         // read the FeatureScoringCapable
         String model_adapter = ReadArgu.getOption('a', args, "ObjGMMAdapter");
         FeatureScoringCapable adapter = (FeatureScoringCapable)StatModelAdapter.createFromFile(model_adapter);

         String object = ReadArgu.getOption('o', args, "trees");

         String suffix = ReadArgu.getOption('s', args, "score");

         String shift_str = ReadArgu.getOption('t', args, "128");
         double shift = Double.parseDouble(shift_str);

         String scale_str = ReadArgu.getOption('c', args, "10");
         double scale = Double.parseDouble(scale_str);

         // loop through the image and their features
         int i_index = 0;
         for (Iterator i=img_list.iterator(); i.hasNext(); i_index++) {
           String img = (String)i.next();
           RgnFeatureRepresentationList rfrl =
               (RgnFeatureRepresentationList)data_center.getImgFeatureList(img, feature);
           int[] label_img =
               rfrl.drawScoreDemo(object, adapter, shift, scale);
           int[] pixels_img = yi.util.ImageUtil.makeNewImageFromGray(label_img);
           /** @todo make image suffix setable */
           OutputResult.outputGIFImage(img + suffix, pixels_img,
                                                  rfrl.imgWidth, rfrl.imgHeight); // color_cluster

          System.out.println("<P>" +
                             "<IMG SRC=\"" + img + "\" width=256>" +
                             "<IMG SRC=\"" + img + ".s256.color.rgn.gif\">" +
                             "<IMG SRC=\"" + img + ".s256.text.rgn.gif\">" +
                             "<IMG SRC=\"" + img + ".ct.rgn.gif\">" +
                             "<IMG SRC=\"" + img + suffix + "\">" +
                             "</P>");
         }
       } catch (Exception e) {
         e.printStackTrace();
       }
     }
   }

   /**
    * Generate a html file which links to the original image file, the color
    * region image, the texture region image, and etc.
    */
   public static class GenHtml {

     public final static String USAGE = "Usage: [-d img_data_center_file] [-i img_list_file] [-f ft_list] [-l gen_img_links] [-o gen_obj_list] [-v gen_feature_vectors]";

     public static void main(String[] args) {

       // init configuration
       Configuration.init(args);

       try {

         // read in an ObjGMMAdapter object
         String img_data_center_file = ReadArgu.getOption(
             'd', args
             );

        if (img_data_center_file == null) {
          System.err.println(USAGE);
          System.exit(1);
        }

        String rep_path = Configuration.getParameter("REPRESENTATION_PATH", "");
        String img_path = Configuration.getParameter("IMAGE_PATH", "");
        ImgDataCenter data_center = ImgDataCenter.createFromFile(rep_path + img_data_center_file);

         // 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);
         } else {
           img_list = data_center.getImageList();
         }

         // whether to generate the links to images
         boolean gen_links = (ReadArgu.getOption('l', args) != null);
         // whether to generate the object list for each image
         boolean gen_objs = (ReadArgu.getOption('o', args) != null);
         // whether to generate the feature vector list for each image
         boolean gen_vectors = (ReadArgu.getOption('v', args) != null);

         Collections.sort(img_list);

         // get the feature list name
         String ft_list_str = ReadArgu.getOption('f', args);
         // feature list
         FeatureDescriptor[] ft_list = FeatureDescriptor.parse(ft_list_str, data_center.getFeatureList());

         // loop through the image and their features
         int i_index = 0;
         System.out.println("<html><body>");
         for (Iterator i=img_list.iterator(); i.hasNext(); i_index++) {
           String img_name = (String)i.next();
           System.out.println("<p>");
           System.out.println(img_name + "<br>");
           if (gen_links) {
             System.out.println("<img src=" + img_path + img_name + ">");
//             for (int j=0; j<ft_list.length; j++) {
//               String ft = ft_list[j].generator;
//               String demo_suffix = FeatureDescriptor.getFeatureColorDemoName(ft_list[j], img_name, true);
//               System.out.println("<img src=" + demo_suffix + ">");
//             }
             System.out.println("<br>");
           }
           if (gen_objs) {
             LinkedList objs = data_center.getImgDescriptions(img_name);
             Collections.sort(objs);
             int o_index = 0;
             for (Iterator o = objs.iterator(); o.hasNext(); o_index++) {
               System.out.print(o.next());
               if (o_index < objs.size() - 1)
                 System.out.println(",");
             }
             System.out.println();
           }
           if (gen_vectors) {
             for (int j=0; j<ft_list.length; j++) {
               String ft = StringUtil.getClassShortName(ft_list[j].generator);
               if (ft_list.length > 1) {
                 System.out.println(j + "<br>");
               }
               FeatureRepresentationList fts = data_center.getImgFeatureList(
                  img_name, ft);
               double[][] data = fts.as2DDoubleArray();
               System.out.println("<table>");
               for (int k=0; k<data.length; k++) {
                 System.out.println("<tr>");
                 for (int m=0; m<data[k].length; m++) {
                   System.out.print("<td>");
                   System.out.print(data[k][m]);
                   System.out.print("</td>");
                 }
                 System.out.println("</tr>");
               }
               System.out.println("</table>");
             }
           }
           System.out.println("</p>");
         }
         System.out.println("</body></html>");
       } catch (Exception e) {
         e.printStackTrace();
       }
     }
   }

   public final static String USAGE = "Usage: -d img_description_file -r representaion_descriptor [-o output_file_name]";

   public static void main(String[] args) {
     try {

       // init configuration
       Configuration.init(args);

       // get the image description file name
       String desc_file = ReadArgu.getOption('d', args);
       if (desc_file == null) {
         System.err.println(USAGE);
         System.exit(1);
       }

       String image_path = Configuration.getParameter("IMAGE_PATH", "");
       String rep_path = Configuration.getParameter("REPRESENTATION_PATH", "");

       // 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 = ReadArgu.readStrings(img_list_file);
         img_list = yi.util.data.Conversion.asLinkedList(images);
       }

       // get the feature data class names
       String representation_desc_str = ReadArgu.getOption('r', args);
       if (representation_desc_str == null) {
         System.err.println(USAGE);
         System.exit(1);
       }
       RepresentationDescriptor[] represent_desc = RepresentationDescriptor.parse(representation_desc_str);

       // object list
       LinkedList obj_list = null;

//       // see whether generate with region info or not
//       String ft_list_type = ReadArgu.getOption('t', args, "FeatureRepresentable");

       /** @todo pass in parameter to decide what features to get (with or
        * without region informaiton */
       ImgDataCenter center = new ImgDataCenter(rep_path, img_list, obj_list, desc_file,
                                                represent_desc);

//       // print it outnull
//       System.out.println(center);

       // write the data center to disk
       String output_file = ReadArgu.getOption('o', args);
       if (output_file == null) {
         String features = new String("");
         for (int i=0; i<represent_desc.length; i++) {
           if (i!=0) features = features + "+";
           features = features + StringUtil.getClassShortName(represent_desc[i].generator);
         }
         output_file = yi.util.data.StringUtil.getFileSuffixNameRemoved(desc_file) + "." +
             features + "." +
             yi.util.data.StringUtil.getClassShortName(represent_desc[0].representation) +".idc";
       }
       center.writeToFile(rep_path + output_file);

//       // read from the disk
//       center = ImgDataCenter.createFromFile("center.ser");

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