1818import org .jfree .chart .ui .RectangleEdge ;
1919import org .jfree .chart .ui .RectangleInsets ;
2020
21+ /**
22+ * Collection of static methods for formatting and plotting data into heatmaps
23+ * of matrix values
24+ *
25+ * @author William KM Lai
26+ * @see scriptmanager.scripts.BAM_Statistics.BAMGenomeCorrelation
27+ */
2128public class HeatMap {
22-
23- public HeatMap () {
24-
25- }
26-
27- public static ChartPanel createCorrelationHeatmap (String [] labels , double [][] MATRIX , File output ) {
28- // create a paint-scale and a legend showing it
29- LookupPaintScale paintScale = new LookupPaintScale (0 , 1 , Color .black );
29+
30+ /**
31+ * Constant value encoding the blue to white to red color scale. (0)
32+ */
33+ public final static short BLUEWHITERED = 0 ;
34+ /**
35+ * Constant value encoding the jet-like color scale. (0)
36+ */
37+ public final static short JETLIKE = 1 ;
38+
39+ /**
40+ * Create a multi-color color scale inspired by Matplotlib's "jet" color scheme.
41+ * 15 starting colors are set to 15 values.
42+ *
43+ * @return jet-like paintscale
44+ */
45+ private static LookupPaintScale getJetLikeScale () {
46+ LookupPaintScale paintScale = new LookupPaintScale (0 , 1 , Color .black );
47+ paintScale .add (0.938 , Color .decode ("#75140C" )); //dark blue
48+ paintScale .add (0.871 , Color .decode ("#C0281B" ));
49+ paintScale .add (0.804 , Color .decode ("#EB4826" ));
50+ paintScale .add (0.737 , Color .decode ("#FF7500" ));
51+ paintScale .add (0.670 , Color .decode ("#F4BC41" ));
52+ paintScale .add (0.603 , Color .decode ("#F3FC53" ));
53+ paintScale .add (0.536 , Color .decode ("#C6FD64" ));
54+ paintScale .add (0.469 , Color .decode ("#9EFC8A" ));
55+ paintScale .add (0.402 , Color .decode ("#81FBBB" ));
56+ paintScale .add (0.335 , Color .decode ("#6DE9EF" ));
57+ paintScale .add (0.268 , Color .decode ("#08A3FF" ));
58+ paintScale .add (0.201 , Color .decode ("#255AF6" ));
59+ paintScale .add (0.134 , Color .decode ("#0912F5" ));
60+ paintScale .add (0.134 , Color .decode ("#0912F5" ));
61+ paintScale .add (0.067 , Color .decode ("#0600C9" ));
62+ paintScale .add (0.000 , Color .decode ("#020080" )); //dark red
63+ return paintScale ;
64+ }
65+
66+ /**
67+ * Create a paint scale using original BAM Genome Correlation color scale scheme:
68+ * blue (low) to white (mid) to red (high).
69+ *
70+ * @return original blue-white-red paintscale
71+ */
72+ private static LookupPaintScale getBlueWhiteRedScale () {
73+ LookupPaintScale paintScale = new LookupPaintScale (0 , 1 , Color .black );
3074 paintScale .add (0.0 , new Color (0 , 0 , 255 ));
3175 paintScale .add (0.11 , new Color (63 , 63 , 255 ));
3276 paintScale .add (0.22 , new Color (126 , 126 , 255 ));
@@ -36,11 +80,39 @@ public static ChartPanel createCorrelationHeatmap(String[] labels, double[][] MA
3680 paintScale .add (0.66 , new Color (255 , 126 , 126 ));
3781 paintScale .add (0.77 , new Color (255 , 63 , 63 ));
3882 paintScale .add (0.88 , new Color (255 , 0 , 0 ));
39-
40- NumberAxis xAxis = new NumberAxis (null );
41- xAxis .setVisible (false );
42- String [] reverselabels = new String [labels .length ];
43- for (int x = 0 ; x < labels .length ; x ++) { reverselabels [labels .length - x - 1 ] = labels [x ]; }
83+ return paintScale ;
84+ }
85+
86+ /**
87+ * Get paint scale based on scale encoding value.
88+ *
89+ * @param type scale encoding for one of the preset paint scales (e.g.
90+ * REDWHITEBLUE, JETLIKE).
91+ * @return paintscale for the given encoding
92+ */
93+ public static LookupPaintScale getPresetPaintscale (short type ) {
94+ if (type == BLUEWHITERED ) { return getBlueWhiteRedScale (); }
95+ else if (type == JETLIKE ) { return getJetLikeScale (); }
96+ // Use original red-white-blue paintscale as default
97+ return getBlueWhiteRedScale ();
98+ }
99+
100+ /**
101+ * Create a correlation heatmap plot based on a square matrix of inputs with a
102+ * strict percentile-based blue-to-red paint scale (9 levels).
103+ *
104+ * @param labels (sample names) for labeling the y-axis (symmetrical plot so
105+ * x-axis labels are implied)
106+ * @param MATRIX the symmetrical 2D array of values
107+ * @param output the file to write the PNG chart to. File not written if this
108+ * value is null.
109+ * @return the resulting correlation heatmap chart
110+ */
111+ public static ChartPanel createCorrelationHeatmap (String [] labels , double [][] MATRIX , File output , LookupPaintScale paintScale ) {
112+ NumberAxis xAxis = new NumberAxis (null );
113+ xAxis .setVisible (false );
114+ String [] reverselabels = new String [labels .length ];
115+ for (int x = 0 ; x < labels .length ; x ++) { reverselabels [labels .length - x - 1 ] = labels [x ]; }
44116 SymbolAxis yAxis = new SymbolAxis ("Experiments" , reverselabels );
45117 XYPlot plot = new XYPlot (createDataset (MATRIX ), xAxis , yAxis , null );
46118 XYBlockRenderer r = new XYBlockRenderer ();
@@ -52,7 +124,7 @@ public static ChartPanel createCorrelationHeatmap(String[] labels, double[][] MA
52124 JFreeChart chart = new JFreeChart ("Correlation Matrix" , JFreeChart .DEFAULT_TITLE_FONT , plot , false );
53125 NumberAxis scaleAxis = new NumberAxis ("Scale" );
54126 scaleAxis .setAxisLinePaint (Color .white );
55- scaleAxis .setTickMarkPaint (Color .white );
127+ scaleAxis .setTickMarkPaint (Color .white );
56128 PaintScaleLegend legend = new PaintScaleLegend (paintScale , scaleAxis );
57129 legend .setSubdivisionCount (128 );
58130 legend .setAxisLocation (AxisLocation .TOP_OR_RIGHT );
@@ -64,19 +136,28 @@ public static ChartPanel createCorrelationHeatmap(String[] labels, double[][] MA
64136 chart .addSubtitle (legend );
65137 chart .setBackgroundPaint (Color .white );
66138
67- if (output !=null ){
68- int width = 640 ;
69- int height = 480 ;
70- try { ChartUtils .saveChartAsPNG (output , chart , width , height ); }
71- catch ( IOException e ){ e .printStackTrace (); }
139+ // Save PNG if output filepath given
140+ if (output !=null ) {
141+ int width = 640 ;
142+ int height = 480 ;
143+ try { ChartUtils .saveChartAsPNG (output , chart , width , height ); }
144+ catch ( IOException ioe ){ ioe .printStackTrace (); }
145+ catch ( Exception e ){ e .printStackTrace (); }
72146 }
73-
147+
74148 return new ChartPanel (chart );
75149 }
76-
150+
151+
152+ /**
153+ * Helper method for formatting data into the XYZDatset type
154+ *
155+ * @param MATRIX the 2-d array of values to convert
156+ * @return the formatted data series
157+ */
77158 private static XYZDataset createDataset (double [][] MATRIX ) {
78- //The heatmap is based on a standard XY scatterplot as as such, is built with 0,0 in the lower left
79- //The matrix must be rotated such that the final output is consistent
159+ //The heatmap is based on a standard XY scatterplot as as such, is built with 0,0 in the lower left
160+ //The matrix must be rotated such that the final output is consistent
80161 DefaultXYZDataset dataset = new DefaultXYZDataset ();
81162 int N = MATRIX .length ;
82163 for (int i = 0 ; i < N ; i ++) {
0 commit comments