package org.seqcode.data.motifdb; import java.awt.*; import java.awt.geom.AffineTransform; import java.awt.font.*; public class WeightMatrixPainter { private static Color AColor = Color.RED; private static Color CColor = Color.BLUE; private static Color GColor = Color.ORANGE; private static Color TColor = Color.GREEN; private static Color GapColor = Color.WHITE; private static Color NColor = Color.GRAY; public final static int X_MARGIN = 10; public final static int Y_MARGIN = 2; public final static int YLABEL_SIZE = 12; public void paint(WeightMatrix wm, Graphics g, int x1, int y1, int x2, int y2) {this.paint(wm, g, x1, y1, x2, y2, null, false);} public void paint(WeightMatrix wm, Graphics g, int x1, int y1, int x2, int y2, String name) {this.paint(wm, g, x1, y1, x2, y2, name, false);} /* paints a representation of a weight matrix wherein the height of the letters roughly indicates their relative probability at each base. The image is painted in g in the bounding box defined by the upper left corner x1,y1 and lower right corner x2,y2 */ public void paint(WeightMatrix wm, Graphics g, int x1, int y1, int x2, int y2, String name, boolean drawAxes) { Graphics2D g2d = (Graphics2D)g; wm.toLogOdds(); String label = wm.toString(); if(name!=null) label = name; int w = x2 - x1; int h = y2 - y1; g2d.setRenderingHint( RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_GASP); Font labelFont = new Font("Arial",Font.PLAIN,YLABEL_SIZE); g2d.setFont(labelFont); FontMetrics fontmetrics = g2d.getFontMetrics(); LineMetrics linemetrics = fontmetrics.getLineMetrics(label,g2d); g2d.setColor(Color.BLACK); g2d.drawString(label,x1+X_MARGIN + w/2 - fontmetrics.charsWidth(label.toCharArray(),0,label.length()) / 2,y2-Y_MARGIN); int labelHeight = fontmetrics.getHeight() + Y_MARGIN; int posAxisHeight = drawAxes ? fontmetrics.getHeight() + Y_MARGIN : 0; int boxHeight = h - labelHeight - posAxisHeight; Font baseFont = new Font("Arial",Font.BOLD, boxHeight ); int pixelsPerLetter = (w-X_MARGIN) / wm.length(); double xfactor = ((float)pixelsPerLetter) / baseFont.getSize() * 1.3; //System.err.println("Xfactor is " + xfactor + ", base size is " + baseFont.getSize()+", pixels per letter is "+pixelsPerLetter); if(drawAxes){ int block = (w-X_MARGIN)/wm.length(); int xpos = x1+X_MARGIN+(block/2); for (int pos = 0; pos < wm.length(); pos++) { String pstr = new Integer((pos+1)-wm.getZeroOffset()).toString(); g2d.drawString(pstr,xpos - fontmetrics.stringWidth(pstr)/2,y2-labelHeight-Y_MARGIN); xpos+=block; } g2d.setColor(Color.black); int ypos = y2 - labelHeight-posAxisHeight; int xend = x1+X_MARGIN+(pixelsPerLetter*wm.length()); g2d.drawLine(x1+X_MARGIN, ypos, xend, ypos); g2d.drawLine(x1+X_MARGIN, y1, x1+X_MARGIN, ypos); g2d.drawString("2",x1,y1+fontmetrics.getAscent()); g2d.drawString("1",x1,y1+(boxHeight/2)+fontmetrics.getAscent()); } double vals[] = new double[4]; for (int pos = 0; pos < wm.length(); pos++) { Character[] letters = WeightMatrix.getLetterOrder(wm,pos); double total = 0; int ypos = y2 - labelHeight-posAxisHeight; for (int j = 3; j >= 0; j--) { vals[j] = Math.exp(wm.matrix[pos][letters[j]]); total += vals[j]; } double bits = 0; for (int j = 3; j >= 0; j--) { vals[j] = vals[j] / total; bits -= vals[j] * (Math.log(vals[j]) / Math.log(2)); } double totalscale = (2.0 - bits) / 2.0; for (int j = 3; j >= 0; j--) { if (letters[j] == 'A') { g2d.setColor(AColor); } else if (letters[j] == 'C') { g2d.setColor(CColor); } else if (letters[j] == 'G') { g2d.setColor(GColor); } else if (letters[j] == 'T') { g2d.setColor(TColor); } double val = vals[j]; AffineTransform transform = new AffineTransform(xfactor,0,0,val * totalscale,0,0); Font thisFont = baseFont.deriveFont(transform); int letterHeight = (int) (thisFont.getSize() * val * totalscale); if (letterHeight>1){ g2d.setFont(thisFont); int offset = 0; /*if (letters[j] == 'G') offset = -(int)(pixelsPerLetter*0.05); else if (letters[j] == 'T') offset = (int)(pixelsPerLetter*0.05); */ g2d.drawString(letters[j].toString(),x1+X_MARGIN +offset+ pos * pixelsPerLetter,ypos); }else if (letterHeight==1){ g2d.fillRect(x1+X_MARGIN+ pos*pixelsPerLetter, ypos, (int)(pixelsPerLetter*0.9), letterHeight); } ypos -= letterHeight; } } } }