Clover coverage report - baseCode - 0.2.5 Coverage timestamp: Tue Apr 12 2005 11:31:58 EDT FRAMES NO FRAMES |
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% |

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 |  |