NumericTransformFilter.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 11k
Category:

Windows Develop

Development Platform:

Java

  1. /*
  2.  *    This program is free software; you can redistribute it and/or modify
  3.  *    it under the terms of the GNU General Public License as published by
  4.  *    the Free Software Foundation; either version 2 of the License, or
  5.  *    (at your option) any later version.
  6.  *
  7.  *    This program is distributed in the hope that it will be useful,
  8.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  *    GNU General Public License for more details.
  11.  *
  12.  *    You should have received a copy of the GNU General Public License
  13.  *    along with this program; if not, write to the Free Software
  14.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  */
  16. /*
  17.  *    NumericTransformFilter.java
  18.  *    Copyright (C) 1999 Eibe Frank
  19.  *
  20.  */
  21. package weka.filters;
  22. import java.io.*;
  23. import java.util.*;
  24. import java.lang.reflect.*;
  25. import weka.core.*;
  26. /** 
  27.  * Transforms numeric attributes using a
  28.  * given transformation method.<p>
  29.  *
  30.  * Valid filter-specific options are: <p>
  31.  *
  32.  * -R index1,index2-index4,...<br>
  33.  * Specify list of columns to transform. First and last are valid indexes.
  34.  * (default none). Non-numeric columns are skipped.<p>
  35.  *
  36.  * -V<br>
  37.  * Invert matching sense.<p>
  38.  *
  39.  * -C string <br>
  40.  * Name of the class containing the method used for transformation. 
  41.  * (default java.lang.Math) <p>
  42.  *
  43.  * -M string <br>
  44.  * Name of the method used for the transformation.
  45.  * (default abs) <p>
  46.  *
  47.  * @author Eibe Frank (eibe@cs.waikato.ac.nz) 
  48.  * @version $Revision: 1.13 $
  49.  */
  50. public class NumericTransformFilter extends Filter implements OptionHandler {
  51.   /** Stores which columns to transform. */
  52.   private Range m_Cols = new Range();
  53.   /** Class containing transformation method. */
  54.   private Class m_Class;
  55.   /** Transformation method. */
  56.   private Method m_Method;
  57.   /** Parameter types. */
  58.   private static Class[] PARAM = new Class[] {Double.TYPE};
  59.   /**
  60.    * Default constructor -- sets the default transform method
  61.    * to java.lang.Math.abs().
  62.    */
  63.   public NumericTransformFilter() {
  64.     try {
  65.       m_Class = Math.class;
  66.       m_Method = Math.class.getMethod("abs", PARAM);
  67.     } catch (NoSuchMethodException ex) {
  68.       System.err.println("One of those errors that you should never see");
  69.       ex.printStackTrace();
  70.     }
  71.   }
  72.   /**
  73.    * Sets the format of the input instances.
  74.    *
  75.    * @param instanceInfo an Instances object containing the input 
  76.    * instance structure (any instances contained in the object are 
  77.    * ignored - only the structure is required).
  78.    * @return true if the outputFormat may be collected immediately
  79.    * @exception Exception if the input format can't be set 
  80.    * successfully
  81.    */
  82.   public boolean setInputFormat(Instances instanceInfo) 
  83.        throws Exception {
  84.     if (m_Class == null) {
  85.       throw new IllegalStateException("No class has been set.");
  86.     }
  87.     if (m_Method == null) {
  88.       throw new IllegalStateException("No method has been set.");
  89.     }
  90.     super.setInputFormat(instanceInfo);
  91.     m_Cols.setUpper(instanceInfo.numAttributes() - 1);
  92.     setOutputFormat(instanceInfo);
  93.     return true;
  94.   }
  95.   /**
  96.    * Input an instance for filtering. The instance is processed
  97.    * and made available for output immediately.
  98.    *
  99.    * @param instance the input instance
  100.    * @return true if the filtered instance may now be
  101.    * collected with output().
  102.    * @exception IllegalStateException if no input format has been set.
  103.    * @exception InvocationTargetException if there is a problem applying
  104.    * the configured transform method.
  105.    */
  106.   public boolean input(Instance instance) throws Exception {
  107.     if (getInputFormat() == null) {
  108.       throw new IllegalStateException("No input instance format defined");
  109.     }
  110.     if (m_NewBatch) {
  111.       resetQueue();
  112.       m_NewBatch = false;
  113.     }
  114.     double []vals = new double[instance.numAttributes()];
  115.     Double []params = new Double[1];
  116.     Double newVal;
  117.     for(int i = 0; i < instance.numAttributes(); i++) {
  118.       if (instance.isMissing(i)) {
  119. vals[i] = Instance.missingValue();
  120.       } else {
  121. if (m_Cols.isInRange(i) &&
  122.     instance.attribute(i).isNumeric()) {
  123.   params[0] = new Double(instance.value(i));
  124.   newVal = (Double) m_Method.invoke(null, params);
  125.   if (newVal.isNaN() || newVal.isInfinite()) {
  126.     vals[i] = Instance.missingValue();
  127.   } else {
  128.     vals[i] = newVal.doubleValue(); 
  129.   }
  130. } else {
  131.   vals[i] = instance.value(i);
  132. }
  133.       }
  134.     }
  135.     Instance inst = null;
  136.     if (instance instanceof SparseInstance) {
  137.       inst = new SparseInstance(instance.weight(), vals);
  138.     } else {
  139.       inst = new Instance(instance.weight(), vals);
  140.     }
  141.     inst.setDataset(instance.dataset());
  142.     push(inst);
  143.     return true;
  144.   }
  145.   /**
  146.    * Returns an enumeration describing the available options
  147.    *
  148.    * @return an enumeration of all the available options
  149.    */
  150.   public Enumeration listOptions() {
  151.     Vector newVector = new Vector(4);
  152.     newVector.addElement(new Option(
  153.               "tSpecify list of columns to transform. First and last aren"
  154.       + "tvalid indexes (default none). Non-numeric columns are n"
  155.       + "tskipped.",
  156.               "R", 1, "-R <index1,index2-index4,...>"));
  157.     newVector.addElement(new Option(
  158.       "tInvert matching sense.",
  159.               "V", 0, "-V"));
  160.     newVector.addElement(new Option(
  161.               "tSets the class containing transformation method.n"+
  162.               "t(default java.lang.Math)",
  163.               "C", 1, "-C <string>"));
  164.     newVector.addElement(new Option(
  165.               "tSets the method. (default abs)",
  166.               "M", 1, "-M <string>"));
  167.     return newVector.elements();
  168.   }
  169.   /**
  170.    * Parses the options for this object. Valid options are: <p>
  171.    *
  172.    * -R index1,index2-index4,...<br>
  173.    * Specify list of columns to transform. First and last are valid indexes.
  174.    * (default none). Non-numeric columns are skipped.<p>
  175.    *
  176.    * -V<br>
  177.    * Invert matching sense.<p>
  178.    *
  179.    * -C string <br>
  180.    * Name of the class containing the method used for transformation.
  181.    * (default java.lang.Math) <p>
  182.    *
  183.    * -M string <br>
  184.    * Name of the method used for the transformation.
  185.    * (default abs) <p>
  186.    *
  187.    * @param options the list of options as an array of strings
  188.    * @exception Exception if an option is not supported
  189.    */
  190.   public void setOptions(String[] options) throws Exception {
  191.     
  192.     setAttributeIndices(Utils.getOption('R', options));
  193.     setInvertSelection(Utils.getFlag('V', options));
  194.     setClassName(Utils.getOption('C', options));
  195.     setMethodName(Utils.getOption('M', options));
  196.     if (getInputFormat() != null) {
  197.       setInputFormat(getInputFormat());
  198.     }
  199.   }
  200.   /**
  201.    * Gets the current settings of the filter.
  202.    *
  203.    * @return an array of strings suitable for passing to setOptions
  204.    */
  205.   public String [] getOptions() {
  206.     String [] options = new String [7];
  207.     int current = 0;
  208.     if (getInvertSelection()) {
  209.       options[current++] = "-V";
  210.     }
  211.     if (!getAttributeIndices().equals("")) {
  212.       options[current++] = "-R"; options[current++] = getAttributeIndices();
  213.     }
  214.     if (m_Class != null) {
  215.       options[current++] = "-C"; options[current++] = getClassName();
  216.     }
  217.     if (m_Method != null) {
  218.       options[current++] = "-M"; options[current++] = getMethodName();
  219.     }
  220.     while (current < options.length) {
  221.       options[current++] = "";
  222.     }
  223.     return options;
  224.   }
  225.   /**
  226.    * Get the class containing the transformation method.
  227.    *
  228.    * @return string describing the class
  229.    */
  230.   public String getClassName() {
  231.     return m_Class.getName();
  232.   }
  233.  
  234.   /**
  235.    * Sets the class containing the transformation method.
  236.    *
  237.    * @param name the name of the class
  238.    * @exception ClassNotFoundException if class can't be found
  239.    */
  240.   public void setClassName(String name) throws ClassNotFoundException {
  241.   
  242.     m_Class = Class.forName(name);
  243.   }
  244.  
  245.   /**
  246.    * Get the transformation method.
  247.    *
  248.    * @return string describing the transformation method.
  249.    */
  250.   public String getMethodName() {
  251.     return m_Method.getName();
  252.   }
  253.   /**
  254.    * Set the transformation method.
  255.    *
  256.    * @param name the name of the method
  257.    * @exception NoSuchMethodException if method can't be found in class
  258.    */
  259.   public void setMethodName(String name) throws NoSuchMethodException {
  260.     m_Method = m_Class.getMethod(name, PARAM);
  261.   }
  262.   /**
  263.    * Get whether the supplied columns are to be transformed or not
  264.    *
  265.    * @return true if the supplied columns will be kept
  266.    */
  267.   public boolean getInvertSelection() {
  268.     return m_Cols.getInvert();
  269.   }
  270.   /**
  271.    * Set whether selected columns should be transformed or not. 
  272.    *
  273.    * @param invert the new invert setting
  274.    */
  275.   public void setInvertSelection(boolean invert) {
  276.     m_Cols.setInvert(invert);
  277.   }
  278.   /**
  279.    * Returns the tip text for this property
  280.    *
  281.    * @return tip text for this property suitable for
  282.    * displaying in the explorer/experimenter gui
  283.    */
  284.   public String attributeIndicesTipText() {
  285.     return "Specify range of attributes to act on."
  286.       + " This is a comma separated list of attribute indices, with"
  287.       + " "first" and "last" valid values. Specify an inclusive"
  288.       + " range with "-". E.g: "first-3,5,6-10,last".";
  289.   }
  290.   /**
  291.    * Get the current range selection
  292.    *
  293.    * @return a string containing a comma separated list of ranges
  294.    */
  295.   public String getAttributeIndices() {
  296.     return m_Cols.getRanges();
  297.   }
  298.   /**
  299.    * Set which attributes are to be transformed (or kept if invert is true). 
  300.    *
  301.    * @param rangeList a string representing the list of attributes. Since
  302.    * the string will typically come from a user, attributes are indexed from
  303.    * 1. <br> eg: 
  304.    * first-3,5,6-last
  305.    * @exception InvalidArgumentException if an invalid range list is supplied
  306.    */
  307.   public void setAttributeIndices(String rangeList) {
  308.     m_Cols.setRanges(rangeList);
  309.   }
  310.   /**
  311.    * Set which attributes are to be transformed (or kept if invert is true)
  312.    *
  313.    * @param attributes an array containing indexes of attributes to select.
  314.    * Since the array will typically come from a program, attributes are indexed
  315.    * from 0.
  316.    * @exception InvalidArgumentException if an invalid set of ranges is supplied
  317.    */
  318.   public void setAttributeIndicesArray(int [] attributes) {
  319.     setAttributeIndices(Range.indicesToRangeList(attributes));
  320.   }
  321.   
  322.   /**
  323.    * Main method for testing this class.
  324.    *
  325.    * @param argv should contain arguments to the filter: use -h for help
  326.    */
  327.   public static void main(String [] argv) {
  328.     try {
  329.       if (Utils.getFlag('b', argv)) {
  330. Filter.batchFilterFile(new NumericTransformFilter(), argv);
  331.       } else {
  332. Filter.filterFile(new NumericTransformFilter(), argv);
  333.       }
  334.     } catch (Exception ex) {
  335.       System.out.println(ex.getMessage());
  336.     }
  337.   }
  338. }