1 package baseCode.gui;
2
3 import java.awt.Color;
4 import java.awt.Dimension;
5 import java.awt.Font;
6 import java.awt.Graphics;
7 import java.awt.Graphics2D;
8 import java.awt.image.BufferedImage;
9 import java.io.File;
10 import java.io.IOException;
11
12 import javax.imageio.ImageIO;
13 import javax.swing.JPanel;
14
15 import baseCode.dataStructure.matrix.AbstractNamedDoubleMatrix;
16 import baseCode.dataStructure.matrix.DenseDoubleMatrix2DNamed;
17 import baseCode.graphics.text.Util;
18
19 /***
20 * <p>
21 * Title: JMatrixDisplay
22 * </p>
23 * <p>
24 * Description: a visual component for displaying a color matrix
25 * </p>
26 * <p>
27 * Copyright: Copyright (c) 2004
28 * </p>
29 * <p>
30 * Institution:: Columbia University
31 * </p>
32 *
33 * @author Will Braynen
34 * @version $Id: JMatrixDisplay.java,v 1.39 2004/09/20 22:19:02 pavlidis Exp $
35 */
36 public class JMatrixDisplay extends JPanel {
37
38
39 ColorMatrix m_matrix;
40 ColorMatrix m_unstandardizedMatrix;
41 ColorMatrix m_standardizedMatrix;
42 boolean m_isShowingStandardizedMatrix = false;
43
44 protected boolean m_isShowLabels = false;
45 protected BufferedImage m_image = null;
46
47 protected int m_ratioWidth = 0;
48 protected int m_rowLabelWidth;
49 protected int m_columnLabelHeight;
50 protected int m_labelGutter = 5;
51 protected int m_fontGutter;
52 protected Font m_labelFont = null;
53 protected int m_fontSize = 10;
54 protected final int m_maxFontSize = 10;
55 protected final int m_defaultResolution = 120;
56 protected int m_resolution = m_defaultResolution;
57 protected int m_textSize = 0;
58
59 protected Dimension m_cellSize = new Dimension( 10, 10 );
60
61 public JMatrixDisplay( String filename ) throws IOException {
62
63 ColorMatrix matrix = new ColorMatrix( filename );
64 init( matrix );
65 }
66
67 public JMatrixDisplay( DenseDoubleMatrix2DNamed matrix ) {
68 this( new ColorMatrix( matrix ) );
69 }
70
71 public JMatrixDisplay( ColorMatrix matrix ) {
72 init( matrix );
73 }
74
75 public void init( ColorMatrix matrix ) {
76
77 m_unstandardizedMatrix = m_matrix = matrix;
78 initSize();
79
80
81 m_standardizedMatrix = ( ColorMatrix ) matrix.clone();
82 m_standardizedMatrix.standardize();
83
84 }
85
86 /***
87 * Sets the display size
88 */
89 protected void initSize() {
90
91 Dimension d = getSize( m_isShowLabels );
92 setMinimumSize( d );
93 setPreferredSize( d );
94 setSize( d );
95 this.revalidate();
96 }
97
98 protected Dimension getSize( boolean withLabels ) {
99
100 if ( m_matrix == null ) {
101 return null;
102 }
103
104
105 setFont();
106 m_rowLabelWidth = m_labelGutter
107 + Util.maxStringPixelWidth( m_matrix.getRowNames(), m_labelFont,
108 this );
109
110
111 m_columnLabelHeight = Util.maxStringPixelWidth(
112 m_matrix.getColumnNames(), m_labelFont, this );
113
114
115
116
117 int height = m_cellSize.height * m_matrix.getRowCount();
118 int width = m_cellSize.width * m_matrix.getColumnCount();
119
120
121 if ( withLabels ) {
122 width += m_rowLabelWidth;
123 height += ( m_columnLabelHeight + m_labelGutter );
124 }
125
126
127 return new Dimension( width, height );
128
129 }
130
131 /***
132 * <code>JComponent</code> method used to render this component
133 *
134 * @param g Graphics used for painting
135 */
136 protected void paintComponent( Graphics g ) {
137
138 super.paintComponent( g );
139 drawMatrix( g, m_isShowLabels );
140
141 if ( m_isShowLabels ) {
142 drawRowNames( g );
143 drawColumnNames( g );
144 }
145 }
146
147 public void setStandardizedEnabled( boolean showStandardizedMatrix ) {
148 m_isShowingStandardizedMatrix = showStandardizedMatrix;
149 if ( showStandardizedMatrix ) {
150 m_matrix = m_standardizedMatrix;
151 } else {
152 m_matrix = m_unstandardizedMatrix;
153 }
154 }
155
156 public boolean getStandardizedEnabled() {
157
158 return m_isShowingStandardizedMatrix;
159 }
160
161 /***
162 * Gets called from #paintComponent and #saveImage
163 *
164 * @param g Graphics
165 * @param leaveRoomForLabels boolean
166 */
167 protected void drawMatrix( Graphics g, boolean leaveRoomForLabels ) {
168
169 g.setColor( Color.white );
170 g.fillRect( 0, 0, this.getWidth(), this.getHeight() );
171
172 int rowCount = m_matrix.getRowCount();
173 int columnCount = m_matrix.getColumnCount();
174
175
176 for ( int i = 0; i < rowCount; i++ ) {
177 int y = ( i * m_cellSize.height );
178 if ( leaveRoomForLabels ) {
179 y += ( m_columnLabelHeight + m_labelGutter );
180 }
181
182
183 for ( int j = 0; j < columnCount; j++ ) {
184 int x = ( j * m_cellSize.width );
185 int width = ( ( j + 1 ) * m_cellSize.width ) - x;
186
187 Color color = m_matrix.getColor( i, j );
188 g.setColor( color );
189 g.fillRect( x, y, width, m_cellSize.height );
190 }
191
192 }
193 }
194
195 /***
196 * Draws row names (horizontally)
197 *
198 * @param g Graphics
199 */
200 protected void drawRowNames( Graphics g ) {
201
202 if ( m_matrix == null ) return;
203
204 int rowCount = m_matrix.getRowCount();
205
206
207 for ( int i = 0; i < rowCount; i++ ) {
208 g.setColor( Color.black );
209 g.setFont( m_labelFont );
210 int y = ( i * m_cellSize.height ) + m_columnLabelHeight
211 + m_labelGutter;
212 int xRatio = ( m_matrix.getColumnCount() * m_cellSize.width )
213 + m_labelGutter;
214 int yRatio = y + m_cellSize.height - m_fontGutter;
215 String rowName = m_matrix.getRowName( i );
216 if ( null == rowName ) {
217 rowName = "Undefined";
218 }
219 g.drawString( rowName, xRatio, yRatio );
220 }
221 }
222
223 /***
224 * Draws column names vertically (turned 90 degrees counter-clockwise)
225 *
226 * @param g Graphics
227 */
228 protected void drawColumnNames( Graphics g ) {
229
230 if ( m_matrix == null ) return;
231
232 int columnCount = m_matrix.getColumnCount();
233 for ( int j = 0; j < columnCount; j++ ) {
234
235 int x = m_cellSize.width + ( j * m_cellSize.width ) - m_fontGutter;
236 int y = m_columnLabelHeight;
237
238
239 String columnName = m_matrix.getColumnName( j );
240 if ( null == columnName ) {
241 columnName = "Undefined";
242 }
243
244
245 g.setColor( Color.black );
246 g.setFont( m_labelFont );
247
248
249 Util.drawVerticalString( g, columnName, m_labelFont, x, y );
250
251 }
252 }
253
254 /***
255 * Sets the font used for drawing text
256 */
257 private void setFont() {
258 int fontSize = Math
259 .min( getFontSize(), ( int ) ( ( double ) m_maxFontSize
260 / ( double ) m_defaultResolution * m_resolution ) );
261 if ( ( fontSize != m_fontSize ) || ( m_labelFont == null ) ) {
262 m_fontSize = fontSize;
263 m_labelFont = new Font( "Ariel", Font.PLAIN, m_fontSize );
264 m_fontGutter = ( int ) ( m_cellSize.height * .22 );
265 }
266 }
267
268 /***
269 * @return the height of the font
270 */
271 private int getFontSize() {
272 return Math.max( m_cellSize.height, 5 );
273 }
274
275 /***
276 * Saves the image to a png file.
277 *
278 * @param outPngFilename String
279 * @throws IOException
280 */
281 public void saveImage( String outPngFilename ) throws java.io.IOException {
282 saveImage( outPngFilename, m_isShowLabels, m_isShowingStandardizedMatrix );
283 }
284
285 public void saveImage( String outPngFilename, boolean showLabels )
286 throws java.io.IOException {
287 saveImage( outPngFilename, showLabels, m_isShowingStandardizedMatrix );
288 }
289
290 /***
291 * @param outPngFilename String
292 * @param showLabels boolean
293 * @param standardize normalize to deviation 1, mean 0.
294 * @todo never read
295 * @throws IOException
296 */
297 public void saveImage( String outPngFilename, boolean showLabels,
298 boolean standardize ) throws java.io.IOException {
299
300 Graphics2D g = null;
301
302
303 boolean wereLabelsShown = m_isShowLabels;
304 if ( !wereLabelsShown ) {
305
306 setLabelsVisible( true );
307 initSize();
308 }
309
310
311 Dimension d = getSize( showLabels );
312
313 m_image = new BufferedImage( d.width, d.height,
314 BufferedImage.TYPE_INT_RGB );
315 g = m_image.createGraphics();
316 drawMatrix( g, showLabels );
317 if ( showLabels ) {
318 drawRowNames( g );
319 drawColumnNames( g );
320 }
321
322
323 ImageIO.write( m_image, "png", new File( outPngFilename ) );
324
325
326 if ( !wereLabelsShown ) {
327
328 setLabelsVisible( false );
329 initSize();
330 }
331 }
332
333 /***
334 * If this display component has already been added to the GUI, it will be resized to fit or exclude the row names
335 *
336 * @param isShowLabels boolean
337 */
338 public void setLabelsVisible( boolean isShowLabels ) {
339 m_isShowLabels = isShowLabels;
340 initSize();
341 }
342
343 public ColorMatrix getColorMatrix() {
344 return m_matrix;
345 }
346
347 public AbstractNamedDoubleMatrix getMatrix() {
348 return m_matrix.m_matrix;
349 }
350
351 /***
352 * @param matrix the new matrix to use; will resize this display component as necessary
353 */
354 public void setMatrix( ColorMatrix matrix ) {
355 m_matrix = matrix;
356 initSize();
357 }
358
359 public void setCellSize( Dimension d ) {
360
361 m_cellSize = d;
362 initSize();
363 }
364
365 public void setRowHeight( int height ) {
366
367 m_cellSize.height = height;
368 initSize();
369 }
370
371 public int getRowHeight() {
372 return m_cellSize.height;
373 }
374
375 public Color getColor( int row, int column ) {
376 return m_matrix.getColor( row, column );
377 }
378
379 public double getValue( int row, int column ) {
380 return m_matrix.getValue( row, column );
381 }
382
383 public double[] getRow( int row ) {
384 return m_matrix.getRow( row );
385 }
386
387 public double[] getRowByName( String rowName ) {
388 return m_matrix.getRowByName( rowName );
389 }
390
391 public int getRowCount() {
392 return m_matrix.getRowCount();
393 }
394
395 public int getColumnCount() {
396 return m_matrix.getColumnCount();
397 }
398
399 public String getColumnName( int column ) {
400 return m_matrix.getColumnName( column );
401 }
402
403 public String getRowName( int row ) {
404 return m_matrix.getRowName( row );
405 }
406
407 public String[] getColumnNames() {
408 return m_matrix.getColumnNames();
409 }
410
411 public String[] getRowNames() {
412 return m_matrix.getRowNames();
413 }
414
415 public int getRowIndexByName( String rowName ) {
416 return m_matrix.getRowIndexByName( rowName );
417 }
418
419 public void setRowKeys( int[] rowKeys ) {
420 m_matrix.setRowKeys( rowKeys );
421 }
422
423 public void resetRowKeys() {
424 m_matrix.resetRowKeys();
425 }
426
427 /***
428 * @param colorMap an array of colors which define the midpoints in the color map; this can be one of the constants
429 * defined in the ColorMap class, like ColorMap.REDGREEN_COLORMAP and ColorMap.BLACKBODY_COLORMAP
430 */
431 public void setColorMap( Color[] colorMap ) {
432
433 m_standardizedMatrix.setColorMap( colorMap );
434 m_unstandardizedMatrix.setColorMap( colorMap );
435 }
436
437 /***
438 * @return the current color map
439 */
440 public Color[] getColorMap() {
441 return m_matrix.m_colorMap;
442 }
443
444 /***
445 * @return the smallest value in the matrix
446 */
447 public double getMin() {
448 return m_matrix.m_min;
449 }
450
451 /***
452 * @return the largest value in the matrix
453 */
454 public double getMax() {
455 return m_matrix.m_max;
456 }
457
458 public double getDisplayMin() {
459 return m_matrix.m_displayMin;
460 }
461
462 public double getDisplayMax() {
463 return m_matrix.m_displayMax;
464 }
465
466 public double getDisplayRange() {
467 return m_matrix.m_displayMax - m_matrix.m_displayMin;
468 }
469
470 public void setDisplayRange( double min, double max ) {
471 m_matrix.setDisplayRange( min, max );
472 }
473
474 /***
475 * @return the color used for missing values
476 */
477 public Color getMissingColor() {
478 return m_matrix.m_missingColor;
479 }
480
481 }
482