[Biojava-l] FrameStopRenderer.java version 0.1 (warning: contains source)
Matthew Pocock
mrp@sanger.ac.uk
Tue, 15 May 2001 12:39:51 +0100
Hi.
I'm off for a long weekend, but I'll look at this properly early next
week. There are three constants on StrandedFeature that define
strandedness (POSITIVE, NEGATIVE, UNKNOWN) which may be more apropreate
than the boolean constructor arg.
The code looks good to me. Great work.
M
Dr S.M. Huen wrote:
> I've just written the first version of a frame stop renderer which will
> form the basis of my six-frame stop renderer later. i thought I'd put it
> out for inspection and comments.
>
> There is a private variable scaleTreshold to prevent this class attempting
> to trigger the download of the entire chromosome sequence! Perhaps I
> ought to allow it to be set at object creation time?
>
> To use, for now add something like this to SequenceViewer:-
> zml.addRenderer(new FrameStopRenderer(0, true));
> zml.addRenderer(new FrameStopRenderer(1, true));
> zml.addRenderer(new FrameStopRenderer(2, true));
> zml.addRenderer(new FrameStopRenderer(0, false));
> zml.addRenderer(new FrameStopRenderer(1, false));
> zml.addRenderer(new FrameStopRenderer(2, false));
>
> This class will eventually be wrapped in a single six-frame renderer
> class when I eventually get started on the six-frame ziggy renderer.
>
> The first integer parameter specifies the modulo of the frame, the second,
> the strand to be examined (isTopStrand).
>
> There's a optimisation so that at small scales, it only searches far
> enough to determine if there's a stop within a pixel and skips on to the
> next pixel when that's the case. Makes a big difference at low
> resolution!
>
> Could I hold off learning how to do CVS commits for the time being and
> have someone handle that for me? I don't have much coding time right
> now and it's doing one or the other. I promise to learn it later: the last
> time I had a look at Cyclic's manual on it, it had me mystified.
>
> Thanks,
> David Huen, Dept. of Genetics, Univ. of Cambridge.
>
>
>
>
>
> ------------------------------------------------------------------------
>
> /*
> * BioJava development code
> *
> * This code may be freely distributed and modified under the
> * terms of the GNU Lesser General Public Licence. This should
> * be distributed with the code. If you do not have a copy,
> * see:
> *
> * http://www.gnu.org/copyleft/lesser.html
> *
> * Copyright for this code is held jointly by the individual
> * authors. These should be listed in @author doc comments.
> *
> * For more information on the BioJava project and its aims,
> * or to join the biojava-l mailing list, visit the home page
> * at:
> *
> * http://www.biojava.org/
> *
> */
>
> package org.biojava.bio.gui.sequence;
>
> import java.util.*;
> import java.awt.*;
> import java.awt.event.*;
> import java.awt.geom.*;
>
> import org.biojava.bio.*;
> import org.biojava.bio.seq.*;
> import org.biojava.bio.symbol.*;
> import org.biojava.bio.gui.*;
>
> import java.util.List;
>
> // The graphics model in Java
> // drawing space -> applet space -> device space
> // All operations are cumulative, including translates
> // translates will move drawing rightward/downward for any supplied value
>
> /**
> * Render the symbols of a sequence.
> *
> * @author David Huen
> */
>
>
> public class FrameStopRenderer implements SequenceRenderer {
> private double depth = 25.0;
> private double margin = 5.0;
> private double scaleThreshold = 0.005;
> private double bandWidth = depth - margin;
> private int moduloFrame;
> private boolean isTopStrand;
>
> public FrameStopRenderer(int moduloFrame, boolean isTopStrand) {
> this.moduloFrame = moduloFrame;
> this.isTopStrand = isTopStrand;
> }
>
> public double getDepth(SequenceRenderContext src) {
> // an arbitrary limit is set here to prevent excessive sequence
> // download.
> if (src.getScale() < scaleThreshold) return 0;
> else return depth + 1.0;
> }
>
> public double getMinimumLeader(SequenceRenderContext src) {
> return 0.0;
> }
>
> public double getMinimumTrailer(SequenceRenderContext src) {
> return 0.0;
> }
>
> private boolean isStop(SymbolList seq,
> int base,
> boolean searchTopStrand) {
> // 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 (searchTopStrand) {
> // 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 {
> // 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; base < maxS; base += 3) {
> // check for stop
> if (!isStop(seq, base, isTopStrand)) continue;
>
> // we have a stop, render a line
> double gPos = src.sequenceToGraphics(base);
> g.drawLine((int) gPos, (int) 0,
> (int) gPos, (int) bandWidth);
>
> // do I call it quits now?
> if (onceOnly) return;
> }
> }
>
> public void paint(
> Graphics2D g,
> SequenceRenderContext src
> ) {
> // moduloFrame indicates the frame that we are to render.
> // the absolute value indicates the mod(3) value that the
> // triplets begin at. The sign indicates whether the top or
> // bottom strand is to be considered.
>
> double scale = src.getScale();
>
> // this is a completely arbitrary limit to stop my viewer
> // from attempting to trigger the download of HUGE amounts
> // of sequence.
> if (scale < scaleThreshold) return;
>
> // could we get more than one stop per pixel at the current
> // scale?
> if (scale < 0.10) {
> // yes, we can. Iterate thru' graphics space.
> // we will check each pixel
> RangeLocation rangeS = src.getRange();
> int minLocS = rangeS.getMin();
> int maxLocS = rangeS.getMax();
> int minP = (int) src.sequenceToGraphics(src.getRange().getMin());
> int maxP = (int) src.sequenceToGraphics(src.getRange().getMax());
> // System.out.println("FrameStopRenderer minP, maxP: " + minP + " " + maxP);
> for (int currP = minP; currP < maxP; currP++) {
> // compute extent of sequence
> // clamp values to sequence range
> int minS = Math.max((int) src.graphicsToSequence(currP), minLocS);
> int maxS = Math.min(((int) src.graphicsToSequence(currP + 1) - 1), maxLocS);
> // System.out.println("FrameStopRenderer range: " + rangeS);
> //System.out.println("FrameStopRenderer minS maxS currP: " + minS + " " + maxS + " " + currP);
> RangeLocation rangeForPixel = new RangeLocation(minS, maxS);
>
> // now draw it if necessary
> renderOneFrame(g, src, rangeForPixel, true);
> }
> }
> else {
> // no we can't. Iterate thru' sequence.
> renderOneFrame(g, src, src.getRange(), false);
> }
> }
> /*
> public void paint(
> Graphics2D g,
> SequenceRenderContext src
> ) {
> SymbolList seq = src.getSymbols();
> int direction = src.getDirection();
>
> Rectangle2D oldClip = g.getClipBounds();
> g.setColor(Color.black);
> double scale = src.getScale();
> }
> */
>
> public SequenceViewerEvent processMouseEvent(
> SequenceRenderContext src,
> MouseEvent me,
> List path
> ) {
> path.add(this);
> int sPos = src.graphicsToSequence(me.getPoint());
> return new SequenceViewerEvent(this, null, sPos, me, path);
> }
> }
> FrameStopRenderer.java
>
> Content-Description:
>
> Source for FrameStopRenderer
> Content-Type:
>
> TEXT/PLAIN
> Content-Encoding:
>
> BASE64