001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 * Created on Aug 3, 2007 021 * 022 */ 023 024package org.biojava.nbio.structure.gui; 025 026import org.biojava.nbio.structure.align.StrucAligParameters; 027import org.biojava.nbio.structure.align.pairwise.AlternativeAlignment; 028import org.biojava.nbio.structure.align.pairwise.FragmentPair; 029import org.biojava.nbio.structure.gui.util.color.ContinuousColorMapper; 030import org.biojava.nbio.structure.gui.util.color.DefaultMatrixMapper; 031import org.biojava.nbio.structure.jama.Matrix; 032 033import javax.swing.*; 034import java.awt.*; 035import java.awt.image.BufferedImage; 036import java.lang.reflect.Method; 037 038 039/** a JPanel that can display a difference of distance matrix and paths that have been 040 * taken for the alignment 041 * 042 * <p>Note: This panel displays the transpose of its underlying matrix. 043 * Thus its width will be the same as {@link Matrix#getRowDimension()} and its 044 * height the same as {@link Matrix#getColumnDimension()}. This stems from the 045 * unfortunate ordering of {@link Matrix#get(int, int)} parameters as (row, col), 046 * which is opposite from the normal (x,y) order used when displaying graphics. 047 * 048 * @author Andreas Prlic 049 * 050 */ 051public class JMatrixPanel extends JPanel{ 052 053 /** 054 * 055 */ 056 private static final long serialVersionUID = -1720879395453257846L; 057 BufferedImage _bufImage; 058 Matrix matrix; 059 ContinuousColorMapper cellColor; //Maps matrix elements to a color 060 float scale; 061 062 FragmentPair[] fragmentPairs; 063 AlternativeAlignment[] aligs; 064 int selectedAlignmentPos; 065 066 final static BasicStroke stroke = new BasicStroke(2.0f); 067 StrucAligParameters params; 068 069 public JMatrixPanel(){ 070 scale = 1; 071 cellColor = new DefaultMatrixMapper(10, 0.9f); 072 //saturation = 0.9f; 073 //scalevalue = 10; 074 selectedAlignmentPos = -1; 075 matrix = new Matrix(0,0); 076 params = new StrucAligParameters(); 077 } 078 079 public int getSelectedAlignmentPos() { 080 return selectedAlignmentPos; 081 } 082 083 public void setSelectedAlignmentPos(int selectedAlignmentPos) { 084 this.selectedAlignmentPos = selectedAlignmentPos; 085 } 086 087 public AlternativeAlignment[] getAlternativeAligs() { 088 return aligs; 089 } 090 091 public void setAlternativeAligs(AlternativeAlignment[] aligs) { 092 this.aligs = aligs; 093 } 094 095 096 097 public FragmentPair[] getFragmentPairs() { 098 return fragmentPairs; 099 } 100 101 public void setFragmentPairs(FragmentPair[] fragmentPairs) { 102 this.fragmentPairs = fragmentPairs; 103 } 104 105 public float getScale() { 106 return scale; 107 } 108 109 public void setPreferredSize(){ 110 111 int prefW = Math.round(matrix.getRowDimension() * scale); 112 int prefH = Math.round(matrix.getColumnDimension() * scale); 113 114 this.setPreferredSize(new Dimension(prefW,prefH)); 115 116 } 117 118 public void setScale(float scale) { 119 120 if ( scale == this.scale) 121 return; 122 //System.out.println("setting scale " + scale + "current width " + getWidth() + " " + getHeight()); 123 124 this.scale = scale; 125 126 setPreferredSize(); 127 128 this.repaint(); 129 130 } 131 132 public Matrix getMatrix() { 133 return matrix; 134 } 135 136 /** sets the distance matrix to be displayed 137 * 138 * @param matrix 139 */ 140 public void setMatrix(Matrix matrix) { 141 this.matrix = matrix; 142 setPreferredSize(); 143 } 144 145 @Override 146 public void paintComponent(Graphics g){ 147 148 //super.paintComponent(g); 149 150 Graphics2D g2 = (Graphics2D)g; 151 if ( _bufImage == null){ 152 153 int w = getWidth(); 154 int h = getHeight(); 155 _bufImage = (BufferedImage) createImage(w,h); 156 //Graphics gc = _bufImage.createGraphics(); 157 //gc.setColor(Color.blue); 158 //gc.fillRect(0,0,w,h); 159 160 } 161 162 163 g2.drawImage(_bufImage,null,0,0); 164 drawDistances(g); 165 166 drawPairs(g); 167 168 if ( scale >= 4) { 169 drawBoxes(g); 170 } 171 } 172 173 /** draw alternative alignments 174 * 175 * @param g 176 */ 177 public void drawPairs(Graphics g){ 178 179 if ( aligs == null) 180 return; 181 182 int nr = aligs.length; 183 184 Graphics2D g2D = (Graphics2D)g; 185 Stroke oldStroke = g2D.getStroke(); 186 g2D.setStroke(stroke); 187 188 Color color; 189 float hue; 190 191 int width = Math.round(scale); 192 int w2 = width / 2 ; 193 194 for (int i = 0; i < aligs.length; i++) { 195 AlternativeAlignment a = aligs[i]; 196 int[] idx1 = a.getIdx1(); 197 int[] idx2 = a.getIdx2(); 198 int xold = -1; 199 int yold = -1; 200 boolean start = true; 201 202 if ( (selectedAlignmentPos != -1 ) && 203 ( selectedAlignmentPos == i)){ 204 color = Color.white; 205 } else { 206 207 hue = i * (1/ (float)nr); 208 color = Color.getHSBColor(hue,1.0f,1.0f); 209 } 210 g.setColor(color); 211 212 for (int j = 0; j < idx1.length; j++) { 213 int x1 = Math.round(idx1[j]*scale) ; 214 int y1 = Math.round(idx2[j]*scale) ; 215 if ( ! start){ 216 //g.drawLine(xold+1,yold,x1+1,y1); 217 218 //g2D.draw(new Line2D.Double(xold,yold,x1,y1)); 219 g.fillRect(xold,yold,2,2); 220 } else { 221 g.fillRect(x1,y1, w2, w2); 222 start =false; 223 } 224 xold = x1; 225 yold = y1; 226 } 227 228 if ( ! start) 229 g.fillRect(xold,yold,w2,w2); 230 231 232 } 233 234 g2D.setStroke(oldStroke); 235 } 236 237 238 /** draw high scoring fragments that are used for the initial alignment seed 239 * selection 240 * 241 * @param g 242 */ 243 public void drawBoxes(Graphics g){ 244 if ( fragmentPairs == null ) 245 return; 246 247 g.setColor(Color.yellow); 248 249 250 for (int i = 0; i < fragmentPairs.length; i++) { 251 FragmentPair fp =fragmentPairs[i]; 252 int xp = fp.getPos1(); 253 int yp = fp.getPos2(); 254 255 int width = Math.round(scale); 256 257 g.drawRect(Math.round(xp*scale),Math.round(yp*scale),width, width); 258 259 } 260 } 261 262 263 /** 264 * For each element in matrix, draw it as a colored square or pixel. 265 * 266 * The color of a matrix element with value x is specified as 267 * - H: 1-x/scalevalue 268 * - S: saturation 269 * - B: 1-x/scalevalue 270 * @param g1 271 */ 272 public void drawDistances(Graphics g1){ 273 Graphics2D g = (Graphics2D)g1; 274 275 int c = matrix.getRowDimension(); 276 int d = matrix.getColumnDimension(); 277 278 float scale = getScale(); 279 int width = Math.round(scale); 280 281 for (int i = 0; i < c; i++) { 282 int ipaint = Math.round(i*scale); 283 284 for (int j = 0; j < d; j++) { 285 double val = matrix.get(i,j); 286 287 int jpaint = Math.round(j*scale); 288 289 Color color = cellColor.getColor(val); 290 g.setColor(color); 291 292 g.fillRect(ipaint,jpaint,width,width); 293 } 294 295 } 296 297 } 298 299 300 @Deprecated 301 public float getSaturation() { 302 try { 303 Method getSaturation = cellColor.getClass().getMethod("getSaturation"); 304 Float saturation = (Float)getSaturation.invoke(cellColor); 305 return saturation; 306 } catch (Exception e) { 307 throw new IllegalStateException("Error calling getSaturation() for "+cellColor.getClass()); 308 } 309 } 310 311 @Deprecated 312 public void setSaturation(float saturation) { 313 try { 314 Method setSaturation = cellColor.getClass().getMethod("setSaturation",Float.TYPE); 315 setSaturation.invoke(cellColor); 316 } catch (Exception e) { 317 throw new IllegalStateException("Error calling setSaturation(float) for "+cellColor.getClass()); 318 } 319 } 320 321 @Deprecated 322 public float getScalevalue() { 323 try { 324 Method getScalevalue = cellColor.getClass().getMethod("getScalevalue"); 325 Float scalevalue = (Float)getScalevalue.invoke(cellColor); 326 return scalevalue; 327 } catch (Exception e) { 328 throw new IllegalStateException("Error calling getScalevalue() for "+cellColor.getClass()); 329 } 330 } 331 332 @Deprecated 333 public void setScalevalue(float scalevalue) { 334 try{ 335 Method setScalevalue = cellColor.getClass().getMethod("setScalevalue",Float.TYPE); 336 setScalevalue.invoke(cellColor); 337 } catch (Exception e) { 338 throw new IllegalStateException("Error calling setScalevalue(float) for "+cellColor.getClass()); 339 } 340 } 341 342 /** 343 * @return the color mapping of the JMatrixPanel 344 */ 345 public ContinuousColorMapper getCellColor() { 346 return cellColor; 347 } 348 349 /** 350 * @param cellColor the color mapping of the JMatrixPanel to set 351 */ 352 public void setCellColor(ContinuousColorMapper cellColor) { 353 this.cellColor = cellColor; 354 } 355 356 357 358}