X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Frenderer%2FAnnotationRenderer.java;h=6d001180ce1a851ec1dae1fbc95ed1a62648efca;hb=0184787284a60624bd112260c0318889ade9fd56;hp=a46aa921c837a3611425049b58e013fb3cd1364a;hpb=27e20b88d0c73ced06e9c20a6e0fa14e27fed179;p=jalview.git diff --git a/src/jalview/renderer/AnnotationRenderer.java b/src/jalview/renderer/AnnotationRenderer.java index a46aa92..6d00118 100644 --- a/src/jalview/renderer/AnnotationRenderer.java +++ b/src/jalview/renderer/AnnotationRenderer.java @@ -1,4 +1,20 @@ - +/* + * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8) + * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with Jalview. If not, see . + */ package jalview.renderer; import jalview.analysis.AAFrequency; @@ -19,23 +35,35 @@ import java.awt.Image; import java.awt.font.LineMetrics; import java.awt.geom.AffineTransform; import java.awt.image.ImageObserver; +import java.util.BitSet; import java.util.Hashtable; import com.stevesoft.pat.Regex; public class AnnotationRenderer { + /** + * flag indicating if timing and redraw parameter info should be output + */ + private final boolean debugRedraw; public AnnotationRenderer() { - // TODO Auto-generated constructor stub + this(false); + } + /** + * Create a new annotation Renderer + * @param debugRedraw flag indicating if timing and redraw parameter info should be output + */ + public AnnotationRenderer(boolean debugRedraw) + { + this.debugRedraw=debugRedraw; } public void drawStemAnnot(Graphics g, Annotation[] row_annotations, int lastSSX, int x, int y, int iconOffset, int startRes, int column, boolean validRes, boolean validEnd) { - g.setColor(STEM_COLOUR); int sCol = (lastSSX / charWidth) + startRes; int x1 = lastSSX; @@ -128,9 +156,25 @@ public class AnnotationRenderer * width of image to render in panel */ private int imgWidth; + /** + * offset to beginning of visible area + */ + private int sOffset; + /** + * offset to end of visible area + */ + private int visHeight; + /** + * indicate if the renderer should only render the visible portion of the annotation given the current view settings + */ + private boolean useClip=true; + /** + * master flag indicating if renderer should ever try to clip. not enabled for jalview 2.8.1 + */ + private boolean canClip=false; - public void drawNotCanonicalAnnot(Graphics g, Color nonCanColor, Annotation[] row_annotations, + public void drawPseudoNode(Graphics g, Color nonCanColor, Annotation[] row_annotations, int lastSSX, int x, int y, int iconOffset, int startRes, int column, boolean validRes, boolean validEnd) { @@ -140,7 +184,7 @@ public class AnnotationRenderer int sCol = (lastSSX / charWidth) + startRes; int x1 = lastSSX; int x2 = (x * charWidth); - Regex closeparen = new Regex("}|]|<|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z"); + Regex closeparen = new Regex("}|]|<|[a-z]"); String dc = (column == 0 || row_annotations[column - 1] == null) ? "" : row_annotations[column - 1].displayCharacter; @@ -197,6 +241,22 @@ public class AnnotationRenderer annotationPanel = annotPanel; fadedImage = annotPanel.getFadedImage(); imgWidth = annotPanel.getFadedImageWidth(); + // visible area for rendering + int[] bounds=annotPanel.getVisibleVRange(); + if (bounds!=null) + { + sOffset = bounds[0]; + visHeight = bounds[1]; + if (visHeight==0) + { + useClip=false; + } else { + useClip=canClip; + } + } else { + useClip=false; + } + updateFromAlignViewport(av); } @@ -276,6 +336,7 @@ public class AnnotationRenderer /** * Render the annotation rows associated with an alignment. + * * @param annotPanel * container frame * @param av @@ -288,19 +349,26 @@ public class AnnotationRenderer * first column that will be drawn * @param endRes * last column that will be drawn - * @return true if the fadedImage was used for any alignment annotation rows currently being calculated + * @return true if the fadedImage was used for any alignment annotation rows + * currently being calculated */ - public boolean drawComponent(AwtRenderPanelI annotPanel, AlignViewportI av, - Graphics g, int activeRow, int startRes, int endRes) + public boolean drawComponent(AwtRenderPanelI annotPanel, + AlignViewportI av, Graphics g, int activeRow, int startRes, + int endRes) { - boolean usedFaded=false; + long stime=System.currentTimeMillis(); + boolean usedFaded = false; // NOTES: // AnnotationPanel needs to implement: ImageObserver, access to // AlignViewport updateFromAwtRenderPanel(annotPanel, av); fm = g.getFontMetrics(); AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation(); - + int temp = 0; + if (aa==null) + { + return false; + } int x = 0, y = 0; int column = 0; char lastSS; @@ -312,16 +380,20 @@ public class AnnotationRenderer boolean centreColLabels, centreColLabelsDef = av .getCentreColumnLabels(); boolean scaleColLabel = false; - boolean[] graphGroupDrawn = new boolean[aa.length]; + + BitSet graphGroupDrawn = new BitSet(); int charOffset = 0; // offset for a label float fmWidth, fmScaling = 1f; // scaling for a label to fit it into a // column. Font ofont = g.getFont(); // \u03B2 \u03B1 + // debug ints + int yfrom=0,f_i=0,yto=0,f_to=0; + boolean clipst=false,clipend=false; for (int i = 0; i < aa.length; i++) { AlignmentAnnotation row = aa[i]; - Annotation[] row_annotations=row.annotations; + Annotation[] row_annotations = row.annotations; if (!row.visible) { continue; @@ -331,10 +403,20 @@ public class AnnotationRenderer scaleColLabel = row.scaleColLabel; lastSS = ' '; lastSSX = 0; + + if (!useClip || ((y-charHeight)=sOffset)) + {// if_in_visible_region + if (!clipst) + { + clipst=true; + yfrom=y; + f_i=i; + } + yto = y; + f_to=i; if (row.graph > 0) { - if (row.graphGroup > -1 && graphGroupDrawn[row.graphGroup]) - { + if (row.graphGroup > -1 && graphGroupDrawn.get(row.graphGroup)) { continue; } @@ -360,7 +442,7 @@ public class AnnotationRenderer if (row.autoCalculated && av.isCalculationInProgress(row)) { y += charHeight; - usedFaded=true; + usedFaded = true; g.drawImage(fadedImage, 0, y - row.height, imgWidth, y, 0, y - row.height, imgWidth, y, annotationPanel); g.setColor(Color.black); @@ -372,22 +454,22 @@ public class AnnotationRenderer /* * else if (annotationPanel.av.updatingConservation && * aa[i].label.equals("Conservation")) { - * + * * y += charHeight; g.drawImage(annotationPanel.fadedImage, 0, y - * row.height, annotationPanel.imgWidth, y, 0, y - row.height, * annotationPanel.imgWidth, y, annotationPanel); - * + * * g.setColor(Color.black); // * g.drawString("Calculating Conservation.....",20, y-row.height/2); - * + * * continue; } else if (annotationPanel.av.updatingConservation && * aa[i].label.equals("Quality")) { - * + * * y += charHeight; g.drawImage(annotationPanel.fadedImage, 0, y - * row.height, annotationPanel.imgWidth, y, 0, y - row.height, * annotationPanel.imgWidth, y, annotationPanel); g.setColor(Color.black); * // / g.drawString("Calculating Quality....",20, y-row.height/2); - * + * * continue; } */ // first pass sets up state for drawing continuation from left-hand column @@ -545,263 +627,50 @@ public class AnnotationRenderer } } - if (ss == 'A') + if (ss >=65) { + // System.out.println("ss="+ss); // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('a') > -1) + if (row_annotations[column].displayCharacter.indexOf(ss+32) > -1) { - ss = 'a'; + + ss = (char) (ss+32); } } + - if (ss == 'B') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('b') > -1) - { - ss = 'b'; - - } - } - - if (ss == 'C') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('c') > -1) - { - ss = 'c'; - - } - } - if (ss == 'D') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('d') > -1) - { - ss = 'd'; - - } - } - if (ss == '1') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('e') > -1) - { - ss = 'e'; - - } - } - if (ss == 'F') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('f') > -1) - { - ss = 'f'; - - } - } - if (ss == 'G') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('g') > -1) - { - ss = 'g'; - - } - } - if (ss == '2') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('h') > -1) - { - ss = 'h'; - - } - } - if (ss == 'I') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('i') > -1) - { - ss = 'i'; - - } - } - if (ss == 'J') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('j') > -1) - { - ss = 'j'; - - } - } - if (ss == 'K') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('k') > -1) - { - ss = 'k'; - - } - } - if (ss == 'L') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('l') > -1) - { - ss = 'l'; - - } - } - if (ss == 'M') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('m') > -1) - { - ss = 'm'; - - } - } - if (ss == 'N') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('n') > -1) - { - ss = 'n'; - - } - } - if (ss == 'O') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('o') > -1) - { - ss = 'o'; - - } - } - if (ss == 'P') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('p') > -1) - { - ss = 'p'; - - } - } - if (ss == 'Q') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('q') > -1) - { - ss = 'q'; - - } - } - if (ss == 'R') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('r') > -1) - { - ss = 'r'; - - } - } - if (ss == 'S') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('s') > -1) - { - ss = 's'; - - } - } - if (ss == 'T') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('t') > -1) - { - ss = 't'; - - } - } - if (ss == 'U') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('u') > -1) - { - ss = 'u'; - - } - } - if (ss == 'V') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('v') > -1) - { - ss = 'v'; - - } - } - if (ss == 'W') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('w') > -1) - { - ss = 'w'; - - } - } - if (ss == 'X') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('x') > -1) - { - ss = 'x'; - - } - } - if (ss == 'Y') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('y') > -1) - { - ss = 'y'; - - } - } - if (ss == 'Z') - { - // distinguish between forward/backward base-pairing - if (row_annotations[column].displayCharacter.indexOf('z') > -1) - { - ss = 'z'; - - } - } if (!validRes || (ss != lastSS)) { + + if (x > -1) { + + + int nb_annot=x-temp; + //System.out.println("\t type :"+lastSS+"\t x :"+x+"\t nbre annot :"+nb_annot); switch (lastSS) { - case 'H': + + case '$': drawHelixAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); break; - case 'E': + case 'µ': drawSheetAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); break; case '(': // Stem case for RNA secondary structure case ')': // and opposite direction + + drawStemAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); + temp=x; break; case '{': case '}': @@ -817,13 +686,13 @@ public class AnnotationRenderer case 'c': case 'D': case 'd': - case '1': + case 'E': case 'e': case 'F': case 'f': case 'G': case 'g': - case '2': + case 'H': case 'h': case 'I': case 'i': @@ -861,16 +730,17 @@ public class AnnotationRenderer case 'y': case 'Z': case 'z': - //System.out.println(lastSS); + Color nonCanColor= getNotCanonicalColor(lastSS); - drawNotCanonicalAnnot(g, nonCanColor, row_annotations, lastSSX, x, y, iconOffset, startRes, + drawPseudoNode(g, nonCanColor, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); + temp=x; break; default: g.setColor(Color.gray); g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth) - lastSSX, 2); - + temp=x; break; } } @@ -916,19 +786,21 @@ public class AnnotationRenderer { switch (lastSS) { - case 'H': + case '$': drawHelixAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); break; - case 'E': + case 'µ': drawSheetAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); break; case 's': case 'S': // Stem case for RNA secondary structure + drawStemAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); + break; case '{': case '}': @@ -944,13 +816,13 @@ public class AnnotationRenderer case 'c': case 'D': case 'd': - case '1': + case 'E': case 'e': case 'F': case 'f': case 'G': case 'g': - case '2': + case 'H': case 'h': case 'I': case 'i': @@ -987,10 +859,13 @@ public class AnnotationRenderer case 'Z': case 'z': //System.out.println(lastSS); + Color nonCanColor = getNotCanonicalColor(lastSS); - drawNotCanonicalAnnot(g,nonCanColor, row_annotations, lastSSX, x, y, iconOffset, startRes, + drawPseudoNode(g,nonCanColor, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); + break; + default: drawGlyphLine(g, row_annotations, lastSSX, x, y, iconOffset, startRes, column, validRes, validEnd); @@ -1002,8 +877,9 @@ public class AnnotationRenderer { if (row.graph == AlignmentAnnotation.LINE_GRAPH) { - if (row.graphGroup > -1 && !graphGroupDrawn[row.graphGroup]) + if (row.graphGroup > -1 && !graphGroupDrawn.get(row.graphGroup)) { + // TODO: JAL-1291 revise rendering model so the graphGroup map is computed efficiently for all visible labels float groupmax = -999999, groupmin = 9999999; for (int gg = 0; gg < aa.length; gg++) { @@ -1016,6 +892,7 @@ public class AnnotationRenderer { aa[gg].visible = false; } + if (aa[gg].graphMax > groupmax) { groupmax = aa[gg].graphMax; @@ -1035,7 +912,7 @@ public class AnnotationRenderer } } - graphGroupDrawn[row.graphGroup] = true; + graphGroupDrawn.set(row.graphGroup); } else { @@ -1049,7 +926,12 @@ public class AnnotationRenderer row.graphMax, y); } } - + } else { + if (clipst && !clipend) + { + clipend = true; + } + }// end if_in_visible_region if (row.graph > 0 && row.hasText) { y += charHeight; @@ -1060,6 +942,27 @@ public class AnnotationRenderer y += aa[i].height; } } + if (debugRedraw) + { + if (canClip) + { + if (clipst) + { + System.err.println("Start clip at : " + yfrom + " (index " + f_i + + ")"); + } + if (clipend) + { + System.err.println("End clip at : " + yto + " (index " + f_to + + ")"); + } + } + ; + System.err.println("Annotation Rendering time:" + + (System.currentTimeMillis() - stime)); + } + ; + return !usedFaded; } @@ -1088,7 +991,7 @@ public class AnnotationRenderer { g.setColor(SHEET_COLOUR); - if (!validEnd || !validRes || row==null || row[column] == null + if (!validEnd || !validRes || row == null || row[column] == null || row[column].secondaryStructure != 'E') { g.fillRect(lastSSX, y + 4 + iconOffset, @@ -1107,9 +1010,9 @@ public class AnnotationRenderer } - public void drawHelixAnnot(Graphics g, Annotation[] row, - int lastSSX, int x, int y, int iconOffset, int startRes, - int column, boolean validRes, boolean validEnd) + public void drawHelixAnnot(Graphics g, Annotation[] row, int lastSSX, + int x, int y, int iconOffset, int startRes, int column, + boolean validRes, boolean validEnd) { g.setColor(HELIX_COLOUR); @@ -1167,8 +1070,9 @@ public class AnnotationRenderer g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8); } - public void drawLineGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes, - int eRes, int y, float min, float max, int graphHeight) + public void drawLineGraph(Graphics g, AlignmentAnnotation _aa, + Annotation[] aa_annotations, int sRes, int eRes, int y, + float min, float max, int graphHeight) { if (sRes > aa_annotations.length) { @@ -1256,8 +1160,9 @@ public class AnnotationRenderer } } - public void drawBarGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes, - int eRes, float min, float max, int y) + public void drawBarGraph(Graphics g, AlignmentAnnotation _aa, + Annotation[] aa_annotations, int sRes, int eRes, float min, + float max, int y) { if (sRes > aa_annotations.length) { @@ -1393,7 +1298,7 @@ public class AnnotationRenderer // g.drawRect(x*av.charWidth, (int)ht, av.charWidth, // (int)(scl)); // g.setColor(profcolour.findColour(dc[0]).darker()); - g.setColor(profcolour.findColour(dc[0], column,null)); + g.setColor(profcolour.findColour(dc[0], column, null)); hght = (ht + (scl - lm.getDescent() - lm.getBaselineOffsets()[lm .getBaselineIndex()])); @@ -1414,15 +1319,16 @@ public class AnnotationRenderer BasicStroke.JOIN_ROUND, 3f, new float[] { 5f, 3f }, 0f)); - y2 = (int) (y - ((_aa.threshold.value - min) / range) * _aa.graphHeight); + y2 = (int) (y - ((_aa.threshold.value - min) / range) + * _aa.graphHeight); g.drawLine(0, y2, (eRes - sRes) * charWidth, y2); g2.setStroke(new BasicStroke()); } } // used by overview window - public void drawGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int width, - int y, int sRes, int eRes) + public void drawGraph(Graphics g, AlignmentAnnotation _aa, + Annotation[] aa_annotations, int width, int y, int sRes, int eRes) { eRes = Math.min(eRes, aa_annotations.length); g.setColor(Color.white); @@ -1459,122 +1365,122 @@ public class AnnotationRenderer { case '{': case '}': - return Color.cyan; + return new Color(255,125,5); case '[': case ']': - return Color.green; + return new Color(245,115,10); case '>': case '<': - return Color.magenta; + return new Color(235,135,15); case 'A': case 'a': - return Color.orange; + return new Color(225,105,20); case 'B': case 'b': - return Color.pink; + return new Color(215,145,30); case 'C': case 'c': - return Color.red; + return new Color(205,95,35); case 'D': case 'd': - return Color.yellow; + return new Color(195,155,45); - case '1': + case 'E': case 'e': - return Color.black; + return new Color(185,85,55); case 'F': case 'f': - return Color.darkGray; + return new Color(175,165,65); case 'G': case 'g': - return Color.gray; + return new Color(170,75,75); - case '2': + case 'H': case 'h': - return Color.lightGray; + return new Color(160,175,85); case 'I': case 'i': - return Color.white; + return new Color(150,65,95); case 'J': case 'j': - return Color.cyan; + return new Color(140,185,105); case 'K': case 'k': - return Color.magenta; + return new Color(130,55,110); case 'L': case 'l': - return Color.orange; + return new Color(120,195,120); case 'M': case 'm': - return Color.red; + return new Color(110,45,130); case 'N': case 'n': - return Color.yellow; + return new Color(100,205,140); case 'O': case 'o': - return Color.pink; + return new Color(90,35,150); case 'P': case 'p': - return Color.black; + return new Color(85,215,160); case 'Q': case 'q': - return Color.blue; + return new Color(75,25,170); case 'R': case 'r': - return Color.cyan; + return new Color(65,225,180); case 'S': case 's': - return Color.magenta; + return new Color(55,15,185); case 'T': case 't': - return Color.darkGray; + return new Color(45,235,195); case 'U': case 'u': - return Color.yellow; + return new Color(35,5,205); case 'V': case 'v': - return Color.blue; + return new Color(25,245,215); case 'W': case 'w': - return Color.orange; + return new Color(15,0,225); case 'X': case 'x': - return Color.magenta; + return new Color(10,255,235); case 'Y': case 'y': - return Color.blue; + return new Color(5,150,245); case 'Z': case 'z': - return Color.blue; + return new Color(0,80,255); default : - System.out.println("This is not a interaction"); + System.out.println("This is not a interaction : "+lastss); return null; }