[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