Clover coverage report - baseCode - 0.2.5
Coverage timestamp: Tue Apr 12 2005 11:31:58 EDT
file stats: LOC: 449   Methods: 31
NCLOC: 270   Classes: 1
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
ColorMatrix.java 0% 0% 0% 0%
coverage
 1   
 package baseCode.gui;
 2   
 
 3   
 import java.awt.Color;
 4   
 import java.io.IOException;
 5   
 
 6   
 import baseCode.dataStructure.matrix.AbstractNamedDoubleMatrix;
 7   
 import baseCode.dataStructure.matrix.DenseDoubleMatrix2DNamed;
 8   
 import baseCode.io.reader.DoubleMatrixReader;
 9   
 import baseCode.math.DescriptiveWithMissing;
 10   
 import baseCode.math.MatrixStats;
 11   
 import cern.colt.list.DoubleArrayList;
 12   
 
 13   
 /**
 14   
  * <p>
 15   
  * Title: ColorMatrix
 16   
  * </p>
 17   
  * <p>
 18   
  * Description: Creates a color matrix from a matrix of doubles
 19   
  * </p>
 20   
  * <p>
 21   
  * Copyright (c) 2004
 22   
  * </p>
 23   
  * <p>
 24   
  * Institution:: Columbia University
 25   
  * </p>
 26   
  * 
 27   
  * @author Will Braynen
 28   
  * @version $Id: ColorMatrix.java,v 1.42 2004/09/20 22:19:02 pavlidis Exp $
 29   
  */
 30   
 public class ColorMatrix implements Cloneable {
 31   
 
 32   
    // data fields
 33   
 
 34   
    /**
 35   
     * Min and max values to display, which might not be the actual min and max values in the matrix. For instance, we
 36   
     * might want to clip values, or show a bigger color range for equal comparison with other rows or matrices.
 37   
     */
 38   
    protected double m_displayMin;
 39   
    protected double m_displayMax;
 40   
 
 41   
    protected double m_min;
 42   
    protected double m_max;
 43   
 
 44   
    protected Color[][] m_colors;
 45   
    protected Color m_missingColor = Color.lightGray;
 46   
    protected Color[] m_colorMap = ColorMap.BLACKBODY_COLORMAP;
 47   
 
 48   
    protected AbstractNamedDoubleMatrix m_matrix;
 49   
    protected DoubleMatrixReader m_matrixReader;
 50   
 
 51   
    protected int m_totalRows, m_totalColumns;
 52   
 
 53   
    /** to be able to sort the rows by an arbitrary key */
 54   
    protected int m_rowKeys[];
 55   
 
 56   
    /**
 57   
     * @param filename either an absolute path, or if providing a relative path (e.g. data.txt), then keep in mind that
 58   
     *        it will be relative to the java interpreter, not the class (not my fault -- that's how java treats relative
 59   
     *        paths)
 60   
     * @throws IOException
 61   
     */
 62  0
    public ColorMatrix( String filename ) throws IOException {
 63  0
       loadMatrixFromFile( filename );
 64   
    }
 65   
 
 66  0
    public ColorMatrix( DenseDoubleMatrix2DNamed matrix ) {
 67  0
       init( matrix );
 68   
    }
 69   
 
 70   
    /**
 71   
     * @param filename data filename
 72   
     * @param colorMap the simplest color map is one with just two colors: { minColor, maxColor }
 73   
     * @param missingColor values missing from the matrix or non-numeric entries will be displayed using this color
 74   
     * @throws IOException
 75   
     */
 76  0
    public ColorMatrix( String filename, Color[] colorMap, Color missingColor )
 77   
          throws IOException {
 78   
 
 79  0
       m_missingColor = missingColor;
 80  0
       m_colorMap = colorMap;
 81  0
       loadMatrixFromFile( filename );
 82   
    }
 83   
 
 84   
    /**
 85   
     * @param matrix the matrix
 86   
     * @param colorMap the simplest color map is one with just two colors: { minColor, maxColor }
 87   
     * @param missingColor values missing from the matrix or non-numeric entries will be displayed using this color
 88   
     */
 89  0
    public ColorMatrix( AbstractNamedDoubleMatrix matrix, Color[] colorMap,
 90   
          Color missingColor ) {
 91   
 
 92  0
       m_missingColor = missingColor;
 93  0
       m_colorMap = colorMap;
 94  0
       init( matrix );
 95   
    }
 96   
 
 97  0
    public int getRowCount() {
 98  0
       return m_totalRows;
 99   
    }
 100   
 
 101  0
    public int getColumnCount() {
 102  0
       return m_totalColumns;
 103   
    }
 104   
 
 105  0
    protected int getTrueRowIndex( int row ) {
 106  0
       return m_rowKeys[row];
 107   
    }
 108   
 
 109  0
    public double getValue( int row, int column )
 110   
          throws ArrayIndexOutOfBoundsException {
 111   
 
 112  0
       if ( row >= m_totalRows )
 113  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 114   
                   + m_totalRows
 115   
                   + " rows, so the maximum possible row index is "
 116   
                   + ( m_totalRows - 1 ) + ". Row index " + row
 117   
                   + " is too high." );
 118  0
       if ( column >= m_totalColumns )
 119  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 120   
                   + m_totalColumns
 121   
                   + " columns, so the maximum possible column index is "
 122   
                   + ( m_totalColumns - 1 ) + ". Column index " + column
 123   
                   + " is too high." );
 124   
 
 125  0
       row = getTrueRowIndex( row );
 126  0
       return m_matrix.get( row, column );
 127   
    }
 128   
 
 129  0
    public double[] getRow( int row ) throws ArrayIndexOutOfBoundsException {
 130   
 
 131  0
       if ( row >= m_totalRows )
 132  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 133   
                   + m_totalRows
 134   
                   + " rows, so the maximum possible row index is "
 135   
                   + ( m_totalRows - 1 ) + ". Row index " + row
 136   
                   + " is too high." );
 137   
 
 138  0
       row = getTrueRowIndex( row );
 139  0
       return m_matrix.getRow( row );
 140   
    }
 141   
 
 142  0
    public double[] getRowByName( String rowName ) {
 143  0
       return m_matrix.getRowByName( rowName );
 144   
    }
 145   
 
 146  0
    public Color getColor( int row, int column )
 147   
          throws ArrayIndexOutOfBoundsException {
 148   
 
 149  0
       if ( row >= m_totalRows )
 150  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 151   
                   + m_totalRows
 152   
                   + " rows, so the maximum possible row index is "
 153   
                   + ( m_totalRows - 1 ) + ". Row index " + row
 154   
                   + " is too high." );
 155  0
       if ( column >= m_totalColumns )
 156  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 157   
                   + m_totalColumns
 158   
                   + " columns, so the maximum possible column index is "
 159   
                   + ( m_totalColumns - 1 ) + ". Column index " + column
 160   
                   + " is too high." );
 161   
 
 162  0
       row = getTrueRowIndex( row );
 163  0
       return m_colors[row][column];
 164   
    }
 165   
 
 166  0
    public void setColor( int row, int column, Color newColor )
 167   
          throws ArrayIndexOutOfBoundsException {
 168   
 
 169  0
       if ( row >= m_totalRows )
 170  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 171   
                   + m_totalRows
 172   
                   + " rows, so the maximum possible row index is "
 173   
                   + ( m_totalRows - 1 ) + ". Row index " + row
 174   
                   + " is too high." );
 175  0
       if ( column >= m_totalColumns )
 176  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 177   
                   + m_totalColumns
 178   
                   + " columns, so the maximum possible column index is "
 179   
                   + ( m_totalColumns - 1 ) + ". Column index " + column
 180   
                   + " is too high." );
 181   
 
 182  0
       row = getTrueRowIndex( row );
 183  0
       m_colors[row][column] = newColor;
 184   
    }
 185   
 
 186  0
    public String getRowName( int row ) throws ArrayIndexOutOfBoundsException {
 187   
 
 188  0
       if ( row >= m_totalRows )
 189  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 190   
                   + m_totalRows
 191   
                   + " rows, so the maximum possible row index is "
 192   
                   + ( m_totalRows - 1 ) + ". Row index " + row
 193   
                   + " is too high." );
 194   
 
 195  0
       row = getTrueRowIndex( row );
 196  0
       return m_matrix.getRowName( row );
 197   
    }
 198   
 
 199  0
    public String getColumnName( int column )
 200   
          throws ArrayIndexOutOfBoundsException {
 201   
 
 202  0
       if ( column >= m_totalColumns )
 203  0
             throw new ArrayIndexOutOfBoundsException( "The matrix has only "
 204   
                   + m_totalColumns
 205   
                   + " columns, so the maximum possible column index is "
 206   
                   + ( m_totalColumns - 1 ) + ". Column index " + column
 207   
                   + " is too high." );
 208   
 
 209  0
       return m_matrix.getColName( column );
 210   
    }
 211   
 
 212  0
    public String[] getRowNames() {
 213  0
       String[] rowNames = new String[m_totalRows];
 214  0
       for ( int i = 0; i < m_totalRows; i++ ) {
 215  0
          int row = getTrueRowIndex( i );
 216  0
          rowNames[i] = getRowName( row );
 217   
       }
 218  0
       return rowNames;
 219   
    }
 220   
 
 221  0
    public String[] getColumnNames() {
 222  0
       String[] columnNames = new String[m_totalColumns];
 223  0
       for ( int i = 0; i < m_totalColumns; i++ ) {
 224  0
          columnNames[i] = getColumnName( i );
 225   
       }
 226  0
       return columnNames;
 227   
    }
 228   
 
 229  0
    public int getRowIndexByName( String rowName ) {
 230  0
       return m_matrix.getRowIndexByName( rowName );
 231   
    }
 232   
 
 233   
    /**
 234   
     * Changes values in a row, clipping if there are more values than columns.
 235   
     * 
 236   
     * @param row row whose values we want to change
 237   
     * @param values new row values
 238   
     */
 239  0
    protected void setRow( int row, double values[] ) {
 240   
 
 241  0
       row = getTrueRowIndex( row );
 242   
 
 243   
       // clip if we have more values than columns
 244  0
       int totalValues = Math.min( values.length, m_totalColumns );
 245   
 
 246  0
       for ( int column = 0; column < totalValues; column++ ) {
 247  0
          m_matrix.set( row, column, values[column] );
 248   
 
 249   
       }
 250   
    } // end setRow
 251   
 
 252   
    /**
 253   
     * To be able to sort the rows by an arbitrary key. Creates <code>m_rowKeys</code> array and initializes it in
 254   
     * ascending order from 0 to <code>m_totalRows</code> -1, so that by default it matches the physical order of the
 255   
     * columns: [0,1,2,...,m_totalRows-1]
 256   
     * 
 257   
     * @return int[]
 258   
     */
 259  0
    protected int[] createRowKeys() {
 260  0
       m_rowKeys = new int[m_totalRows];
 261  0
       for ( int i = 0; i < m_totalRows; i++ ) {
 262  0
          m_rowKeys[i] = i;
 263   
       }
 264  0
       return m_rowKeys;
 265   
    }
 266   
 
 267  0
    public void setRowKeys( int[] rowKeys ) {
 268  0
       m_rowKeys = rowKeys;
 269   
    }
 270   
 
 271  0
    public void resetRowKeys() {
 272  0
       for ( int i = 0; i < m_totalRows; i++ ) {
 273  0
          m_rowKeys[i] = i;
 274   
       }
 275   
    }
 276   
 
 277  0
    public void init( AbstractNamedDoubleMatrix matrix ) {
 278   
 
 279  0
       m_matrix = matrix; // by reference, or should we clone?
 280  0
       m_totalRows = m_matrix.rows();
 281  0
       m_totalColumns = m_matrix.columns();
 282  0
       m_colors = new Color[m_totalRows][m_totalColumns];
 283  0
       createRowKeys();
 284   
 
 285  0
       m_displayMin = m_min = MatrixStats.min( m_matrix );
 286  0
       m_displayMax = m_max = MatrixStats.max( m_matrix );
 287   
 
 288   
       // map values to colors
 289  0
       mapValuesToColors();
 290   
    }
 291   
 
 292   
    /**
 293   
     * A convenience method for loading data files
 294   
     * 
 295   
     * @param filename the name of the data file
 296   
     * @throws IOException
 297   
     */
 298  0
    public void loadMatrixFromFile( String filename ) throws IOException {
 299   
 
 300  0
       m_matrixReader = new DoubleMatrixReader();
 301  0
       DenseDoubleMatrix2DNamed matrix = ( DenseDoubleMatrix2DNamed ) m_matrixReader
 302   
             .read( filename );
 303  0
       init( matrix );
 304   
    }
 305   
 
 306   
    /**
 307   
     * Normalizes the elements of a matrix to variance one and mean zero, ignoring missing values todo move this to
 308   
     * matrixstats or something.
 309   
     */
 310  0
    public void standardize() {
 311   
 
 312   
       // normalize the data in each row
 313  0
       for ( int r = 0; r < m_totalRows; r++ ) {
 314  0
          double[] rowValues = getRow( r );
 315  0
          DoubleArrayList doubleArrayList = new cern.colt.list.DoubleArrayList(
 316   
                rowValues );
 317  0
          DescriptiveWithMissing.standardize( doubleArrayList );
 318  0
          rowValues = doubleArrayList.elements();
 319  0
          setRow( r, rowValues );
 320   
       }
 321   
 
 322  0
       m_displayMin = -2;
 323  0
       m_displayMax = +2;
 324   
 
 325  0
       mapValuesToColors();
 326   
 
 327   
    } // end standardize
 328   
 
 329   
    /**
 330   
     * @return a DenseDoubleMatrix2DNamed object
 331   
     */
 332  0
    public AbstractNamedDoubleMatrix getMatrix() {
 333  0
       return m_matrix;
 334   
    }
 335   
 
 336   
    //
 337   
    // Standardized display range
 338   
    //
 339  0
    public void setDisplayRange( double min, double max ) {
 340   
 
 341  0
       m_displayMin = min;
 342  0
       m_displayMax = max;
 343   
 
 344  0
       mapValuesToColors();
 345   
    }
 346   
 
 347  0
    public double getDisplayMin() {
 348  0
       return m_displayMin;
 349   
    }
 350   
 
 351  0
    public double getDisplayMax() {
 352  0
       return m_displayMax;
 353   
    }
 354   
 
 355   
    /**
 356   
     * @param colorMap an array of colors which define the midpoints in the color map; this can be one of the constants
 357   
     *        defined in the ColorMap class, like ColorMap.REDGREEN_COLORMAP and ColorMap.BLACKBODY_COLORMAP
 358   
     * @throws IllegalArgumentException if the colorMap array argument contains less than two colors.
 359   
     */
 360  0
    public void setColorMap( Color[] colorMap ) throws IllegalArgumentException {
 361   
 
 362  0
       if ( colorMap.length < 2 ) {
 363  0
          throw new IllegalArgumentException();
 364   
       }
 365   
 
 366  0
       m_colorMap = colorMap;
 367  0
       mapValuesToColors();
 368   
    }
 369   
 
 370  0
    public void mapValuesToColors() {
 371  0
       ColorMap colorMap = new ColorMap( m_colorMap );
 372  0
       double range = m_displayMax - m_displayMin;
 373   
 
 374  0
       if ( 0.0 == range ) {
 375   
          // This is not an exception, just a warning, so no exception to throw
 376  0
          System.err.println( "Warning: range of values in data is zero." );
 377  0
          range = 1.0; // This avoids getting a step size of zero
 378   
          // in case all values in the matrix are equal.
 379   
       }
 380   
 
 381   
       // zoom factor for stretching or shrinking the range
 382  0
       double zoomFactor = ( colorMap.getPaletteSize() - 1 ) / range;
 383   
 
 384   
       // map values to colors
 385  0
       for ( int row = 0; row < m_totalRows; row++ ) {
 386  0
          for ( int column = 0; column < m_totalColumns; column++ ) {
 387  0
             double value = getValue( row, column );
 388   
 
 389  0
             if ( Double.isNaN( value ) ) {
 390   
                // the value is missing
 391  0
                m_colors[row][column] = m_missingColor;
 392   
             } else {
 393   
                // clip extreme values (this makes sense for normalized
 394   
                // values because then for a standard deviation of one and
 395   
                // mean zero, we set m_minValue = -2 and m_maxValue = 2,
 396   
                // even though there could be a few extreme values
 397   
                // outside this range (right?)
 398  0
                if ( value > m_displayMax ) {
 399   
                   // clip extremely large values
 400  0
                   value = m_displayMax;
 401  0
                } else if ( value < m_displayMin ) {
 402   
                   // clip extremely small values
 403  0
                   value = m_displayMin;
 404   
                }
 405   
 
 406   
                // shift the minimum value to zero
 407   
                // to the range [0, maxValue + minValue]
 408  0
                value -= m_displayMin;
 409   
 
 410   
                // stretch or shrink the range to [0, totalColors]
 411  0
                double valueNew = value * zoomFactor;
 412  0
                int i = ( int ) Math.round( valueNew );
 413  0
                m_colors[row][column] = colorMap.getColor( i );
 414   
             }
 415   
          }
 416   
       }
 417   
    } // end mapValuesToColors
 418   
 
 419  0
    public Object clone() {
 420   
       // create another double matrix
 421  0
       DenseDoubleMatrix2DNamed matrix = new DenseDoubleMatrix2DNamed(
 422   
             m_totalRows, m_totalColumns );
 423   
       // copy the row and column names
 424  0
       for ( int i = 0; i < m_totalRows; i++ ) {
 425  0
          matrix.addRowName( m_matrix.getRowName( i ), i );
 426   
       }
 427  0
       for ( int i = 0; i < m_totalColumns; i++ ) {
 428  0
          matrix.addColumnName( m_matrix.getColName( i ), i );
 429   
          // copy the data
 430   
       }
 431  0
       for ( int r = 0; r < m_totalRows; r++ ) {
 432  0
          for ( int c = 0; c < m_totalColumns; c++ ) {
 433  0
             matrix.set( r, c, m_matrix.get( r, c ) );
 434   
          }
 435   
       }
 436   
 
 437   
       // create another copy of a color matrix (this class)
 438  0
       ColorMatrix clonedColorMatrix = new ColorMatrix( matrix, m_colorMap,
 439   
             m_missingColor );
 440   
 
 441  0
       int[] rowKeys = ( int[] ) m_rowKeys.clone();
 442  0
       clonedColorMatrix.setRowKeys( rowKeys );
 443   
 
 444  0
       return clonedColorMatrix;
 445   
 
 446   
    } // end clone
 447   
 
 448   
 } // end class ColorMatrix
 449