1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package ubic.basecode.graphics;
20
21 import java.awt.Color;
22
23 import ubic.basecode.dataStructure.matrix.DenseDoubleMatrix;
24 import ubic.basecode.dataStructure.matrix.DoubleMatrix;
25 import ubic.basecode.io.reader.DoubleMatrixReader;
26 import ubic.basecode.math.Constants;
27 import ubic.basecode.math.DescriptiveWithMissing;
28 import ubic.basecode.math.MatrixStats;
29 import cern.colt.list.DoubleArrayList;
30
31
32
33
34
35
36
37 public class ColorMatrix<A, B> implements Cloneable {
38
39
40
41 public static <R, C> ColorMatrix<R, C> newInstance( DoubleMatrix<R, C> matrix ) {
42 return new ColorMatrix<R, C>( matrix );
43 }
44
45 protected Color[] colorMap = ColorMap.BLACKBODY_COLORMAP;
46
47 protected Color[][] colors;
48 protected double displayMax;
49
50
51
52
53
54 protected double displayMin;
55 protected DoubleMatrixReader m_matrixReader;
56
57 protected int m_rowKeys[];
58
59 protected int m_totalRows, m_totalColumns;
60 protected double max;
61
62 protected DoubleMatrix<A, B> maxtrix;
63
64 protected double min;
65
66 protected Color missingColor = Color.lightGray;
67
68 public ColorMatrix( DoubleMatrix<A, B> matrix ) {
69 init( matrix );
70 }
71
72
73
74
75
76
77 public ColorMatrix( DoubleMatrix<A, B> matrix, Color[] colorMap, Color missingColor ) {
78 this.missingColor = missingColor;
79 this.colorMap = colorMap;
80 init( matrix );
81 }
82
83 @Override
84 public ColorMatrix<A, B> clone() {
85
86 try {
87 super.clone();
88 } catch ( CloneNotSupportedException e ) {
89 }
90
91
92 DenseDoubleMatrix<A, B> matrix = new DenseDoubleMatrix<A, B>( m_totalRows, m_totalColumns );
93
94 for ( int i = 0; i < m_totalRows; i++ ) {
95 A rowName = maxtrix.getRowName( i );
96 matrix.setRowName( rowName, i );
97 }
98 for ( int i = 0; i < m_totalColumns; i++ ) {
99 B colName = maxtrix.getColName( i );
100 matrix.setColumnName( colName, i );
101
102 }
103 for ( int r = 0; r < m_totalRows; r++ ) {
104 for ( int c = 0; c < m_totalColumns; c++ ) {
105 matrix.set( r, c, maxtrix.get( r, c ) );
106 }
107 }
108
109
110 ColorMatrix<A, B> clonedColorMatrix = new ColorMatrix<A, B>( matrix, colorMap, missingColor );
111
112 int[] rowKeys = m_rowKeys.clone();
113 clonedColorMatrix.setRowKeys( rowKeys );
114
115 return clonedColorMatrix;
116
117 }
118
119 public Color getColor( int row, int column ) throws ArrayIndexOutOfBoundsException {
120
121 rowRangeCheck( row );
122 colRangeCheck( column );
123
124 return colors[getTrueRowIndex( row )][column];
125 }
126
127 public Color[] getColorMap() {
128 return colorMap;
129 }
130
131 public Color[][] getColors() {
132 return colors;
133 }
134
135 public int getColumnCount() {
136 return m_totalColumns;
137 }
138
139 public B getColumnName( int column ) throws ArrayIndexOutOfBoundsException {
140
141 colRangeCheck( column );
142
143 return maxtrix.getColName( column );
144 }
145
146 public String[] getColumnNames() {
147 String[] columnNames = new String[m_totalColumns];
148 for ( int i = 0; i < m_totalColumns; i++ ) {
149 columnNames[i] = getColumnName( i ).toString();
150 }
151 return columnNames;
152 }
153
154 public double getDisplayMax() {
155 return displayMax;
156 }
157
158 public double getDisplayMin() {
159 return displayMin;
160 }
161
162
163
164
165 public DoubleMatrix<A, B> getMatrix() {
166 return maxtrix;
167 }
168
169 public double getMax() {
170 return max;
171 }
172
173 public DoubleMatrix<A, B> getMaxtrix() {
174 return maxtrix;
175 }
176
177 public double getMin() {
178 return min;
179 }
180
181 public Color getMissingColor() {
182 return missingColor;
183 }
184
185 public double[] getRow( int row ) throws ArrayIndexOutOfBoundsException {
186
187 rowRangeCheck( row );
188
189 return maxtrix.getRow( getTrueRowIndex( row ) );
190 }
191
192 public double[] getRowByName( A rowName ) {
193 return maxtrix.getRowByName( rowName );
194 }
195
196 public int getRowCount() {
197 return m_totalRows;
198 }
199
200 public int getRowIndexByName( A rowName ) {
201 return maxtrix.getRowIndexByName( rowName );
202 }
203
204 public Object getRowName( int row ) throws ArrayIndexOutOfBoundsException {
205
206 rowRangeCheck( row );
207 return maxtrix.getRowName( getTrueRowIndex( row ) );
208 }
209
210 public String[] getRowNames() {
211 String[] rowNames = new String[m_totalRows];
212 for ( int i = 0; i < m_totalRows; i++ ) {
213 int row = getTrueRowIndex( i );
214 Object rowName = getRowName( row );
215 String rowNameString = rowName.toString();
216 rowNames[i] = rowNameString;
217 }
218 return rowNames;
219 }
220
221 public double getValue( int row, int column ) throws ArrayIndexOutOfBoundsException {
222
223 rowRangeCheck( row );
224 colRangeCheck( column );
225
226 return maxtrix.get( getTrueRowIndex( row ), column );
227 }
228
229 public void mapValuesToColors() {
230 ColorMap#ColorMap">ColorMap colorMapO = new ColorMap( colorMap );
231 double range = displayMax - displayMin;
232
233 if ( range < Constants.SMALL ) {
234 range = Constants.SMALL;
235 }
236
237
238 double zoomFactor = ( colorMapO.getPaletteSize() - 1.0 ) / range;
239
240
241 for ( int row = 0; row < m_totalRows; row++ ) {
242 for ( int column = 0; column < m_totalColumns; column++ ) {
243 double value = getValue( row, column );
244
245 if ( Double.isNaN( value ) ) {
246
247 colors[row][column] = missingColor;
248 } else {
249
250 if ( value > displayMax ) {
251 value = displayMax;
252 } else if ( value < displayMin ) {
253 value = displayMin;
254 }
255
256
257
258 value -= displayMin;
259
260
261 double valueNew = value * zoomFactor;
262 int i = ( int ) Math.floor( valueNew );
263 colors[row][column] = colorMapO.getColor( i );
264 }
265 }
266 }
267 }
268
269 public void resetRowKeys() {
270 for ( int i = 0; i < m_totalRows; i++ ) {
271 m_rowKeys[i] = i;
272 }
273 }
274
275
276
277
278
279
280
281 public void setColor( int row, int column, Color newColor ) throws ArrayIndexOutOfBoundsException {
282
283 rowRangeCheck( row );
284 colRangeCheck( column );
285
286 colors[getTrueRowIndex( row )][column] = newColor;
287 }
288
289
290
291
292
293
294 public void setColorMap( Color[] colorMap ) throws IllegalArgumentException {
295
296 if ( colorMap.length < 2 ) {
297 throw new IllegalArgumentException();
298 }
299
300 this.colorMap = colorMap;
301 mapValuesToColors();
302 }
303
304
305
306
307 public void setDisplayRange( double min, double max ) {
308
309 displayMin = min;
310 displayMax = max;
311
312 mapValuesToColors();
313 }
314
315
316
317
318 public void setRowKeys( int[] rowKeys ) {
319 m_rowKeys = rowKeys;
320 }
321
322
323
324
325
326 public void standardize() {
327
328
329 for ( int r = 0; r < m_totalRows; r++ ) {
330 double[] rowValues = getRow( r );
331 DoubleArrayList doubleArrayList = new cern.colt.list.DoubleArrayList( rowValues );
332 DescriptiveWithMissing.standardize( doubleArrayList );
333 rowValues = doubleArrayList.elements();
334 setRow( r, rowValues );
335 }
336
337 displayMin = -2;
338 displayMax = +2;
339
340 mapValuesToColors();
341
342 }
343
344
345
346
347
348
349
350
351 protected int[] createRowKeys() {
352 m_rowKeys = new int[m_totalRows];
353 for ( int i = 0; i < m_totalRows; i++ ) {
354 m_rowKeys[i] = i;
355 }
356 return m_rowKeys;
357 }
358
359 protected int getTrueRowIndex( int row ) {
360 return m_rowKeys[row];
361 }
362
363
364
365
366
367
368
369 protected void setRow( int row, double values[] ) {
370
371
372 int totalValues = Math.min( values.length, m_totalColumns );
373
374 for ( int column = 0; column < totalValues; column++ ) {
375 maxtrix.set( getTrueRowIndex( row ), column, values[column] );
376
377 }
378 }
379
380 private void colRangeCheck( int column ) {
381 if ( column >= m_totalColumns )
382 throw new ArrayIndexOutOfBoundsException( "The matrix has only " + m_totalColumns
383 + " columns, so the maximum possible column index is " + ( m_totalColumns - 1 ) + ". Column index "
384 + column + " is too high." );
385 }
386
387 private void init( DoubleMatrix<A, B> matrix ) {
388 if ( matrix == null ) {
389 throw new IllegalArgumentException( "Matrix cannot be null" );
390 }
391 maxtrix = matrix;
392 m_totalRows = maxtrix.rows();
393 m_totalColumns = maxtrix.columns();
394 colors = new Color[m_totalRows][m_totalColumns];
395 createRowKeys();
396
397 displayMin = min = MatrixStats.min( maxtrix );
398 displayMax = max = MatrixStats.max( maxtrix );
399
400
401 mapValuesToColors();
402 }
403
404 private void rowRangeCheck( int row ) {
405 if ( row >= m_totalRows )
406 throw new ArrayIndexOutOfBoundsException( "The matrix has only " + m_totalRows
407 + " rows, so the maximum possible row index is " + ( m_totalRows - 1 ) + ". Row index " + row
408 + " is too high." );
409 }
410
411 }