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 import java.awt.Dimension;
23 import java.awt.Font;
24 import java.awt.Graphics;
25 import java.awt.Graphics2D;
26 import java.awt.image.BufferedImage;
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.OutputStream;
30
31 import javax.imageio.ImageIO;
32 import javax.swing.JPanel;
33
34 import org.apache.commons.lang3.StringUtils;
35
36 import ubic.basecode.dataStructure.matrix.DoubleMatrix;
37 import ubic.basecode.graphics.text.Util;
38
39
40
41
42
43
44
45 public class MatrixDisplay<R, C> extends JPanel {
46
47 private static final int DEFAULT_SCALE_BAR_WIDTH = 100;
48
49 private static final long serialVersionUID = -8078532270193813539L;
50
51 public static <R, C> MatrixDisplay<R, C> newInstance( ColorMatrix<R, C> matrix ) {
52 return new MatrixDisplay<R, C>( matrix );
53 }
54
55
56 ColorMatrix<R, C> colorMatrix;
57 boolean m_isShowingStandardizedMatrix = false;
58 ColorMatrix<R, C> m_standardizedMatrix;
59
60 ColorMatrix<R, C> m_unstandardizedMatrix;
61
62 final int SCALE_BAR_ROOM = 40;
63
64 protected Dimension m_cellSize = new Dimension( 10, 10 );
65 protected int m_columnLabelHeight;
66 protected final int m_defaultResolution = 120;
67 protected int m_fontGutter;
68 protected int m_fontSize = 10;
69 protected boolean m_isShowLabels = false;
70 protected boolean m_isShowScale = false;
71 protected Font m_labelFont = null;
72 protected int m_labelGutter = 5;
73 protected int m_maxColumnLength = 0;
74 protected final int m_maxFontSize = 10;
75
76 protected int m_ratioWidth = 0;
77
78 protected int m_resolution = m_defaultResolution;
79
80 protected int m_rowLabelWidth;
81
82 protected int m_textSize = 0;
83
84 public MatrixDisplay( ColorMatrix<R, C> matrix ) {
85 init( matrix );
86 }
87
88 public MatrixDisplay( DoubleMatrix<R, C> matrix ) {
89 this( new ColorMatrix<R, C>( matrix ) );
90 }
91
92 public Color getColor( int row, int column ) {
93 return colorMatrix.getColor( row, column );
94 }
95
96
97
98
99 public Color[] getColorMap() {
100 return colorMatrix.getColorMap();
101 }
102
103 public ColorMatrix<R, C> getColorMatrix() {
104 return colorMatrix;
105 }
106
107 public int getColumnCount() {
108 return colorMatrix.getColumnCount();
109 }
110
111 public Object getColumnName( int column ) {
112 return colorMatrix.getColumnName( column );
113 }
114
115 public String[] getColumnNames() {
116 return colorMatrix.getColumnNames();
117 }
118
119 public double getDisplayMax() {
120 return colorMatrix.getDisplayMax();
121 }
122
123 public double getDisplayMin() {
124 return colorMatrix.getDisplayMin();
125 }
126
127 public double getDisplayRange() {
128 return colorMatrix.getDisplayMax() - getDisplayMin();
129 }
130
131 public DoubleMatrix<R, C> getMatrix() {
132 return colorMatrix.getMatrix();
133 }
134
135
136
137
138 public double getMax() {
139 return colorMatrix.getMax();
140 }
141
142
143
144
145 public int getMaxColumnLength() {
146 return m_maxColumnLength;
147 }
148
149
150
151
152 public double getMin() {
153 return colorMatrix.getMin();
154 }
155
156
157
158
159 public Color getMissingColor() {
160 return colorMatrix.getMissingColor();
161 }
162
163 public double getRawValue( int row, int column ) {
164 return m_unstandardizedMatrix.getValue( row, column );
165 }
166
167 public double[] getRow( int row ) {
168 return colorMatrix.getRow( row );
169 }
170
171 public double[] getRowByName( R rowName ) {
172 return colorMatrix.getRowByName( rowName );
173 }
174
175 public int getRowCount() {
176 return colorMatrix.getRowCount();
177 }
178
179 public int getRowHeight() {
180 return m_cellSize.height;
181 }
182
183 public int getRowIndexByName( R rowName ) {
184 return colorMatrix.getRowIndexByName( rowName );
185 }
186
187 public Object getRowName( int row ) {
188 return colorMatrix.getRowName( row );
189 }
190
191 public String[] getRowNames() {
192 return colorMatrix.getRowNames();
193 }
194
195 public boolean getStandardizedEnabled() {
196
197 return m_isShowingStandardizedMatrix;
198 }
199
200 public double getValue( int row, int column ) {
201 return colorMatrix.getValue( row, column );
202 }
203
204 public void init( ColorMatrix<R, C> matrix ) {
205
206 m_unstandardizedMatrix = colorMatrix = matrix;
207 initSize();
208
209
210 m_standardizedMatrix = matrix.clone();
211 m_standardizedMatrix.standardize();
212
213 }
214
215
216
217
218 public void resetRowKeys() {
219 colorMatrix.resetRowKeys();
220 }
221
222
223
224
225
226
227
228 public void saveImage( ColorMatrix<R, C> matrix, String outPngFilename, boolean showLabels, boolean showScalebar,
229 boolean standardize ) throws java.io.IOException {
230
231 Graphics2D g = null;
232
233
234 boolean wereLabelsShown = m_isShowLabels;
235 if ( !wereLabelsShown ) {
236
237 setLabelsVisible( true );
238 initSize();
239 }
240
241
242 Dimension d = computeSize( showLabels, showScalebar );
243
244 BufferedImage m_image = new BufferedImage( d.width, d.height, BufferedImage.TYPE_INT_RGB );
245 g = m_image.createGraphics();
246 g.setBackground( Color.white );
247 g.clearRect( 0, 0, d.width, d.height );
248
249 drawMatrix( matrix, g, showLabels, showScalebar );
250 if ( showLabels ) {
251 drawRowNames( g, showScalebar );
252 drawColumnNames( g, showScalebar );
253 }
254 if ( showScalebar ) {
255 drawScaleBar( g, d, matrix.getDisplayMin(), matrix.getDisplayMax() );
256 }
257
258
259 ImageIO.write( m_image, "png", new File( outPngFilename ) );
260
261
262 if ( !wereLabelsShown ) {
263
264 setLabelsVisible( false );
265 initSize();
266 }
267 }
268
269
270
271
272
273
274
275 public void saveImage( String outPngFilename ) throws java.io.IOException {
276 saveImage( this.colorMatrix, outPngFilename, m_isShowLabels, m_isShowScale, m_isShowingStandardizedMatrix );
277 }
278
279
280
281
282
283
284 public void saveImage( String outPngFilename, boolean showLabels, boolean showScale ) throws java.io.IOException {
285 saveImage( this.colorMatrix, outPngFilename, showLabels, showScale, m_isShowingStandardizedMatrix );
286 }
287
288
289
290
291
292
293
294 public void saveImageToPng( ColorMatrix<R, C> matrix, OutputStream stream, boolean showLabels,
295 boolean showScalebar, boolean standardize ) throws IOException {
296
297 boolean wasScalebarShown = m_isShowScale;
298 if ( !wasScalebarShown ) {
299 setScaleBarVisible( true );
300 initSize();
301 }
302
303
304 boolean wereLabelsShown = m_isShowLabels;
305 if ( !wereLabelsShown ) {
306
307 setLabelsVisible( true );
308 initSize();
309 }
310
311 try {
312 writeToPng( matrix, stream, showLabels, showScalebar );
313 } finally {
314
315 if ( !wereLabelsShown ) {
316
317 setLabelsVisible( false );
318 initSize();
319 }
320
321 if ( !wasScalebarShown ) {
322 setScaleBarVisible( false );
323 initSize();
324 }
325 }
326 }
327
328 public void setCellSize( Dimension d ) {
329
330 m_cellSize = d;
331 initSize();
332 }
333
334
335
336
337
338 public void setColorMap( Color[] colorMap ) {
339
340 m_standardizedMatrix.setColorMap( colorMap );
341 m_unstandardizedMatrix.setColorMap( colorMap );
342 }
343
344
345
346
347
348 public void setDisplayRange( double min, double max ) {
349 colorMatrix.setDisplayRange( min, max );
350 }
351
352
353
354
355
356
357 public void setLabelsVisible( boolean isShowLabels ) {
358 m_isShowLabels = isShowLabels;
359 initSize();
360 }
361
362
363
364
365 public void setMatrix( ColorMatrix<R, C> matrix ) {
366 colorMatrix = matrix;
367 initSize();
368 }
369
370
371
372
373 public void setMaxColumnLength( int columnLength ) {
374 m_maxColumnLength = columnLength;
375 }
376
377 public void setRowHeight( int height ) {
378
379 m_cellSize.height = height;
380 initSize();
381 }
382
383 public void setRowKeys( int[] rowKeys ) {
384 colorMatrix.setRowKeys( rowKeys );
385 }
386
387 public void setScaleBarVisible( boolean isShowScale ) {
388 m_isShowScale = isShowScale;
389 initSize();
390 }
391
392 public void setStandardizedEnabled( boolean showStandardizedMatrix ) {
393 m_isShowingStandardizedMatrix = showStandardizedMatrix;
394 if ( showStandardizedMatrix ) {
395 colorMatrix = m_standardizedMatrix;
396 } else {
397 colorMatrix = m_unstandardizedMatrix;
398 }
399 }
400
401
402
403
404
405
406
407 public void writeToPng( ColorMatrix<R, C> matrix, OutputStream stream, boolean showLabels, boolean showScalebar )
408 throws IOException {
409
410 boolean oldLabelSate = this.m_isShowLabels;
411 if ( !oldLabelSate ) {
412 this.setLabelsVisible( true );
413 }
414
415 Dimension d = computeSize( showLabels, showScalebar );
416 BufferedImage m_image = new BufferedImage( d.width, d.height, BufferedImage.TYPE_INT_RGB );
417 Graphics2D g = m_image.createGraphics();
418 g.setBackground( Color.white );
419 g.clearRect( 0, 0, d.width, d.height );
420 drawMatrix( matrix, g, showLabels, showScalebar );
421 if ( showLabels ) {
422 drawRowNames( g, showScalebar );
423 drawColumnNames( g, showScalebar );
424 }
425 if ( showScalebar ) {
426 drawScaleBar( g, d, matrix.getDisplayMin(), matrix.getDisplayMax() );
427 }
428
429
430
431 ImageIO.write( m_image, "png", stream );
432
433 this.setLabelsVisible( oldLabelSate );
434 }
435
436
437
438
439
440
441
442 protected Dimension computeSize( boolean showLabels, boolean showScalebar ) {
443
444 if ( colorMatrix == null ) {
445 return null;
446 }
447
448
449 setFont();
450 m_rowLabelWidth = m_labelGutter
451 + Util.maxStringPixelWidth( colorMatrix.getRowNames(), this.getFontMetrics( m_labelFont ) );
452 m_rowLabelWidth += m_labelGutter;
453 if ( m_maxColumnLength > 0 ) {
454 String[] cols = colorMatrix.getColumnNames();
455 for ( int i = 0; i < cols.length; i++ ) {
456 cols[i] = padColumnString( cols[i] );
457
458 }
459
460
461 m_columnLabelHeight = 5 * m_maxColumnLength;
462 } else {
463 m_columnLabelHeight = Util.maxStringPixelWidth( colorMatrix.getColumnNames(),
464 this.getFontMetrics( m_labelFont ) );
465 }
466
467
468
469
470
471 int height = m_cellSize.height * colorMatrix.getRowCount();
472 int width = m_cellSize.width * colorMatrix.getColumnCount();
473
474
475 if ( showLabels ) {
476 width += m_rowLabelWidth;
477 height += m_columnLabelHeight + m_labelGutter;
478 }
479
480 if ( showScalebar ) {
481 height += SCALE_BAR_ROOM;
482
483
484
485 }
486
487
488 return new Dimension( width, height );
489
490 }
491
492
493
494
495
496
497 protected void drawColumnNames( Graphics g, boolean leaveRoomForScalebar ) {
498
499 if ( colorMatrix == null ) return;
500 Color oldColor = g.getColor();
501
502 int y = m_columnLabelHeight;
503 if ( leaveRoomForScalebar ) {
504 y += SCALE_BAR_ROOM;
505 }
506
507 g.setColor( Color.white );
508 g.fillRect( 0, 0, this.getWidth(), y );
509
510 g.setColor( Color.black );
511 g.setFont( m_labelFont );
512
513 int columnCount = colorMatrix.getColumnCount();
514 for ( int j = 0; j < columnCount; j++ ) {
515
516 int x = m_cellSize.width + j * m_cellSize.width - m_fontGutter;
517
518 Object columnName = colorMatrix.getColumnName( j );
519 if ( null == columnName ) {
520 columnName = "Undefined";
521 }
522
523
524
525
526 String columnNameString = columnName.toString();
527 if ( m_maxColumnLength > 0 ) {
528 columnNameString = padColumnString( columnNameString );
529 }
530
531
532 Util.drawVerticalString( g, columnNameString, m_labelFont, x, y );
533
534 }
535 g.setColor( oldColor );
536 }
537
538
539
540
541
542
543
544 protected void drawMatrix( ColorMatrix<R, C> matrix, Graphics g, boolean leaveRoomForLabels,
545 boolean leaveRoomForScalebar ) {
546
547
548 Color oldColor = g.getColor();
549 g.setColor( Color.white );
550 g.fillRect( 0, 0, this.getWidth(), this.getHeight() );
551
552 int rowCount = matrix.getRowCount();
553 int columnCount = matrix.getColumnCount();
554
555
556 for ( int i = 0; i < rowCount; i++ ) {
557 int y = i * m_cellSize.height;
558 if ( leaveRoomForLabels ) {
559 y += m_columnLabelHeight + m_labelGutter;
560 }
561 if ( leaveRoomForScalebar ) {
562 y += SCALE_BAR_ROOM;
563 }
564
565
566 for ( int j = 0; j < columnCount; j++ ) {
567 int x = j * m_cellSize.width;
568 int width = ( j + 1 ) * m_cellSize.width - x;
569
570 Color color = matrix.getColor( i, j );
571 g.setColor( color );
572 g.fillRect( x, y, width, m_cellSize.height );
573 }
574
575 }
576 g.setColor( oldColor );
577 }
578
579
580
581
582
583
584
585 protected void drawRowNames( Graphics g, boolean showScalebar ) {
586
587 if ( colorMatrix == null ) return;
588
589 Color oldColor = g.getColor();
590
591 g.setColor( Color.white );
592 g.fillRect( colorMatrix.getColumnCount() * m_cellSize.width, 0,
593 colorMatrix.getColumnCount() * m_cellSize.width, this.getHeight() );
594
595 int rowCount = colorMatrix.getRowCount();
596 int xLabelStartPosition = colorMatrix.getColumnCount() * m_cellSize.width + m_labelGutter;
597 g.setColor( Color.black );
598 g.setFont( m_labelFont );
599
600 for ( int i = 0; i < rowCount; i++ ) {
601 int y = i * m_cellSize.height + m_columnLabelHeight + m_labelGutter;
602 int yLabelPosition = y + m_cellSize.height - m_fontGutter;
603 if ( showScalebar ) {
604 yLabelPosition += SCALE_BAR_ROOM;
605 }
606
607 Object rowName = colorMatrix.getRowName( i );
608 if ( null == rowName ) {
609 rowName = "Undefined";
610 }
611
612 g.drawString( rowName.toString(), xLabelStartPosition, yLabelPosition );
613
614 }
615 g.setColor( oldColor );
616 }
617
618
619
620
621
622 protected void drawScaleBar( Graphics g, Dimension d, double displayMin, double displayMax ) {
623
624
625
626 g.setColor( Color.white );
627 int upperLeftScalebarGutter = 10;
628 int scaleBarHeight = 10;
629 int desiredScaleBarLength = ( int ) Math.min( DEFAULT_SCALE_BAR_WIDTH, d.getWidth() );
630
631 if ( desiredScaleBarLength < 10 ) {
632 return;
633 }
634
635 g.drawRect( upperLeftScalebarGutter, upperLeftScalebarGutter, desiredScaleBarLength, upperLeftScalebarGutter );
636 JGradientLabell#JGradientLabel">JGradientLabel scalebar = new JGradientLabel( new ColorMap( this.getColorMap() ).getPalette() );
637 scalebar.setBackground( Color.white );
638 scalebar.setSize( new Dimension( desiredScaleBarLength, scaleBarHeight ) );
639 int actualWidth = scalebar.drawAtLocation( g, upperLeftScalebarGutter, upperLeftScalebarGutter );
640 g.setColor( Color.black );
641 g.drawString( String.format( "%.2g", displayMin ), 0, upperLeftScalebarGutter + scaleBarHeight + m_fontGutter
642 + g.getFontMetrics().getHeight() );
643 g.drawString( String.format( "%.2g", displayMax ), actualWidth, upperLeftScalebarGutter + scaleBarHeight
644 + m_fontGutter + g.getFontMetrics().getHeight() );
645 g.drawRect( upperLeftScalebarGutter, upperLeftScalebarGutter, actualWidth, scaleBarHeight );
646 }
647
648
649
650
651 protected void initSize() {
652
653 Dimension d = getSize();
654 setMinimumSize( d );
655 setPreferredSize( d );
656 setSize( d );
657 this.revalidate();
658 }
659
660
661
662
663
664
665 @Override
666 protected void paintComponent( Graphics g ) {
667
668 super.paintComponent( g );
669 drawMatrix( colorMatrix, g, m_isShowLabels, m_isShowScale );
670
671 if ( m_isShowLabels ) {
672 drawRowNames( g, m_isShowScale );
673 drawColumnNames( g, m_isShowScale );
674 }
675 if ( m_isShowScale ) {
676 drawScaleBar( g, this.getSize(), colorMatrix.getDisplayMin(), colorMatrix.getDisplayMax() );
677 }
678 }
679
680
681
682
683 private int getFontSize() {
684 return Math.max( m_cellSize.height, 5 );
685 }
686
687
688
689
690
691
692
693 private String padColumnString( String str ) {
694 String paddedstr = StringUtils.abbreviate( str, m_maxColumnLength );
695 paddedstr = StringUtils.rightPad( str, m_maxColumnLength, " " );
696 return paddedstr;
697 }
698
699
700
701
702 private void setFont() {
703 int fontSize = Math.min( getFontSize(),
704 ( int ) ( ( double ) m_maxFontSize / ( double ) m_defaultResolution * m_resolution ) );
705 if ( fontSize != m_fontSize || m_labelFont == null ) {
706 m_fontSize = fontSize;
707 m_labelFont = new Font( "Ariel", Font.PLAIN, m_fontSize );
708 m_fontGutter = ( int ) ( m_cellSize.height * .22 );
709 }
710 }
711
712 }
713