View Javadoc

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     // data fields
39     ColorMatrix m_matrix; // reference to standardized or unstandardized 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; // max
49     protected int m_columnLabelHeight; // max
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 ); // in pixels
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        // create a standardized copy of the matrix
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       // row label width and height (font-dependent)
105       setFont();
106       m_rowLabelWidth = m_labelGutter
107             + Util.maxStringPixelWidth( m_matrix.getRowNames(), m_labelFont,
108                   this );
109       //m_rowLabelWidth += m_labelGutter; // this is optional (leaves some
110       // space on the right)
111       m_columnLabelHeight = Util.maxStringPixelWidth(
112             m_matrix.getColumnNames(), m_labelFont, this );
113       //m_columnLabelHeight += m_labelGutter; // this is optional (leaves some
114       // space on top)
115 
116       // height and width of this display component
117       int height = m_cellSize.height * m_matrix.getRowCount();
118       int width = m_cellSize.width * m_matrix.getColumnCount();
119 
120       // adjust for row and column labels
121       if ( withLabels ) {
122          width += m_rowLabelWidth;
123          height += ( m_columnLabelHeight + m_labelGutter );
124       }
125 
126       // set the sizes
127       return new Dimension( width, height );
128 
129    } // end getSize
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    } // end paintComponent
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    } // end setStandardizedEnabled
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       // loop through the matrix, one row at a time
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          // draw an entire row, one cell at a time
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       } // end looping through the matrix, one row at a time
193    } // end drawMatrix
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       // draw row names
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       } // end drawing row names
221    } // end rawRowName
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          // compute the coordinates
235          int x = m_cellSize.width + ( j * m_cellSize.width ) - m_fontGutter;
236          int y = m_columnLabelHeight;
237 
238          // get column name
239          String columnName = m_matrix.getColumnName( j );
240          if ( null == columnName ) {
241             columnName = "Undefined";
242          }
243 
244          // set font and color
245          g.setColor( Color.black );
246          g.setFont( m_labelFont );
247 
248          // print the text vertically
249          Util.drawVerticalString( g, columnName, m_labelFont, x, y );
250 
251       } // end for column
252    } // end drawColumnNames
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       // Include row and column labels?
303       boolean wereLabelsShown = m_isShowLabels;
304       if ( !wereLabelsShown ) {
305          // Labels aren't visible, so make them visible
306          setLabelsVisible( true );
307          initSize();
308       }
309 
310       // Draw the image to a buffer
311       Dimension d = getSize( showLabels ); // how big is the image with row and
312       // column labels
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       // Write the image to a png file
323       ImageIO.write( m_image, "png", new File( outPngFilename ) );
324 
325       // Restore state: make the image as it was before
326       if ( !wereLabelsShown ) {
327          // Labels weren't visible to begin with, so hide them
328          setLabelsVisible( false );
329          initSize();
330       }
331    } // end saveImage
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    } // end getColor
378 
379    public double getValue( int row, int column ) {
380       return m_matrix.getValue( row, column );
381    } // end getValue
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 } // end class JMatrixDisplay
482