PairedTTester.java
Upload User: rhdiban
Upload Date: 2013-08-09
Package Size: 15085k
Code Size: 45k
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.  *    PairedTTester.java
  18.  *    Copyright (C) 1999 Len Trigg
  19.  *
  20.  */
  21. package weka.experiment;
  22. import weka.core.Instances;
  23. import weka.core.Instance;
  24. import weka.core.Range;
  25. import weka.core.Attribute;
  26. import weka.core.Utils;
  27. import weka.core.FastVector;
  28. import weka.core.Statistics;
  29. import weka.core.OptionHandler;
  30. import java.io.BufferedReader;
  31. import java.io.FileReader;
  32. import java.util.Date;
  33. import java.text.SimpleDateFormat;
  34. import java.util.Enumeration;
  35. import java.util.Vector;
  36. import weka.core.Option;
  37. /**
  38.  * Calculates T-Test statistics on data stored in a set of instances.<p>
  39.  *
  40.  * Valid options from the command-line are:<p>
  41.  *
  42.  * -D num,num2... <br>
  43.  * The column numbers that uniquely specify a dataset.
  44.  * (default last) <p>
  45.  *
  46.  * -R num <br>
  47.  * The column number containing the run number.
  48.  * (default last) <p>
  49.  *
  50.  * -S num <br>
  51.  * The significance level for T-Tests.
  52.  * (default 0.05) <p>
  53.  *
  54.  * -R num,num2... <br>
  55.  * The column numbers that uniquely specify one result generator (eg:
  56.  * scheme name plus options).
  57.  * (default last) <p>
  58.  *
  59.  * @author Len Trigg (trigg@cs.waikato.ac.nz)
  60.  * @version $Revision: 1.14 $
  61.  */
  62. public class PairedTTester implements OptionHandler {
  63.   /** The set of instances we will analyse */
  64.   protected Instances m_Instances;
  65.   /** The index of the column containing the run number */
  66.   protected int m_RunColumn = 0;
  67.   /** The option setting for the run number column (-1 means last) */
  68.   protected int m_RunColumnSet = -1;
  69.   /** The significance level for comparisons */
  70.   protected double m_SignificanceLevel = 0.05;
  71.   /**
  72.    * The range of columns that specify a unique "dataset"
  73.    * (eg: scheme plus configuration)
  74.    */
  75.   protected Range m_DatasetKeyColumnsRange = new Range();
  76.   /** An array containing the indexes of just the selected columns */ 
  77.   protected int [] m_DatasetKeyColumns;
  78.   /** The list of dataset specifiers */
  79.   protected DatasetSpecifiers m_DatasetSpecifiers = 
  80.     new DatasetSpecifiers();
  81.   /**
  82.    * The range of columns that specify a unique result set
  83.    * (eg: scheme plus configuration)
  84.    */
  85.   protected Range m_ResultsetKeyColumnsRange = new Range();
  86.   /** An array containing the indexes of just the selected columns */ 
  87.   protected int [] m_ResultsetKeyColumns;
  88.   /** Stores a vector for each resultset holding all instances in each set */
  89.   protected FastVector m_Resultsets = new FastVector();
  90.   /** Indicates whether the instances have been partitioned */
  91.   protected boolean m_ResultsetsValid;
  92.   /** Indicates whether standard deviations should be displayed */
  93.   protected boolean m_ShowStdDevs = false;
  94.   /** Produce tables in latex format */
  95.   protected boolean m_latexOutput = false;
  96.   
  97.   /* A list of unique "dataset" specifiers that have been observed */
  98.   private class DatasetSpecifiers {
  99.     FastVector m_Specifiers = new FastVector();
  100.     /**
  101.      * Removes all specifiers.
  102.      */
  103.     protected void removeAllSpecifiers() {
  104.       m_Specifiers.removeAllElements();
  105.     }
  106.     /** 
  107.      * Add an instance to the list of specifiers (if necessary)
  108.      */
  109.     protected void add(Instance inst) {
  110.       
  111.       for (int i = 0; i < m_Specifiers.size(); i++) {
  112. Instance specifier = (Instance)m_Specifiers.elementAt(i);
  113. boolean found = true;
  114. for (int j = 0; j < m_DatasetKeyColumns.length; j++) {
  115.   if (inst.value(m_DatasetKeyColumns[j]) !=
  116.       specifier.value(m_DatasetKeyColumns[j])) {
  117.     found = false;
  118.   }
  119. }
  120. if (found) {
  121.   return;
  122. }
  123.       }
  124.       m_Specifiers.addElement(inst);
  125.     }
  126.     /**
  127.      * Get the template at the given position.
  128.      */
  129.     protected Instance specifier(int i) {
  130.       return (Instance)m_Specifiers.elementAt(i);
  131.     }
  132.     /**
  133.      * Gets the number of specifiers.
  134.      */
  135.     protected int numSpecifiers() {
  136.       return m_Specifiers.size();
  137.     }
  138.   }
  139.   /* Utility class to store the instances pertaining to a dataset */
  140.   private class Dataset {
  141.     Instance m_Template;
  142.     FastVector m_Dataset;
  143.     public Dataset(Instance template) {
  144.       m_Template = template;
  145.       m_Dataset = new FastVector();
  146.       add(template);
  147.     }
  148.     
  149.     /**
  150.      * Returns true if the two instances match on those attributes that have
  151.      * been designated key columns (eg: scheme name and scheme options)
  152.      *
  153.      * @param first the first instance
  154.      * @param second the second instance
  155.      * @return true if first and second match on the currently set key columns
  156.      */
  157.     protected boolean matchesTemplate(Instance first) {
  158.       
  159.       for (int i = 0; i < m_DatasetKeyColumns.length; i++) {
  160. if (first.value(m_DatasetKeyColumns[i]) !=
  161.     m_Template.value(m_DatasetKeyColumns[i])) {
  162.   return false;
  163. }
  164.       }
  165.       return true;
  166.     }
  167.     /**
  168.      * Adds the given instance to the dataset
  169.      */
  170.     protected void add(Instance inst) {
  171.       
  172.       m_Dataset.addElement(inst);
  173.     }
  174.     /**
  175.      * Returns a vector containing the instances in the dataset
  176.      */
  177.     protected FastVector contents() {
  178.       return m_Dataset;
  179.     }
  180.     /**
  181.      * Sorts the instances in the dataset by the run number.
  182.      *
  183.      * @param runColumn a value of type 'int'
  184.      */
  185.     public void sort(int runColumn) {
  186.       double [] runNums = new double [m_Dataset.size()];
  187.       for (int j = 0; j < runNums.length; j++) {
  188. runNums[j] = ((Instance) m_Dataset.elementAt(j)).value(runColumn);
  189.       }
  190.       int [] index = Utils.sort(runNums);
  191.       FastVector newDataset = new FastVector(runNums.length);
  192.       for (int j = 0; j < index.length; j++) {
  193. newDataset.addElement(m_Dataset.elementAt(index[j]));
  194.       }
  195.       m_Dataset = newDataset;
  196.     }
  197.   }
  198.  
  199.   /* Utility class to store the instances in a resultset */
  200.   private class Resultset {
  201.     Instance m_Template;
  202.     FastVector m_Datasets;
  203.     public Resultset(Instance template) {
  204.       m_Template = template;
  205.       m_Datasets = new FastVector();
  206.       add(template);
  207.     }
  208.     
  209.     /**
  210.      * Returns true if the two instances match on those attributes that have
  211.      * been designated key columns (eg: scheme name and scheme options)
  212.      *
  213.      * @param first the first instance
  214.      * @param second the second instance
  215.      * @return true if first and second match on the currently set key columns
  216.      */
  217.     protected boolean matchesTemplate(Instance first) {
  218.       
  219.       for (int i = 0; i < m_ResultsetKeyColumns.length; i++) {
  220. if (first.value(m_ResultsetKeyColumns[i]) !=
  221.     m_Template.value(m_ResultsetKeyColumns[i])) {
  222.   return false;
  223. }
  224.       }
  225.       return true;
  226.     }
  227.     /**
  228.      * Returns a string descriptive of the resultset key column values
  229.      * for this resultset
  230.      *
  231.      * @return a value of type 'String'
  232.      */
  233.     protected String templateString() {
  234.       String result = "";
  235.       String tempResult = "";
  236.       for (int i = 0; i < m_ResultsetKeyColumns.length; i++) {
  237. tempResult = m_Template.toString(m_ResultsetKeyColumns[i]) + ' ';
  238. // compact the string
  239.         tempResult = Utils.removeSubstring(tempResult, "weka.classifiers.");
  240.         tempResult = Utils.removeSubstring(tempResult, "weka.filters.");
  241.         tempResult = Utils.removeSubstring(tempResult, "weka.attributeSelection.");
  242. result += tempResult;
  243.       }
  244.       return result.trim();
  245.     }
  246.     
  247.     /**
  248.      * Returns a vector containing all instances belonging to one dataset.
  249.      *
  250.      * @param index a template instance
  251.      * @return a value of type 'FastVector'
  252.      */
  253.     public FastVector dataset(Instance inst) {
  254.       for (int i = 0; i < m_Datasets.size(); i++) {
  255. if (((Dataset)m_Datasets.elementAt(i)).matchesTemplate(inst)) {
  256.   return ((Dataset)m_Datasets.elementAt(i)).contents();
  257.       }
  258.       return null;
  259.     }
  260.     
  261.     /**
  262.      * Adds an instance to this resultset
  263.      *
  264.      * @param newInst a value of type 'Instance'
  265.      */
  266.     public void add(Instance newInst) {
  267.       
  268.       for (int i = 0; i < m_Datasets.size(); i++) {
  269. if (((Dataset)m_Datasets.elementAt(i)).matchesTemplate(newInst)) {
  270.   ((Dataset)m_Datasets.elementAt(i)).add(newInst);
  271.   return;
  272. }
  273.       }
  274.       Dataset newDataset = new Dataset(newInst);
  275.       m_Datasets.addElement(newDataset);
  276.     }
  277.     /**
  278.      * Sorts the instances in each dataset by the run number.
  279.      *
  280.      * @param runColumn a value of type 'int'
  281.      */
  282.     public void sort(int runColumn) {
  283.       for (int i = 0; i < m_Datasets.size(); i++) {
  284. ((Dataset)m_Datasets.elementAt(i)).sort(runColumn);
  285.       }
  286.     }
  287.   } // Resultset
  288.   /**
  289.    * Returns a string descriptive of the key column values for
  290.    * the "datasets
  291.    *
  292.    * @param template the template
  293.    * @return a value of type 'String'
  294.    */
  295.   private String templateString(Instance template) {
  296.     
  297.     String result = "";
  298.     for (int i = 0; i < m_DatasetKeyColumns.length; i++) {
  299.       result += template.toString(m_DatasetKeyColumns[i]) + ' ';
  300.     }
  301.     if (result.startsWith("weka.classifiers.")) {
  302.       result = result.substring("weka.classifiers.".length());
  303.     }
  304.     return result.trim();
  305.   }
  306.   /**
  307.    * Set whether latex is output
  308.    * @param l true if tables are to be produced in Latex format
  309.    */
  310.   public void setProduceLatex(boolean l) {
  311.     m_latexOutput = l;
  312.   }
  313.   /**
  314.    * Get whether latex is output
  315.    * @return true if Latex is to be output
  316.    */
  317.   public boolean getProduceLatex() {
  318.     return m_latexOutput;
  319.   }
  320.   /**
  321.    * Set whether standard deviations are displayed or not.
  322.    * @param s true if standard deviations are to be displayed
  323.    */
  324.   public void setShowStdDevs(boolean s) {
  325.     m_ShowStdDevs = s;
  326.   }
  327.   /**
  328.    * Returns true if standard deviations have been requested.
  329.    * @return true if standard deviations are to be displayed.
  330.    */
  331.   public boolean getShowStdDevs() {
  332.     return m_ShowStdDevs;
  333.   }
  334.   
  335.   /**
  336.    * Separates the instances into resultsets and by dataset/run.
  337.    *
  338.    * @exception Exception if the TTest parameters have not been set.
  339.    */
  340.   protected void prepareData() throws Exception {
  341.     if (m_Instances == null) {
  342.       throw new Exception("No instances have been set");
  343.     }
  344.     if (m_RunColumnSet == -1) {
  345.       m_RunColumn = m_Instances.numAttributes() - 1;
  346.     } else {
  347.       m_RunColumn = m_RunColumnSet;
  348.     }
  349.     if (m_ResultsetKeyColumnsRange == null) {
  350.       throw new Exception("No result specifier columns have been set");
  351.     }
  352.     m_ResultsetKeyColumnsRange.setUpper(m_Instances.numAttributes() - 1);
  353.     m_ResultsetKeyColumns = m_ResultsetKeyColumnsRange.getSelection();
  354.     if (m_DatasetKeyColumnsRange == null) {
  355.       throw new Exception("No dataset specifier columns have been set");
  356.     }
  357.     m_DatasetKeyColumnsRange.setUpper(m_Instances.numAttributes() - 1);
  358.     m_DatasetKeyColumns = m_DatasetKeyColumnsRange.getSelection();
  359.     
  360.     //  Split the data up into result sets
  361.     m_Resultsets.removeAllElements();  
  362.     m_DatasetSpecifiers.removeAllSpecifiers();
  363.     for (int i = 0; i < m_Instances.numInstances(); i++) {
  364.       Instance current = m_Instances.instance(i);
  365.       if (current.isMissing(m_RunColumn)) {
  366. throw new Exception("Instance has missing value in run "
  367.     + "column!n" + current);
  368.       } 
  369.       for (int j = 0; j < m_ResultsetKeyColumns.length; j++) {
  370. if (current.isMissing(m_ResultsetKeyColumns[j])) {
  371.   throw new Exception("Instance has missing value in resultset key "
  372.       + "column " + (m_ResultsetKeyColumns[j] + 1)
  373.       + "!n" + current);
  374. }
  375.       }
  376.       for (int j = 0; j < m_DatasetKeyColumns.length; j++) {
  377. if (current.isMissing(m_DatasetKeyColumns[j])) {
  378.   throw new Exception("Instance has missing value in dataset key "
  379.       + "column " + (m_DatasetKeyColumns[j] + 1)
  380.       + "!n" + current);
  381. }
  382.       }
  383.       boolean found = false;
  384.       for (int j = 0; j < m_Resultsets.size(); j++) {
  385. Resultset resultset = (Resultset) m_Resultsets.elementAt(j);
  386. if (resultset.matchesTemplate(current)) {
  387.   resultset.add(current);
  388.   found = true;
  389.   break;
  390. }
  391.       }
  392.       if (!found) {
  393. Resultset resultset = new Resultset(current);
  394. m_Resultsets.addElement(resultset);
  395.       }
  396.       m_DatasetSpecifiers.add(current);
  397.     }
  398.     // Tell each resultset to sort on the run column
  399.     for (int j = 0; j < m_Resultsets.size(); j++) {
  400.       Resultset resultset = (Resultset) m_Resultsets.elementAt(j);
  401.       resultset.sort(m_RunColumn);
  402.     }
  403.     m_ResultsetsValid = true;
  404.   }
  405.   /**
  406.    * Gets the number of datasets in the resultsets
  407.    *
  408.    * @return the number of datasets in the resultsets
  409.    */
  410.   public int getNumDatasets() {
  411.     if (!m_ResultsetsValid) {
  412.       try {
  413. prepareData();
  414.       } catch (Exception ex) {
  415. ex.printStackTrace();
  416. return 0;
  417.       }
  418.     }
  419.     return m_DatasetSpecifiers.numSpecifiers();
  420.   }
  421.   /**
  422.    * Gets the number of resultsets in the data.
  423.    *
  424.    * @return the number of resultsets in the data
  425.    */
  426.   public int getNumResultsets() {
  427.     if (!m_ResultsetsValid) {
  428.       try {
  429. prepareData();
  430.       } catch (Exception ex) {
  431. ex.printStackTrace();
  432. return 0;
  433.       }
  434.     }
  435.     return m_Resultsets.size();
  436.   }
  437.   /**
  438.    * Gets a string descriptive of the specified resultset.
  439.    *
  440.    * @param index the index of the resultset
  441.    * @return a descriptive string for the resultset
  442.    */
  443.   public String getResultsetName(int index) {
  444.     if (!m_ResultsetsValid) {
  445.       try {
  446. prepareData();
  447.       } catch (Exception ex) {
  448. ex.printStackTrace();
  449. return null;
  450.       }
  451.     }
  452.     return ((Resultset) m_Resultsets.elementAt(index)).templateString();
  453.   }
  454.   
  455.   /**
  456.    * Computes a paired t-test comparison for a specified dataset between
  457.    * two resultsets.
  458.    *
  459.    * @param datasetSpecifier the dataset specifier
  460.    * @param resultset1Index the index of the first resultset
  461.    * @param resultset2Index the index of the second resultset
  462.    * @param comparisonColumn the column containing values to compare
  463.    * @return the results of the paired comparison
  464.    * @exception Exception if an error occurs
  465.    */
  466.   public PairedStats calculateStatistics(Instance datasetSpecifier,
  467.      int resultset1Index,
  468.      int resultset2Index,
  469.      int comparisonColumn) throws Exception {
  470.     if (m_Instances.attribute(comparisonColumn).type()
  471. != Attribute.NUMERIC) {
  472.       throw new Exception("Comparison column " + (comparisonColumn + 1)
  473.   + " ("
  474.   + m_Instances.attribute(comparisonColumn).name()
  475.   + ") is not numeric");
  476.     }
  477.     if (!m_ResultsetsValid) {
  478.       prepareData();
  479.     }
  480.     Resultset resultset1 = (Resultset) m_Resultsets.elementAt(resultset1Index);
  481.     Resultset resultset2 = (Resultset) m_Resultsets.elementAt(resultset2Index);
  482.     FastVector dataset1 = resultset1.dataset(datasetSpecifier);
  483.     FastVector dataset2 = resultset2.dataset(datasetSpecifier);
  484.     String datasetName = templateString(datasetSpecifier);
  485.     if (dataset1 == null) {
  486.       throw new Exception("No results for dataset=" + datasetName
  487.  + " for resultset=" + resultset1.templateString());
  488.     } else if (dataset2 == null) {
  489.       throw new Exception("No results for dataset=" + datasetName
  490.  + " for resultset=" + resultset2.templateString());
  491.     } else if (dataset1.size() != dataset2.size()) {
  492.       throw new Exception("Results for dataset=" + datasetName
  493.   + " differ in size for resultset="
  494.   + resultset1.templateString()
  495.   + " and resultset="
  496.   + resultset2.templateString()
  497.   );
  498.     }
  499.     
  500.     PairedStats pairedStats = new PairedStats(m_SignificanceLevel);
  501.     for (int k = 0; k < dataset1.size(); k ++) {
  502.       Instance current1 = (Instance) dataset1.elementAt(k);
  503.       Instance current2 = (Instance) dataset2.elementAt(k);
  504.       if (current1.isMissing(comparisonColumn)) {
  505. throw new Exception("Instance has missing value in comparison "
  506.     + "column!n" + current1);
  507.       }
  508.       if (current2.isMissing(comparisonColumn)) {
  509. throw new Exception("Instance has missing value in comparison "
  510.     + "column!n" + current2);
  511.       }
  512.       if (current1.value(m_RunColumn) != current2.value(m_RunColumn)) {
  513. System.err.println("Run numbers do not match!n"
  514.     + current1 + current2);
  515.       }
  516.       double value1 = current1.value(comparisonColumn);
  517.       double value2 = current2.value(comparisonColumn);
  518.       pairedStats.add(value1, value2);
  519.     }
  520.     pairedStats.calculateDerived();
  521.     return pairedStats;
  522.   }
  523.   
  524.   /**
  525.    * Creates a key that maps resultset numbers to their descriptions.
  526.    *
  527.    * @return a value of type 'String'
  528.    */
  529.   public String resultsetKey() {
  530.     if (!m_ResultsetsValid) {
  531.       try {
  532. prepareData();
  533.       } catch (Exception ex) {
  534. ex.printStackTrace();
  535. return ex.getMessage();
  536.       }
  537.     }
  538.     String result = "";
  539.     for (int j = 0; j < getNumResultsets(); j++) {
  540.       result += "(" + (j + 1) + ") " + getResultsetName(j) + 'n';
  541.     }
  542.     return result + 'n';
  543.   }
  544.   
  545.   /**
  546.    * Creates a "header" string describing the current resultsets.
  547.    *
  548.    * @param comparisonColumn a value of type 'int'
  549.    * @return a value of type 'String'
  550.    */
  551.   public String header(int comparisonColumn) {
  552.     if (!m_ResultsetsValid) {
  553.       try {
  554. prepareData();
  555.       } catch (Exception ex) {
  556. ex.printStackTrace();
  557. return ex.getMessage();
  558.       }
  559.     }
  560.     return "Analysing:  "
  561.       + m_Instances.attribute(comparisonColumn).name() + 'n'
  562.       + "Datasets:   " + getNumDatasets() + 'n'
  563.       + "Resultsets: " + getNumResultsets() + 'n'
  564.       + "Confidence: " + getSignificanceLevel() + " (two tailed)n"
  565.       + "Date:       " + (new SimpleDateFormat()).format(new Date()) + "nn";
  566.   }
  567.   /**
  568.    * Carries out a comparison between all resultsets, counting the number
  569.    * of datsets where one resultset outperforms the other.
  570.    *
  571.    * @param comparisonColumn the index of the comparison column
  572.    * @return a 2d array where element [i][j] is the number of times resultset
  573.    * j performed significantly better than resultset i.
  574.    * @exception Exception if an error occurs
  575.    */
  576.   public int [][] multiResultsetWins(int comparisonColumn)
  577.     throws Exception {
  578.     int numResultsets = getNumResultsets();
  579.     int [][] win = new int [numResultsets][numResultsets];
  580.     for (int i = 0; i < numResultsets; i++) {
  581.       for (int j = i + 1; j < numResultsets; j++) {
  582. System.err.print("Comparing (" + (i + 1) + ") with ("
  583.  + (j + 1) + ")r");
  584. System.err.flush();
  585. for (int k = 0; k < getNumDatasets(); k++) {
  586.   try {
  587.     PairedStats pairedStats = 
  588.       calculateStatistics(m_DatasetSpecifiers.specifier(k), i, j,
  589.   comparisonColumn);
  590.     if (pairedStats.differencesSignificance < 0) {
  591.       win[i][j]++;
  592.     } else if (pairedStats.differencesSignificance > 0) {
  593.       win[j][i]++;
  594.     }
  595.   } catch (Exception ex) {
  596.     ex.printStackTrace();
  597.     System.err.println(ex.getMessage());
  598.   }
  599. }
  600.       }
  601.     }
  602.     return win;
  603.   }
  604.   
  605.   /**
  606.    * Carries out a comparison between all resultsets, counting the number
  607.    * of datsets where one resultset outperforms the other. The results
  608.    * are summarized in a table.
  609.    *
  610.    * @param comparisonColumn the index of the comparison column
  611.    * @return the results in a string
  612.    * @exception Exception if an error occurs
  613.    */
  614.   public String multiResultsetSummary(int comparisonColumn)
  615.     throws Exception {
  616.     
  617.     int [][] win = multiResultsetWins(comparisonColumn);
  618.     int numResultsets = getNumResultsets();
  619.     int resultsetLength = 1 + Math.max((int)(Math.log(numResultsets)
  620.      / Math.log(10)),
  621.        (int)(Math.log(getNumDatasets()) / 
  622.      Math.log(10)));
  623.     String result = "";
  624.     String titles = "";
  625.     if (m_latexOutput) {
  626.       result += "\begin{table}[thb]n\caption{\label{labelname}"
  627.   +"Table Caption}n";
  628.       result += "\footnotesizen";
  629.       result += "{\centering \begin{tabular}{l";
  630.     }
  631.     for (int i = 0; i < numResultsets; i++) {
  632.       if (m_latexOutput) {
  633. titles += " &";
  634. result += "c";
  635.       }
  636.       titles += ' ' + Utils.padLeft("" + (char)((int)'a' + i % 26),
  637.     resultsetLength);
  638.     }
  639.     if (m_latexOutput) {
  640.       result += "}}\\n\hlinen";
  641.       result += titles + " \\n\hlinen";
  642.     } else {
  643.       result += titles + "  (No. of datasets where [col] >> [row])n";
  644.     }
  645.     for (int i = 0; i < numResultsets; i++) {
  646.       for (int j = 0; j < numResultsets; j++) {
  647. if (m_latexOutput && j == 0) {
  648.   result +=  (char)((int)'a' + i % 26);
  649. }
  650. if (j == i) {
  651.   if (m_latexOutput) {
  652.     result += " & - ";
  653.   } else {
  654.     result += ' ' + Utils.padLeft("-", resultsetLength);
  655.   }
  656. } else {
  657.   if (m_latexOutput) {
  658.     result += "& " + win[i][j] + ' ';
  659.   } else {
  660.     result += ' ' + Utils.padLeft("" + win[i][j], resultsetLength);
  661.   }
  662. }
  663.       }
  664.       if (!m_latexOutput) {
  665. result += " | " + (char)((int)'a' + i % 26)
  666.   + " = " + getResultsetName(i) + 'n';
  667.       } else {
  668. result += "\\n";
  669.       }
  670.     }
  671.     if (m_latexOutput) {
  672.       result += "\hlinen\end{tabular} \footnotesize \par}n\end{table}";
  673.     }
  674.     return result;
  675.   }
  676.   public String multiResultsetRanking(int comparisonColumn)
  677.     throws Exception {
  678.     int [][] win = multiResultsetWins(comparisonColumn);
  679.     int numResultsets = getNumResultsets();
  680.     int [] wins = new int [numResultsets];
  681.     int [] losses = new int [numResultsets];
  682.     int [] diff = new int [numResultsets];
  683.     for (int i = 0; i < win.length; i++) {
  684.       for (int j = 0; j < win[i].length; j++) {
  685. wins[j] += win[i][j];
  686. diff[j] += win[i][j];
  687. losses[i] += win[i][j];
  688. diff[i] -= win[i][j];
  689.       }
  690.     }
  691.     int biggest = Math.max(wins[Utils.maxIndex(wins)],
  692.    losses[Utils.maxIndex(losses)]);
  693.     int width = Math.max(2 + (int)(Math.log(biggest) / Math.log(10)),
  694.  ">-<".length());
  695.     String result;
  696.     if (m_latexOutput) {
  697.       result = "\begin{table}[thb]n\caption{\label{labelname}Table Caption"
  698. +"}n\footnotesizen{\centering \begin{tabular}{rlll}\\n\hlinen";
  699.       result += "Resultset & Wins$-$ & Wins & Losses \\n& Losses & & "
  700. +"\\n\hlinen";
  701.     } else {
  702.       result = Utils.padLeft(">-<", width) + ' '
  703. + Utils.padLeft(">", width) + ' '
  704. + Utils.padLeft("<", width) + " Resultsetn";
  705.     }
  706.     int [] ranking = Utils.sort(diff);
  707.     for (int i = numResultsets - 1; i >= 0; i--) {
  708.       int curr = ranking[i];
  709.       if (m_latexOutput) {
  710. result += "(" + (curr+1) + ") & " 
  711.   + Utils.padLeft("" + diff[curr], width) 
  712.   +" & " + Utils.padLeft("" + wins[curr], width)
  713.   +" & " + Utils.padLeft("" + losses[curr], width)
  714.   +"\\n";
  715.       } else {
  716. result += Utils.padLeft("" + diff[curr], width) + ' '
  717.   + Utils.padLeft("" + wins[curr], width) + ' '
  718.   + Utils.padLeft("" + losses[curr], width) + ' '
  719.   + getResultsetName(curr) + 'n';
  720.       }
  721.     }
  722.     if (m_latexOutput) {
  723.       result += "\hlinen\end{tabular} \footnotesize \par}n\end{table}";
  724.     }
  725.     return result;
  726.   }
  727.   /**
  728.    * Generates a comparison table in latex table format
  729.    *
  730.    * @param baseResultset the index of the base resultset
  731.    * @param comparisonColumn the index of the column to compare over
  732.    * @param maxWidthMean width for the mean
  733.    * @param maxWidthStdDev width for the standard deviation
  734.    * @return the comparison table string
  735.    */
  736.   private String multiResultsetFullLatex(int baseResultset,
  737.      int comparisonColumn,
  738.      int maxWidthMean,
  739.      int maxWidthStdDev) {
  740.     StringBuffer result = new StringBuffer(1000);
  741.     int numcols = getNumResultsets() * 2;
  742.     if (m_ShowStdDevs) {
  743.       numcols += getNumResultsets();
  744.     }
  745.     result.append("\begin{table}[thb]n\caption{\label{labelname}"
  746.   +"Table Caption}n");
  747.     if (!m_ShowStdDevs) {
  748.       result.append("\footnotesizen");
  749.     } else {
  750.       result.append("\scriptsizen");
  751.     }
  752.     // output the column alignment characters
  753.     // one for the dataset name and one for the comparison column
  754.     if (!m_ShowStdDevs) {
  755.       result.append("{\centering \begin{tabular}{ll");
  756.     } else {
  757.       // dataset, mean, std dev
  758.       result.append("{\centering \begin{tabular}{lr@{\hspace{0cm}}l");
  759.     }
  760.     for (int j = 0; j < getNumResultsets(); j++) {
  761.       if (j != baseResultset) {
  762. if (!m_ShowStdDevs) {
  763.   result.append("l@{\hspace{0.1cm}}l");
  764. } else {
  765.   result.append("r@{\hspace{0cm}}l@{\hspace{0cm}}r");
  766. }
  767.       }
  768.     }
  769.     result.append("}n\\n\hlinen");
  770.     if (!m_ShowStdDevs) {
  771.       result.append("Data Set & ("+(baseResultset+1)+")");
  772.     } else {
  773.       result.append("Data Set & \multicolumn{2}{c}{("+(baseResultset+1)+")}");
  774.     }
  775.     // now do the column names (numbers)
  776.     for (int j = 0; j < getNumResultsets(); j++) {
  777.       if (j != baseResultset) {
  778. if (!m_ShowStdDevs) {
  779.   result.append("& (" + (j + 1) + ") & ");
  780. } else {
  781.   result.append("& \multicolumn{3}{c}{(" + (j + 1) + ")} ");
  782. }
  783.       }
  784.     }
  785.     result.append("\\n\hlinen");
  786.     
  787.     int datasetLength = 25;
  788.     int resultsetLength = maxWidthMean + 7;
  789.     if (m_ShowStdDevs) {
  790.       resultsetLength += (maxWidthStdDev + 5);
  791.     }
  792.     for (int i = 0; i < getNumDatasets(); i++) {
  793.       // Print the name of the dataset
  794.       String datasetName = 
  795. templateString(m_DatasetSpecifiers.specifier(i)).replace('_','-');
  796.       try {
  797. PairedStats pairedStats = 
  798.   calculateStatistics(m_DatasetSpecifiers.specifier(i), 
  799.       baseResultset, baseResultset,
  800.       comparisonColumn);
  801. datasetName = Utils.padRight(datasetName, datasetLength);
  802. result.append(datasetName);
  803. if (!m_ShowStdDevs) {
  804.   result.append("& "+Utils.doubleToString(pairedStats.xStats.mean,
  805.        resultsetLength - 2, 2));
  806. } else {
  807.   result.append("& "+Utils.doubleToString(pairedStats.xStats.mean,
  808.      (maxWidthMean+5), 2)+"$\pm$");
  809.   if (Double.isNaN(pairedStats.xStats.stdDev)) {
  810.     result.append("&"+Utils.doubleToString(0.0,
  811.   (maxWidthStdDev+3),2)+" ");
  812.   } else {
  813.     result.append("&"+Utils.doubleToString(pairedStats.xStats.stdDev,
  814.    (maxWidthStdDev+3),2)+" ");
  815.   }
  816. }
  817. // Iterate over the resultsets
  818. for (int j = 0; j < getNumResultsets(); j++) {
  819.   if (j != baseResultset) {
  820.     try {
  821.       pairedStats = 
  822. calculateStatistics(m_DatasetSpecifiers.specifier(i), 
  823.     baseResultset, j, comparisonColumn);
  824.       String sigString = "";
  825.       if (pairedStats.differencesSignificance < 0) {
  826. sigString = "$\circ$";
  827.       } else if (pairedStats.differencesSignificance > 0) {
  828. sigString = "$\bullet$";
  829.       } 
  830.       if (!m_ShowStdDevs) {
  831. result.append(" & "+Utils.doubleToString(pairedStats.yStats.mean,
  832.    resultsetLength - 2,
  833.    2)).append(" & "+sigString);
  834.       } else {
  835. result.append(" & "
  836.       +Utils.doubleToString(pairedStats.yStats.mean,
  837.    (maxWidthMean+5),
  838.    2)+"$\pm$");
  839. if (Double.isNaN(pairedStats.yStats.stdDev)) {
  840.   result.append("&"+Utils.doubleToString(0.0, 
  841. (maxWidthStdDev+3),2)+" ");
  842. } else {
  843.   result.append("&"+Utils.doubleToString(pairedStats.
  844.   yStats.stdDev, (maxWidthStdDev+3),2)+" ");
  845. }
  846. result.append(" & ").append(sigString);
  847.       }
  848.     } catch (Exception ex) {
  849.       ex.printStackTrace();
  850.       result.append(Utils.padLeft("", resultsetLength + 1));
  851.     }
  852.   }
  853. }
  854. result.append("\\n");
  855.       } catch (Exception ex) {
  856. ex.printStackTrace();
  857.       }
  858.     }
  859.     result.append("\hlinen\multicolumn{"+numcols+"}{c}{$\circ$, $\bullet$"
  860.   +" statistically significant improvement or degradation}"
  861.   +"\\n\end{tabular} ");
  862.     if (!m_ShowStdDevs) {
  863.       result.append("\footnotesize ");
  864.       } else {
  865. result.append("\scriptsize ");
  866.       }
  867.     
  868.     result.append("\par}n\end{table}"
  869.   +"n");
  870.     System.out.println(result.toString()+"nn");
  871.     return result.toString();
  872.   }
  873.   /**
  874.    * Generates a comparison table in latex table format
  875.    *
  876.    * @param baseResultset the index of the base resultset
  877.    * @param comparisonColumn the index of the column to compare over
  878.    * @param maxWidthMean width for the mean
  879.    * @param maxWidthStdDev width for the standard deviation
  880.    * @return the comparison table string
  881.    */
  882.   private String multiResultsetFullPlainText(int baseResultset,
  883.                                              int comparisonColumn,
  884.                                              int maxWidthMean,
  885.                                              int maxWidthStdDev) {
  886.     StringBuffer result = new StringBuffer(1000);
  887.     int datasetLength = 25;
  888.     //    int resultsetLength = 9;
  889.     //    int resultsetLength = 16;
  890.     int resultsetLength = maxWidthMean + 7;
  891.     if (m_ShowStdDevs) {
  892.       resultsetLength += (maxWidthStdDev + 5);
  893.     }
  894.     // Set up the titles
  895.     StringBuffer titles = new StringBuffer(Utils.padRight("Dataset",
  896.                                                           datasetLength));
  897.     titles.append(' ');
  898.     StringBuffer label 
  899.       = new StringBuffer(Utils.padLeft("(" + (baseResultset + 1)
  900.                                        + ") "
  901.                                        + getResultsetName(baseResultset),
  902.                                        resultsetLength + 3));
  903.     titles.append(label);
  904.     StringBuffer separator = new StringBuffer(Utils.padRight("",
  905.                                                              datasetLength));
  906.     while (separator.length() < titles.length()) {
  907.       separator.append('-');
  908.     }
  909.     separator.append("---");
  910.     titles.append(" | ");
  911.     for (int j = 0; j < getNumResultsets(); j++) {
  912.       if (j != baseResultset) {
  913.         label = new StringBuffer(Utils.padLeft("(" + (j + 1) + ") "
  914.                                                + getResultsetName(j), resultsetLength));
  915.         titles.append(label).append(' ');
  916.         for (int i = 0; i < label.length(); i++) {
  917.           separator.append('-');
  918.         }
  919.         separator.append('-');
  920.       }
  921.     }
  922.     result.append(titles).append('n').append(separator).append('n');
  923.     
  924.     // Iterate over datasets
  925.     int [] win = new int [getNumResultsets()];
  926.     int [] loss = new int [getNumResultsets()];
  927.     int [] tie = new int [getNumResultsets()];
  928.     StringBuffer skipped = new StringBuffer("");
  929.     for (int i = 0; i < getNumDatasets(); i++) {
  930.       // Print the name of the dataset
  931.       String datasetName = 
  932.         templateString(m_DatasetSpecifiers.specifier(i));
  933.       try {
  934.         PairedStats pairedStats = 
  935.           calculateStatistics(m_DatasetSpecifiers.specifier(i), 
  936.                               baseResultset, baseResultset,
  937.                               comparisonColumn);
  938.         datasetName = Utils.padRight(datasetName, datasetLength);
  939.         result.append(datasetName);
  940.         result.append(Utils.padLeft('('
  941.                                     + Utils.doubleToString(pairedStats.count,
  942.                                                            0)
  943.                                     + ')', 5)).append(' ');
  944.         if (!m_ShowStdDevs) {
  945.           result.append(Utils.doubleToString(pairedStats.xStats.mean,
  946.                                              resultsetLength - 2, 2)).
  947.             append(" | ");
  948.         } else {
  949.           result.append(Utils.doubleToString(pairedStats.xStats.mean,
  950.                                              (maxWidthMean+5), 2));
  951.           if (Double.isInfinite(pairedStats.xStats.stdDev)) {
  952.             result.append('(' + Utils.padRight("Inf", maxWidthStdDev + 3)
  953.                           +')').append(" | ");
  954.           } else {
  955.             result.append('('+Utils.doubleToString(pairedStats.xStats.stdDev,
  956.                                                    (maxWidthStdDev+3),2)
  957.                           +')').append(" | ");
  958.           }
  959.         }
  960.         // Iterate over the resultsets
  961.         for (int j = 0; j < getNumResultsets(); j++) {
  962.           if (j != baseResultset) {
  963.             try {
  964.               pairedStats = 
  965.                 calculateStatistics(m_DatasetSpecifiers.specifier(i), 
  966.                                     baseResultset, j, comparisonColumn);
  967.               char sigChar = ' ';
  968.               if (pairedStats.differencesSignificance < 0) {
  969.                 sigChar = 'v';
  970.                 win[j]++;
  971.               } else if (pairedStats.differencesSignificance > 0) {
  972.                 sigChar = '*';
  973.                 loss[j]++;
  974.               } else {
  975.                 tie[j]++;
  976.               }
  977.               if (!m_ShowStdDevs) {
  978.                 result.append(Utils.doubleToString(pairedStats.yStats.mean,
  979.                                                    resultsetLength - 2,
  980.                                                    2)).append(' ')
  981.                   .append(sigChar).append(' ');
  982.               } else {
  983.                 result.append(Utils.doubleToString(pairedStats.yStats.mean,
  984.                                                    (maxWidthMean+5),
  985.                                                    2));
  986.                 if (Double.isInfinite(pairedStats.yStats.stdDev)) {
  987.                   result.append('(' 
  988.                                 + Utils.padRight("Inf", maxWidthStdDev + 3)
  989.                                 +')');
  990.                 } else {
  991.                   result.append('('+Utils.doubleToString(pairedStats.
  992.                                                          yStats.stdDev, 
  993.                                                          (maxWidthStdDev+3),
  994.                                                          2)+')');
  995.                 }
  996.                 result.append(' ').append(sigChar).append(' ');
  997.               }
  998.             } catch (Exception ex) {
  999.               ex.printStackTrace();
  1000.               result.append(Utils.padLeft("", resultsetLength + 1));
  1001.             }
  1002.           }
  1003.         }
  1004.         result.append('n');
  1005.       } catch (Exception ex) {
  1006.         ex.printStackTrace();
  1007.         skipped.append(datasetName).append(' ');
  1008.       }
  1009.     }
  1010.     result.append(separator).append('n');
  1011.     result.append(Utils.padLeft("(v/ /*)", datasetLength + 4 +
  1012.                                 resultsetLength)).append(" | ");
  1013.     for (int j = 0; j < getNumResultsets(); j++) {
  1014.       if (j != baseResultset) {
  1015.         result.append(Utils.padLeft("(" + win[j] + '/' + tie[j]
  1016.                                     + '/' + loss[j] + ')',
  1017.                                     resultsetLength)).append(' ');
  1018.       }
  1019.     }
  1020.     result.append('n');
  1021.     if (!skipped.equals("")) {
  1022.       result.append("Skipped: ").append(skipped).append('n');
  1023.     }
  1024.     return result.toString();
  1025.   }
  1026.     
  1027.   /**
  1028.    * Creates a comparison table where a base resultset is compared to the
  1029.    * other resultsets. Results are presented for every dataset.
  1030.    *
  1031.    * @param baseResultset the index of the base resultset
  1032.    * @param comparisonColumn the index of the column to compare over
  1033.    * @return the comparison table string
  1034.    * @exception Exception if an error occurs
  1035.    */
  1036.   public String multiResultsetFull(int baseResultset,
  1037.    int comparisonColumn) throws Exception {
  1038.     int maxWidthMean = 2;
  1039.     int maxWidthStdDev = 2;
  1040.      // determine max field width
  1041.     for (int i = 0; i < getNumDatasets(); i++) {
  1042.       for (int j = 0; j < getNumResultsets(); j++) {
  1043. try {
  1044.   PairedStats pairedStats = 
  1045.     calculateStatistics(m_DatasetSpecifiers.specifier(i), 
  1046. baseResultset, j, comparisonColumn);
  1047.           if (!Double.isInfinite(pairedStats.yStats.mean) &&
  1048.               !Double.isNaN(pairedStats.yStats.mean)) {
  1049.             double width = ((Math.log(Math.abs(pairedStats.yStats.mean)) / 
  1050.                              Math.log(10))+1);
  1051.             if (width > maxWidthMean) {
  1052.               maxWidthMean = (int)width;
  1053.             }
  1054.           }
  1055.   
  1056.   if (m_ShowStdDevs &&
  1057.               !Double.isInfinite(pairedStats.yStats.stdDev) &&
  1058.               !Double.isNaN(pairedStats.yStats.stdDev)) {
  1059.     double width = ((Math.log(Math.abs(pairedStats.yStats.stdDev)) / 
  1060.                              Math.log(10))+1);
  1061.     if (width > maxWidthStdDev) {
  1062.       maxWidthStdDev = (int)width;
  1063.     }
  1064.   }
  1065. }  catch (Exception ex) {
  1066.   ex.printStackTrace();
  1067. }
  1068.       }
  1069.     }
  1070.     StringBuffer result = new StringBuffer(1000);
  1071.     if (m_latexOutput) {
  1072.       result = new StringBuffer(multiResultsetFullLatex(baseResultset, 
  1073. comparisonColumn, 
  1074. maxWidthMean,
  1075. maxWidthStdDev));
  1076.     } else {
  1077.       result = new StringBuffer(multiResultsetFullPlainText(baseResultset, 
  1078.                                                             comparisonColumn, 
  1079.                                                             maxWidthMean,
  1080.                                                             maxWidthStdDev));
  1081.     }
  1082.     // append a key so that we can tell the difference between long
  1083.     // scheme+option names
  1084.     result.append("nKey:nn");
  1085.     for (int j = 0; j < getNumResultsets(); j++) {
  1086.       result.append("("+(j+1)+") ");
  1087.       result.append(getResultsetName(j)+"n");
  1088.     }
  1089.     return result.toString();
  1090.   }
  1091.   /**
  1092.    * Lists options understood by this object.
  1093.    *
  1094.    * @return an enumeration of Options.
  1095.    */
  1096.   public Enumeration listOptions() {
  1097.     
  1098.     Vector newVector = new Vector(5);
  1099.     newVector.addElement(new Option(
  1100.              "tSpecify list of columns that specify a uniquen"
  1101.       + "tdataset.n"
  1102.       + "tFirst and last are valid indexes. (default none)",
  1103.               "D", 1, "-D <index,index2-index4,...>"));
  1104.     newVector.addElement(new Option(
  1105.       "tSet the index of the column containing the run number",
  1106.               "R", 1, "-R <index>"));
  1107.     newVector.addElement(new Option(
  1108.               "tSpecify list of columns that specify a uniquen"
  1109.       + "t'result generator' (eg: classifier name and options).n"
  1110.       + "tFirst and last are valid indexes. (default none)",
  1111.               "G", 1, "-G <index1,index2-index4,...>"));
  1112.     newVector.addElement(new Option(
  1113.       "tSet the significance level for comparisons (default 0.05)",
  1114.               "S", 1, "-S <significance level>"));
  1115.     newVector.addElement(new Option(
  1116.       "tShow standard deviations",
  1117.               "V", 0, "-V"));
  1118.     newVector.addElement(new Option(
  1119.       "tProduce table comparisons in Latex table format",
  1120.               "L", 0, "-L"));
  1121.     return newVector.elements();
  1122.   }
  1123.   /**
  1124.    * Parses a given list of options. Valid options are:<p>
  1125.    *
  1126.    * -D num,num2... <br>
  1127.    * The column numbers that uniquely specify a dataset.
  1128.    * (default last) <p>
  1129.    *
  1130.    * -R num <br>
  1131.    * The column number containing the run number.
  1132.    * (default last) <p>
  1133.    *
  1134.    * -S num <br>
  1135.    * The significance level for T-Tests.
  1136.    * (default 0.05) <p>
  1137.    *
  1138.    * -R num,num2... <br>
  1139.    * The column numbers that uniquely specify one result generator (eg:
  1140.    * scheme name plus options).
  1141.    * (default last) <p>
  1142.    *
  1143.    * -V <br>
  1144.    * Show standard deviations <p>
  1145.    *
  1146.    * -L <br>
  1147.    * Produce comparison tables in Latex table format <p>
  1148.    *
  1149.    * @param options an array containing options to set.
  1150.    * @exception Exception if invalid options are given
  1151.    */
  1152.   public void setOptions(String[] options) throws Exception {
  1153.     setShowStdDevs(Utils.getFlag('V', options));
  1154.     setProduceLatex(Utils.getFlag('L', options));
  1155.     String datasetList = Utils.getOption('D', options);
  1156.     Range datasetRange = new Range();
  1157.     if (datasetList.length() != 0) {
  1158.       datasetRange.setRanges(datasetList);
  1159.     }
  1160.     setDatasetKeyColumns(datasetRange);
  1161.     String indexStr = Utils.getOption('R', options);
  1162.     if (indexStr.length() != 0) {
  1163.       if (indexStr.equals("first")) {
  1164. setRunColumn(0);
  1165.       } else if (indexStr.equals("last")) {
  1166. setRunColumn(-1);
  1167.       } else {
  1168. setRunColumn(Integer.parseInt(indexStr) - 1);
  1169.       }    
  1170.     } else {
  1171.       setRunColumn(-1);
  1172.     }
  1173.     String sigStr = Utils.getOption('S', options);
  1174.     if (sigStr.length() != 0) {
  1175.       setSignificanceLevel((new Double(sigStr)).doubleValue());
  1176.     } else {
  1177.       setSignificanceLevel(0.05);
  1178.     }
  1179.     
  1180.     String resultsetList = Utils.getOption('G', options);
  1181.     Range generatorRange = new Range();
  1182.     if (resultsetList.length() != 0) {
  1183.       generatorRange.setRanges(resultsetList);
  1184.     }
  1185.     setResultsetKeyColumns(generatorRange);
  1186.   }
  1187.   
  1188.   /**
  1189.    * Gets current settings of the PairedTTester.
  1190.    *
  1191.    * @return an array of strings containing current options.
  1192.    */
  1193.   public String[] getOptions() {
  1194.     String [] options = new String [10];
  1195.     int current = 0;
  1196.     if (!getResultsetKeyColumns().getRanges().equals("")) {
  1197.       options[current++] = "-G";
  1198.       options[current++] = getResultsetKeyColumns().getRanges();
  1199.     }
  1200.     if (!getDatasetKeyColumns().getRanges().equals("")) {
  1201.       options[current++] = "-D";
  1202.       options[current++] = getDatasetKeyColumns().getRanges();
  1203.     }
  1204.     options[current++] = "-R";
  1205.     options[current++] = "" + (getRunColumn() + 1);
  1206.     options[current++] = "-S";
  1207.     options[current++] = "" + getSignificanceLevel();
  1208.     
  1209.     if (getShowStdDevs()) {
  1210.       options[current++] = "-V";
  1211.     }
  1212.     if (getProduceLatex()) {
  1213.       options[current++] = "-L";
  1214.     }
  1215.     while (current < options.length) {
  1216.       options[current++] = "";
  1217.     }
  1218.     return options;
  1219.   }
  1220.   /**
  1221.    * Get the value of ResultsetKeyColumns.
  1222.    *
  1223.    * @return Value of ResultsetKeyColumns.
  1224.    */
  1225.   public Range getResultsetKeyColumns() {
  1226.     
  1227.     return m_ResultsetKeyColumnsRange;
  1228.   }
  1229.   
  1230.   /**
  1231.    * Set the value of ResultsetKeyColumns.
  1232.    *
  1233.    * @param newResultsetKeyColumns Value to assign to ResultsetKeyColumns.
  1234.    */
  1235.   public void setResultsetKeyColumns(Range newResultsetKeyColumns) {
  1236.     
  1237.     m_ResultsetKeyColumnsRange = newResultsetKeyColumns;
  1238.     m_ResultsetsValid = false;
  1239.   }
  1240.   
  1241.   /**
  1242.    * Get the value of SignificanceLevel.
  1243.    *
  1244.    * @return Value of SignificanceLevel.
  1245.    */
  1246.   public double getSignificanceLevel() {
  1247.     
  1248.     return m_SignificanceLevel;
  1249.   }
  1250.   
  1251.   /**
  1252.    * Set the value of SignificanceLevel.
  1253.    *
  1254.    * @param newSignificanceLevel Value to assign to SignificanceLevel.
  1255.    */
  1256.   public void setSignificanceLevel(double newSignificanceLevel) {
  1257.     
  1258.     m_SignificanceLevel = newSignificanceLevel;
  1259.   }
  1260.   /**
  1261.    * Get the value of DatasetKeyColumns.
  1262.    *
  1263.    * @return Value of DatasetKeyColumns.
  1264.    */
  1265.   public Range getDatasetKeyColumns() {
  1266.     
  1267.     return m_DatasetKeyColumnsRange;
  1268.   }
  1269.   
  1270.   /**
  1271.    * Set the value of DatasetKeyColumns.
  1272.    *
  1273.    * @param newDatasetKeyColumns Value to assign to DatasetKeyColumns.
  1274.    */
  1275.   public void setDatasetKeyColumns(Range newDatasetKeyColumns) {
  1276.     
  1277.     m_DatasetKeyColumnsRange = newDatasetKeyColumns;
  1278.     m_ResultsetsValid = false;
  1279.   }
  1280.   
  1281.   /**
  1282.    * Get the value of RunColumn.
  1283.    *
  1284.    * @return Value of RunColumn.
  1285.    */
  1286.   public int getRunColumn() {
  1287.     
  1288.     return m_RunColumnSet;
  1289.   }
  1290.   
  1291.   /**
  1292.    * Set the value of RunColumn.
  1293.    *
  1294.    * @param newRunColumn Value to assign to RunColumn.
  1295.    */
  1296.   public void setRunColumn(int newRunColumn) {
  1297.     
  1298.     m_RunColumnSet = newRunColumn;
  1299.   }
  1300.   
  1301.   /**
  1302.    * Get the value of Instances.
  1303.    *
  1304.    * @return Value of Instances.
  1305.    */
  1306.   public Instances getInstances() {
  1307.     
  1308.     return m_Instances;
  1309.   }
  1310.   
  1311.   /**
  1312.    * Set the value of Instances.
  1313.    *
  1314.    * @param newInstances Value to assign to Instances.
  1315.    */
  1316.   public void setInstances(Instances newInstances) {
  1317.     
  1318.     m_Instances = newInstances;
  1319.     m_ResultsetsValid = false;
  1320.   }
  1321.   
  1322.   /**
  1323.    * Test the class from the command line.
  1324.    *
  1325.    * @param args contains options for the instance ttests
  1326.    */
  1327.   public static void main(String args[]) {
  1328.     try {
  1329.       PairedTTester tt = new PairedTTester();
  1330.       String datasetName = Utils.getOption('t', args);
  1331.       String compareColStr = Utils.getOption('c', args);
  1332.       String baseColStr = Utils.getOption('b', args);
  1333.       boolean summaryOnly = Utils.getFlag('s', args);
  1334.       boolean rankingOnly = Utils.getFlag('r', args);
  1335.       try {
  1336. if ((datasetName.length() == 0)
  1337.     || (compareColStr.length() == 0)) {
  1338.   throw new Exception("-t and -c options are required");
  1339. }
  1340. tt.setOptions(args);
  1341. Utils.checkForRemainingOptions(args);
  1342.       } catch (Exception ex) {
  1343. String result = "";
  1344. Enumeration enum = tt.listOptions();
  1345. while (enum.hasMoreElements()) {
  1346.   Option option = (Option) enum.nextElement();
  1347.   result += option.synopsis() + 'n'
  1348.     + option.description() + 'n';
  1349. }
  1350. throw new Exception(
  1351.       "Usage:nn"
  1352.       + "-t <file>n"
  1353.       + "tSet the dataset containing data to evaluaten"
  1354.       + "-b <index>n"
  1355.       + "tSet the resultset to base comparisons against (optional)n"
  1356.       + "-c <index>n"
  1357.       + "tSet the column to perform a comparison onn"
  1358.       + "-sn"
  1359.       + "tSummarize wins over all resultset pairsnn"
  1360.       + "-rn"
  1361.       + "tGenerate a resultset rankingnn"
  1362.       + result);
  1363.       }
  1364.       Instances data = new Instances(new BufferedReader(
  1365.   new FileReader(datasetName)));
  1366.       tt.setInstances(data);
  1367.       //      tt.prepareData();
  1368.       int compareCol = Integer.parseInt(compareColStr) - 1;
  1369.       System.out.println(tt.header(compareCol));
  1370.       if (rankingOnly) {
  1371. System.out.println(tt.multiResultsetRanking(compareCol));
  1372.       } else if (summaryOnly) {
  1373. System.out.println(tt.multiResultsetSummary(compareCol));
  1374.       } else {
  1375. System.out.println(tt.resultsetKey());
  1376. if (baseColStr.length() == 0) {
  1377.   for (int i = 0; i < tt.getNumResultsets(); i++) {
  1378.     System.out.println(tt.multiResultsetFull(i, compareCol));
  1379.   }
  1380. } else {
  1381.   int baseCol = Integer.parseInt(baseColStr) - 1;
  1382.   System.out.println(tt.multiResultsetFull(baseCol, compareCol));
  1383. }
  1384.       }
  1385.     } catch(Exception e) {
  1386.       e.printStackTrace();
  1387.       System.err.println(e.getMessage());
  1388.     }
  1389.   }
  1390. }