package org.seqcode.projects.seqview.paintable; import java.awt.*; import java.util.*; import org.seqcode.genome.location.Region; import org.seqcode.gseutils.*; import org.seqcode.projects.seqview.model.RegionMapperModel; /* paints some subset of nucleotides blue and some subset red. Default is blue = GC and red = AT */ public class GCContentPainter extends RegionPaintable { private RegionMapperModel<String> model; private GCContentProperties props; public GCContentPainter(RegionMapperModel<String> model) { super(); this.model = model; props = new GCContentProperties(); model.addEventListener(this); } public GCContentProperties getProperties() { return props;} public void cleanup() { super.cleanup(); model.removeEventListener(this); } public void removeEventListener(Listener<EventObject> l) { super.removeEventListener(l); if (!hasListeners()) { model.removeEventListener(this); } } public synchronized void eventRegistered(EventObject e) { if (e.getSource() == model && model.isReady()) { setCanPaint(true); setWantsPaint(true); notifyListeners(); // System.err.println("GCCP got event and notified"); } } public int getMaxVertSpace() { return 40; } public int getMinVertSpace() { return 40; } public void paintItem(Graphics2D g, int x1, int y1, int x2, int y2) { if (!canPaint()) { return; } int w = x2 - x1; double h = y2 - y1; Region region = getRegion(); int regionstart = region.getStart(), regionend = region.getEnd(); int regionwidth = regionend - regionstart; int pixwidth = props.PixWidth; if (pixwidth < 1) { pixwidth = 1; } String wholestring = model.getResults(); if (wholestring == null) { return; } char[] chars = wholestring.toUpperCase().toCharArray(); String bluestring = props.BlueBases; char[] bluechar = new char[bluestring.length()]; for (int i = 0; i < bluechar.length; i++) { bluechar[i] = bluestring.charAt(i); } String redstring = props.RedBases; char[] redchar = new char[redstring.length()]; for (int i = 0; i < redchar.length; i++) { redchar[i] = redstring.charAt(i); } float expfrac = (float)bluechar.length / ((float)redchar.length + (float)bluechar.length); for (int i = x1; i < x2; i += pixwidth) { int rstart = (int)Math.round((i - x1) * regionwidth / ((double)w)); int rend = (int)Math.round((i - x1 + pixwidth) * regionwidth / ((double)w)); if (rend >= chars.length) { rend = chars.length - 1 ; } int blue = 0; int red = 0; for (int j = rstart; j <= rend; j++) { for (int k = 0; k < bluechar.length; k++) { if (chars[j] == bluechar[k]) { blue++; break; } } for (int k = 0; k < redchar.length; k++) { if (chars[j] == redchar[k]) { red++; break; } } } if (red + blue == 0) {continue;} float frac = (float)blue / ((float)red + (float) blue); if (frac > expfrac) { g.setColor(Color.BLUE); int fill = (int) (h * ((frac - expfrac) / (1.0 - expfrac))); g.fillRect(i,y1,pixwidth,fill); } else { g.setColor(Color.RED); int fill = (int)(h * ((expfrac - frac) / expfrac)); g.fillRect(i,y1,pixwidth,fill); } } if (props.DrawTrackLabel) { g.setColor(Color.BLACK); g.drawString(getLabel(),x1,y2); } } }