[Biojava-dev] About the six frame renderer again.
hywang at scbit.org
hywang at scbit.org
Tue Sep 23 22:55:18 EDT 2003
Hi,
I have wrote a renderer for six frame view based on your
SixFrameRenderer, it can render a frame with the input
parameter:
moduloFrame
which could only be 0,1,2 for the different start base of translation.
strand
which stands for the positive or negtive strand.
I can get the expected effect of six lines of Amino arrays in zoom in mode,
and different sticks drawed for stop codon in zoom out mode.
But if a sequence is very long, for example about 100k,
the scroll action in zoom in mode will be a bit slow.
I think that is probably because of the wholy repainting all the amino
strings, so I have tried getclip() function in the paint() method
,but the improvement seemed to be not a satisfaction.
Any help would be greatly appreciated and would stop me pulling anymore hair
out!
Thanks.
Best Wishes !
Hywang
import org.biojava.utils.AbstractChangeable;
import org.biojava.bio.gui.sequence.SequenceRenderer;
import org.biojava.bio.gui.sequence.SequenceRenderContext;
import org.biojava.bio.gui.sequence.SequenceViewerEvent;
import org.biojava.bio.seq.StrandedFeature;
import org.biojava.bio.seq.DNATools;
import org.biojava.bio.seq.RNATools;
import org.biojava.bio.seq.ProteinTools;
import org.biojava.bio.seq.io.SymbolTokenization;
import org.biojava.bio.symbol.*;
import org.biojava.bio.BioRuntimeException;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: administrator
* Date: 2003-9-5
* Time: 10:03:58
* To change this template use Options | File Templates.
*/
public class OneFrameRenderer extends AbstractChangeable
implements SequenceRenderer {
private double depth = 14.0;
private double blockWidth = 12.0;
private Paint fontcolor = Color.black;
private Paint linecolor = Color.black;
private int moduloFrame;
private StrandedFeature.Strand strand;
public OneFrameRenderer(int moduloFrame, StrandedFeature.Strand strand) {
this.moduloFrame = moduloFrame;
this.strand = strand;
}
public double getDepth(SequenceRenderContext context) {
return depth + 1.0;
}
public double getMinimumLeader(SequenceRenderContext context) {
return 0.0;
}
public double getMinimumTrailer(SequenceRenderContext context) {
return 0.0;
}
public void paint(Graphics2D g2, SequenceRenderContext context) {
//Rectangle2D prevClip = g2.getClipBounds(); //seems no use
AffineTransform prevTransform = g2.getTransform();
g2.setPaint(fontcolor);
Font font = context.getFont();
Rectangle2D maxCharBounds =
font.getMaxCharBounds(g2.getFontRenderContext());
double scale = context.getScale();
if (scale >= (maxCharBounds.getWidth() * 0.2) &&
scale >= (maxCharBounds.getHeight() * 0.2)) {
double xFontOffset = 0.0;
double yFontOffset = 0.0;
// These offsets are not set quite correctly yet. The
// Rectangle2D from getMaxCharBounds() seems slightly
// off. The "correct" application of translations based on
// the Rectangle2D seem to give the wrong results. The
// values below are mostly fudges.
if (context.getDirection() == SequenceRenderContext.HORIZONTAL) {
xFontOffset = maxCharBounds.getCenterX() * 0.25;
yFontOffset = -maxCharBounds.getCenterY() + (depth * 0.5);
}
else {
xFontOffset = -maxCharBounds.getCenterX() + (depth * 0.5);
yFontOffset = -maxCharBounds.getCenterY() * 3.0;
}
SymbolList seq1 = context.getSymbols();
if (strand == StrandedFeature.NEGATIVE) {
try {
seq1 = DNATools.reverseComplement(seq1);
} catch (Exception ex) {
throw new BioRuntimeException(ex);
}
}
SymbolList seq = seq1.subList(1 + moduloFrame, seq1.length() -
(seq1.length() - moduloFrame) % 3);
//int min = context.getRange().getMin();
int min = 1;
//int max = context.getRange().getMax();
int max = seq.length();
//transcribe to RNA
SymbolTokenization toke = null;
TranslationTable eup =
RNATools.getGeneticCode(TranslationTable.UNIVERSAL);
Alphabet protein_al = ProteinTools.getAlphabet();
SymbolList protein = null;
try {
toke = protein_al.getTokenization("token");
seq = RNATools.transcribe(seq);
//veiw the RNA sequence as codons, this is done internally by
RNATool.translate()
seq = SymbolListViews.windowedSymbolList(seq, 3);
//translate
protein = SymbolListViews.translate(seq, eup);
}
catch (Exception ex) {
throw new BioRuntimeException(ex);
}
//System.out.println(protein.seqString());
//g2.drawString(protein.seqString(),(float)context.sequenceToGraphics(1),(fl
oat)yFontOffset); //---the same slow
for (int sPos = min; sPos <= max; sPos++) {
if (context.getDirection() ==
SequenceRenderContext.HORIZONTAL && sPos % 3 == 0) {
double gPos = context.sequenceToGraphics(sPos - 1 +
moduloFrame);
String s = "*";
try {
s = toke.tokenizeSymbol(protein.symbolAt(sPos / 3));
//s = protein.symbolAt(sPos).toString();
}
catch (Exception ex) {
// We'll ignore the case of not being able to
tokenize it
}
g2.drawString(s,(float)(gPos+
xFontOffset),(float)yFontOffset);
/*
char [] tmpc = s.toCharArray();
g2.drawChars(tmpc,0,1,
(int) (gPos),// + xFontOffset),
(int) yFontOffset);*/
}
}
}
else {
renderOneFrame(g2, context, context.getRange(), false);
}
//g2.setClip(prevClip);// ---seems no use
g2.setTransform(prevTransform);
}
public SequenceViewerEvent processMouseEvent(SequenceRenderContext
context,
MouseEvent me,
List path) {
path.add(this);
int sPos = context.graphicsToSequence(me.getPoint());
return new SequenceViewerEvent(this, null, sPos, me, path);
}
private boolean isStop(SymbolList seq,
int base,
StrandedFeature.Strand strand) {
// tests whether there is a stop at given location.
// the triplet is either base, +1, +2 or -1, -2
// depending on the strand searched
if (strand == StrandedFeature.POSITIVE) {
// check that search does not exceed bounds
if (base + 2 > seq.length()) return false;
// search top strand
// first base must be t
if (seq.symbolAt(base) != DNATools.t()) return false;
// second base cannot be c or t
if (seq.symbolAt(base + 1) == DNATools.c()) return false;
if (seq.symbolAt(base + 1) == DNATools.t()) return false;
// if second base is g, the third must be a
if (seq.symbolAt(base + 1) == DNATools.g()) {
if (seq.symbolAt(base + 2) != DNATools.a()) return false;
} else {
// second base is a: third must be a or g.
if (seq.symbolAt(base + 2) == DNATools.c()) return false;
if (seq.symbolAt(base + 2) == DNATools.t()) return false;
}
// oh well, must be a stop, innit?
return true;
} else {
// check bounds
if (base - 2 < 1) return false;
// search bottom strand
// first base must be t
if (seq.symbolAt(base) != DNATools.a()) return false;
// second base cannot be c or t on reverse strand
if (seq.symbolAt(base - 1) == DNATools.a()) return false;
if (seq.symbolAt(base - 1) == DNATools.g()) return false;
// if second base is g, the third must be a
if (seq.symbolAt(base - 1) == DNATools.c()) {
if (seq.symbolAt(base - 2) != DNATools.t()) return false;
} else {
// second base is a: third must be a or g.
if (seq.symbolAt(base - 2) == DNATools.a()) return false;
if (seq.symbolAt(base - 2) == DNATools.g()) return false;
}
// ach! a stop!
return true;
}
}
private void renderOneFrame(
Graphics2D g,
SequenceRenderContext src,
RangeLocation range,
boolean onceOnly) {
// method to draw by checking succeeding triplets for
// stop codons.
// write it for horizontal rendering first.
SymbolList seq = src.getSymbols();
// get extent of sequence to render
// hope it agrees with clip region!
int minS = range.getMin();
int maxS = range.getMax();
// we start at the first triplet whose first base is within
// the range.
/* if (minS % 3 > moduloFrame) {
// first triplet of my frame is in next mod-zero triplet
minS = (minS / 3 + 1) * 3 + moduloFrame;
} else if (minS % 3 != moduloFrame) {
// first triplet is in current mod-zero triplet
minS = (minS / 3) * 3 + moduloFrame;
}*/
// now we search every triplet from minS upward seeking stops.
for (int base = minS+moduloFrame; base <= maxS; base += 3) {
// check for stop
if (!isStop(seq, base, strand)) continue;
// we have a stop, render a line
drawLine(g, src, base, strand);
// do I call it quits now?
if (onceOnly) return;
}
}
public void drawLine(
Graphics2D g,
SequenceRenderContext src,
int base,
StrandedFeature.Strand strand) {
Paint prevPaint = g.getPaint();
g.setPaint(linecolor);
// compute the frame to use.
//int moduloFrame = base%3;
// System.out.println("drawLine: base,strand,modulo" + base + " " +
strand + " " + moduloFrame);
// get required offset for frame
double offset = 0;//modi by hywang
// compute position of line to be drawn
int lineP = (int) src.sequenceToGraphics(base);
// draw the line
if (src.getDirection() == src.HORIZONTAL) {
g.drawLine(lineP, (int) offset,
lineP, (int) (offset + blockWidth));
} else {
g.drawLine((int) offset, lineP,
(int) (offset + blockWidth), lineP);
}
g.setPaint(prevPaint);
}
}
More information about the biojava-dev
mailing list