2 package jalview.renderer;
4 import jalview.analysis.AAFrequency;
5 import jalview.analysis.StructureFrequency;
6 import jalview.api.AlignViewportI;
7 import jalview.datamodel.AlignmentAnnotation;
8 import jalview.datamodel.Annotation;
9 import jalview.datamodel.ColumnSelection;
10 import jalview.schemes.ColourSchemeI;
12 import java.awt.BasicStroke;
13 import java.awt.Color;
15 import java.awt.FontMetrics;
16 import java.awt.Graphics;
17 import java.awt.Graphics2D;
18 import java.awt.Image;
19 import java.awt.font.LineMetrics;
20 import java.awt.geom.AffineTransform;
21 import java.awt.image.ImageObserver;
22 import java.util.Hashtable;
24 import com.stevesoft.pat.Regex;
26 public class AnnotationRenderer
29 public AnnotationRenderer()
31 // TODO Auto-generated constructor stub
34 public void drawStemAnnot(Graphics g, Annotation[] row_annotations,
35 int lastSSX, int x, int y, int iconOffset, int startRes,
36 int column, boolean validRes, boolean validEnd)
39 g.setColor(STEM_COLOUR);
40 int sCol = (lastSSX / charWidth) + startRes;
42 int x2 = (x * charWidth);
43 Regex closeparen = new Regex("(\\))");
45 String dc = (column == 0 || row_annotations[column - 1] == null) ? ""
46 : row_annotations[column - 1].displayCharacter;
48 boolean diffupstream = sCol == 0 || row_annotations[sCol - 1] == null
49 || !dc.equals(row_annotations[sCol - 1].displayCharacter);
50 boolean diffdownstream = !validRes || !validEnd
51 || row_annotations[column] == null
52 || !dc.equals(row_annotations[column].displayCharacter);
53 // System.out.println("Column "+column+" diff up: "+diffupstream+" down:"+diffdownstream);
54 // If a closing base pair half of the stem, display a backward arrow
55 if (column > 0 && closeparen.search(dc))
59 // if (validRes && column>1 && row_annotations[column-2]!=null &&
60 // dc.equals(row_annotations[column-2].displayCharacter))
62 g.fillPolygon(new int[]
63 { lastSSX + 5, lastSSX + 5, lastSSX }, new int[]
64 { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
75 // display a forward arrow
78 g.fillPolygon(new int[]
79 { x2 - 5, x2 - 5, x2 }, new int[]
80 { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
89 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 7);
92 private int charWidth, endRes, charHeight;
94 private boolean validCharWidth, hasHiddenColumns;
96 private FontMetrics fm;
98 private final boolean MAC = new jalview.util.Platform().isAMac();
100 boolean av_renderHistogram = true, av_renderProfile = true,
101 av_normaliseProfile = false;
103 ColourSchemeI profcolour = null;
105 private ColumnSelection columnSelection;
107 private Hashtable[] hconsensus;
109 private Hashtable[] hStrucConsensus;
111 private boolean av_ignoreGapsConsensus;
114 * attributes set from AwtRenderPanelI
117 * old image used when data is currently being calculated and cannot be
120 private Image fadedImage;
123 * panel being rendered into
125 private ImageObserver annotationPanel;
128 * width of image to render in panel
130 private int imgWidth;
133 public void drawNotCanonicalAnnot(Graphics g, Color nonCanColor, Annotation[] row_annotations,
134 int lastSSX, int x, int y, int iconOffset, int startRes,
135 int column, boolean validRes, boolean validEnd)
137 //System.out.println(nonCanColor);
139 g.setColor(nonCanColor);
140 int sCol = (lastSSX / charWidth) + startRes;
142 int x2 = (x * charWidth);
143 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");
145 String dc = (column == 0 || row_annotations[column - 1] == null) ? ""
146 : row_annotations[column - 1].displayCharacter;
148 boolean diffupstream = sCol == 0 || row_annotations[sCol - 1] == null
149 || !dc.equals(row_annotations[sCol - 1].displayCharacter);
150 boolean diffdownstream = !validRes || !validEnd
151 || row_annotations[column] == null
152 || !dc.equals(row_annotations[column].displayCharacter);
153 // System.out.println("Column "+column+" diff up: "+diffupstream+" down:"+diffdownstream);
154 // If a closing base pair half of the stem, display a backward arrow
155 if (column > 0 && closeparen.search(dc))// closeletter_b.search(dc)||closeletter_c.search(dc)||closeletter_d.search(dc)||closecrochet.search(dc)) )
159 // if (validRes && column>1 && row_annotations[column-2]!=null &&
160 // dc.equals(row_annotations[column-2].displayCharacter))
162 g.fillPolygon(new int[]
163 { lastSSX + 5, lastSSX + 5, lastSSX }, new int[]
164 { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
175 // display a forward arrow
178 g.fillPolygon(new int[]
179 { x2 - 5, x2 - 5, x2 }, new int[]
180 { y + iconOffset, y + 14 + iconOffset, y + 8 + iconOffset }, 3);
189 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 7);
191 // public void updateFromAnnotationPanel(FontMetrics annotFM, AlignViewportI
193 public void updateFromAwtRenderPanel(AwtRenderPanelI annotPanel,
196 fm = annotPanel.getFontMetrics();
197 annotationPanel = annotPanel;
198 fadedImage = annotPanel.getFadedImage();
199 imgWidth = annotPanel.getFadedImageWidth();
200 updateFromAlignViewport(av);
203 public void updateFromAlignViewport(AlignViewportI av)
205 charWidth = av.getCharWidth();
206 endRes = av.getEndRes();
207 charHeight = av.getCharHeight();
208 hasHiddenColumns = av.hasHiddenColumns();
209 validCharWidth = av.isValidCharWidth();
210 av_renderHistogram = av.isShowConsensusHistogram();
211 av_renderProfile = av.isShowSequenceLogo();
212 av_normaliseProfile = av.isNormaliseSequenceLogo();
213 profcolour = av.getGlobalColourScheme();
214 if (profcolour == null)
216 // Set the default colour for sequence logo if the alignnent has no
218 profcolour = av.getAlignment().isNucleotide() ? new jalview.schemes.NucleotideColourScheme()
219 : new jalview.schemes.ZappoColourScheme();
221 columnSelection = av.getColumnSelection();
222 hconsensus = av.getSequenceConsensusHash();// hconsensus;
223 hStrucConsensus = av.getRnaStructureConsensusHash(); // hStrucConsensus;
224 av_ignoreGapsConsensus = av.getIgnoreGapsConsensus();
227 public int[] getProfileFor(AlignmentAnnotation aa, int column)
229 // TODO : consider refactoring the global alignment calculation
230 // properties/rendering attributes as a global 'alignment group' which holds
231 // all vis settings for the alignment as a whole rather than a subset
233 if (aa.autoCalculated && aa.label.startsWith("Consensus"))
235 if (aa.groupRef != null && aa.groupRef.consensusData != null
236 && aa.groupRef.isShowSequenceLogo())
238 return AAFrequency.extractProfile(
239 aa.groupRef.consensusData[column],
240 aa.groupRef.getIgnoreGapsConsensus());
242 // TODO extend annotation row to enable dynamic and static profile data to
244 if (aa.groupRef == null && aa.sequenceRef == null && av_renderProfile)
246 return AAFrequency.extractProfile(hconsensus[column],
247 av_ignoreGapsConsensus);
252 if (aa.autoCalculated && aa.label.startsWith("StrucConsensus"))
254 // TODO implement group structure consensus
256 * if (aa.groupRef != null && aa.groupRef.consensusData != null &&
257 * aa.groupRef.isShowSequenceLogo()) { //TODO check what happens for
258 * group selections return StructureFrequency.extractProfile(
259 * aa.groupRef.consensusData[column], aa.groupRef
260 * .getIgnoreGapsConsensus()); }
262 // TODO extend annotation row to enable dynamic and static profile data
265 if (aa.groupRef == null && aa.sequenceRef == null
266 && av_renderProfile && hStrucConsensus != null
267 && hStrucConsensus.length > column)
269 return StructureFrequency.extractProfile(hStrucConsensus[column],
270 av_ignoreGapsConsensus);
278 * Render the annotation rows associated with an alignment.
282 * data and view settings to render
284 * destination for graphics
286 * row where a mouse event occured (or -1)
288 * first column that will be drawn
290 * last column that will be drawn
291 * @return true if the fadedImage was used for any alignment annotation rows currently being calculated
293 public boolean drawComponent(AwtRenderPanelI annotPanel, AlignViewportI av,
294 Graphics g, int activeRow, int startRes, int endRes)
296 boolean usedFaded=false;
298 // AnnotationPanel needs to implement: ImageObserver, access to
300 updateFromAwtRenderPanel(annotPanel, av);
301 fm = g.getFontMetrics();
302 AlignmentAnnotation[] aa = av.getAlignment().getAlignmentAnnotation();
309 boolean validRes = false;
310 boolean validEnd = false;
311 boolean labelAllCols = false;
312 boolean centreColLabels, centreColLabelsDef = av
313 .getCentreColumnLabels();
314 boolean scaleColLabel = false;
315 boolean[] graphGroupDrawn = new boolean[aa.length];
316 int charOffset = 0; // offset for a label
317 float fmWidth, fmScaling = 1f; // scaling for a label to fit it into a
319 Font ofont = g.getFont();
321 for (int i = 0; i < aa.length; i++)
323 AlignmentAnnotation row = aa[i];
324 Annotation[] row_annotations=row.annotations;
329 centreColLabels = row.centreColLabels || centreColLabelsDef;
330 labelAllCols = row.showAllColLabels;
331 scaleColLabel = row.scaleColLabel;
336 if (row.graphGroup > -1 && graphGroupDrawn[row.graphGroup])
341 // this is so that we draw the characters below the graph
346 iconOffset = charHeight - fm.getDescent();
350 else if (row.hasText)
352 iconOffset = charHeight - fm.getDescent();
360 if (row.autoCalculated && av.isCalculationInProgress(row))
364 g.drawImage(fadedImage, 0, y - row.height, imgWidth, y, 0, y
365 - row.height, imgWidth, y, annotationPanel);
366 g.setColor(Color.black);
367 // g.drawString("Calculating "+aa[i].label+"....",20, y-row.height/2);
373 * else if (annotationPanel.av.updatingConservation &&
374 * aa[i].label.equals("Conservation")) {
376 * y += charHeight; g.drawImage(annotationPanel.fadedImage, 0, y -
377 * row.height, annotationPanel.imgWidth, y, 0, y - row.height,
378 * annotationPanel.imgWidth, y, annotationPanel);
380 * g.setColor(Color.black); //
381 * g.drawString("Calculating Conservation.....",20, y-row.height/2);
383 * continue; } else if (annotationPanel.av.updatingConservation &&
384 * aa[i].label.equals("Quality")) {
386 * y += charHeight; g.drawImage(annotationPanel.fadedImage, 0, y -
387 * row.height, annotationPanel.imgWidth, y, 0, y - row.height,
388 * annotationPanel.imgWidth, y, annotationPanel); g.setColor(Color.black);
389 * // / g.drawString("Calculating Quality....",20, y-row.height/2);
393 // first pass sets up state for drawing continuation from left-hand column
395 x = (startRes == 0) ? 0 : -1;
396 while (x < endRes - startRes)
398 if (hasHiddenColumns)
400 column = columnSelection.adjustForHiddenColumns(startRes + x);
401 if (column > row_annotations.length - 1)
408 column = startRes + x;
411 if ((row_annotations == null) || (row_annotations.length <= column)
412 || (row_annotations[column] == null))
424 g.setColor(Color.red);
426 if (columnSelection != null)
428 for (int n = 0; n < columnSelection.size(); n++)
430 int v = columnSelection.columnAt(n);
434 g.fillRect(x * charWidth, y, charWidth, charHeight);
439 if (!row.isValidStruc())
441 g.setColor(Color.orange);
442 g.fillRect((int) row.getInvalidStrucPos() * charWidth, y,
443 charWidth, charHeight);
447 && row_annotations[column].displayCharacter != null
448 && (row_annotations[column].displayCharacter.length() > 0))
451 if (centreColLabels || scaleColLabel)
453 fmWidth = fm.charsWidth(
454 row_annotations[column].displayCharacter
456 row_annotations[column].displayCharacter.length());
460 // justify the label and scale to fit in column
461 if (fmWidth > charWidth)
463 // scale only if the current font isn't already small enough
464 fmScaling = charWidth;
465 fmScaling /= fmWidth;
466 g.setFont(ofont.deriveFont(AffineTransform
467 .getScaleInstance(fmScaling, 1.0)));
468 // and update the label's width to reflect the scaling.
476 .charWidth(row_annotations[column].displayCharacter
479 charOffset = (int) ((charWidth - fmWidth) / 2f);
481 if (row_annotations[column].colour == null)
482 g.setColor(Color.black);
484 g.setColor(row_annotations[column].colour);
486 if (column == 0 || row.graph > 0)
488 g.drawString(row_annotations[column].displayCharacter,
489 (x * charWidth) + charOffset, y + iconOffset);
491 else if (row_annotations[column - 1] == null
493 || !row_annotations[column].displayCharacter
494 .equals(row_annotations[column - 1].displayCharacter) || (row_annotations[column].displayCharacter
495 .length() < 2 && row_annotations[column].secondaryStructure == ' ')))
497 g.drawString(row_annotations[column].displayCharacter
499 * charWidth + charOffset, y + iconOffset);
506 char ss = validRes ? row_annotations[column].secondaryStructure
511 // distinguish between forward/backward base-pairing
512 if (row_annotations[column].displayCharacter.indexOf(')') > -1)
521 if ((row_annotations[column].displayCharacter.indexOf(']') > -1))
530 // distinguish between forward/backward base-pairing
531 if (row_annotations[column].displayCharacter.indexOf('}') > -1)
540 // distinguish between forward/backward base-pairing
541 if (row_annotations[column].displayCharacter.indexOf('<') > -1)
550 // distinguish between forward/backward base-pairing
551 if (row_annotations[column].displayCharacter.indexOf('a') > -1)
561 // distinguish between forward/backward base-pairing
562 if (row_annotations[column].displayCharacter.indexOf('b') > -1)
571 // distinguish between forward/backward base-pairing
572 if (row_annotations[column].displayCharacter.indexOf('c') > -1)
580 // distinguish between forward/backward base-pairing
581 if (row_annotations[column].displayCharacter.indexOf('d') > -1)
589 // distinguish between forward/backward base-pairing
590 if (row_annotations[column].displayCharacter.indexOf('e') > -1)
598 // distinguish between forward/backward base-pairing
599 if (row_annotations[column].displayCharacter.indexOf('f') > -1)
607 // distinguish between forward/backward base-pairing
608 if (row_annotations[column].displayCharacter.indexOf('g') > -1)
616 // distinguish between forward/backward base-pairing
617 if (row_annotations[column].displayCharacter.indexOf('h') > -1)
625 // distinguish between forward/backward base-pairing
626 if (row_annotations[column].displayCharacter.indexOf('i') > -1)
634 // distinguish between forward/backward base-pairing
635 if (row_annotations[column].displayCharacter.indexOf('j') > -1)
643 // distinguish between forward/backward base-pairing
644 if (row_annotations[column].displayCharacter.indexOf('k') > -1)
652 // distinguish between forward/backward base-pairing
653 if (row_annotations[column].displayCharacter.indexOf('l') > -1)
661 // distinguish between forward/backward base-pairing
662 if (row_annotations[column].displayCharacter.indexOf('m') > -1)
670 // distinguish between forward/backward base-pairing
671 if (row_annotations[column].displayCharacter.indexOf('n') > -1)
679 // distinguish between forward/backward base-pairing
680 if (row_annotations[column].displayCharacter.indexOf('o') > -1)
688 // distinguish between forward/backward base-pairing
689 if (row_annotations[column].displayCharacter.indexOf('p') > -1)
697 // distinguish between forward/backward base-pairing
698 if (row_annotations[column].displayCharacter.indexOf('q') > -1)
706 // distinguish between forward/backward base-pairing
707 if (row_annotations[column].displayCharacter.indexOf('r') > -1)
715 // distinguish between forward/backward base-pairing
716 if (row_annotations[column].displayCharacter.indexOf('s') > -1)
724 // distinguish between forward/backward base-pairing
725 if (row_annotations[column].displayCharacter.indexOf('t') > -1)
733 // distinguish between forward/backward base-pairing
734 if (row_annotations[column].displayCharacter.indexOf('u') > -1)
742 // distinguish between forward/backward base-pairing
743 if (row_annotations[column].displayCharacter.indexOf('v') > -1)
751 // distinguish between forward/backward base-pairing
752 if (row_annotations[column].displayCharacter.indexOf('w') > -1)
760 // distinguish between forward/backward base-pairing
761 if (row_annotations[column].displayCharacter.indexOf('x') > -1)
769 // distinguish between forward/backward base-pairing
770 if (row_annotations[column].displayCharacter.indexOf('y') > -1)
778 // distinguish between forward/backward base-pairing
779 if (row_annotations[column].displayCharacter.indexOf('z') > -1)
785 if (!validRes || (ss != lastSS))
792 drawHelixAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
793 column, validRes, validEnd);
797 drawSheetAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
798 column, validRes, validEnd);
801 case '(': // Stem case for RNA secondary structure
802 case ')': // and opposite direction
803 drawStemAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
804 column, validRes, validEnd);
864 //System.out.println(lastSS);
865 Color nonCanColor= getNotCanonicalColor(lastSS);
866 drawNotCanonicalAnnot(g, nonCanColor, row_annotations, lastSSX, x, y, iconOffset, startRes,
867 column, validRes, validEnd);
870 g.setColor(Color.gray);
871 g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth)
887 lastSSX = (x * charWidth);
894 if (column >= row_annotations.length)
896 column = row_annotations.length - 1;
903 if ((row_annotations == null) || (row_annotations.length <= column)
904 || (row_annotations[column] == null))
920 drawHelixAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
921 column, validRes, validEnd);
925 drawSheetAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
926 column, validRes, validEnd);
929 case 'S': // Stem case for RNA secondary structure
930 drawStemAnnot(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
931 column, validRes, validEnd);
989 //System.out.println(lastSS);
990 Color nonCanColor = getNotCanonicalColor(lastSS);
991 drawNotCanonicalAnnot(g,nonCanColor, row_annotations, lastSSX, x, y, iconOffset, startRes,
992 column, validRes, validEnd);
995 drawGlyphLine(g, row_annotations, lastSSX, x, y, iconOffset, startRes,
996 column, validRes, validEnd);
1001 if (row.graph > 0 && row.graphHeight > 0)
1003 if (row.graph == AlignmentAnnotation.LINE_GRAPH)
1005 if (row.graphGroup > -1 && !graphGroupDrawn[row.graphGroup])
1007 float groupmax = -999999, groupmin = 9999999;
1008 for (int gg = 0; gg < aa.length; gg++)
1010 if (aa[gg].graphGroup != row.graphGroup)
1017 aa[gg].visible = false;
1020 if (aa[gg].graphMax > groupmax)
1022 groupmax = aa[gg].graphMax;
1024 if (aa[gg].graphMin < groupmin)
1026 groupmin = aa[gg].graphMin;
1030 for (int gg = 0; gg < aa.length; gg++)
1032 if (aa[gg].graphGroup == row.graphGroup)
1034 drawLineGraph(g, aa[gg], aa[gg].annotations, startRes, endRes, y, groupmin,
1035 groupmax, row.graphHeight);
1039 graphGroupDrawn[row.graphGroup] = true;
1043 drawLineGraph(g, row, row_annotations, startRes, endRes, y, row.graphMin,
1044 row.graphMax, row.graphHeight);
1047 else if (row.graph == AlignmentAnnotation.BAR_GRAPH)
1049 drawBarGraph(g, row, row_annotations, startRes, endRes, row.graphMin,
1054 if (row.graph > 0 && row.hasText)
1067 private final Color GLYPHLINE_COLOR = Color.gray;
1069 private final Color SHEET_COLOUR = Color.green;
1071 private final Color HELIX_COLOUR = Color.red;
1073 private final Color STEM_COLOUR = Color.blue;
1075 private Color sdNOTCANONICAL_COLOUR;
1077 public void drawGlyphLine(Graphics g, Annotation[] row,
1078 int lastSSX, int x, int y, int iconOffset, int startRes,
1079 int column, boolean validRes, boolean validEnd)
1081 g.setColor(GLYPHLINE_COLOR);
1082 g.fillRect(lastSSX, y + 6 + iconOffset, (x * charWidth) - lastSSX, 2);
1085 public void drawSheetAnnot(Graphics g, Annotation[] row,
1087 int lastSSX, int x, int y, int iconOffset, int startRes,
1088 int column, boolean validRes, boolean validEnd)
1090 g.setColor(SHEET_COLOUR);
1092 if (!validEnd || !validRes || row==null || row[column] == null
1093 || row[column].secondaryStructure != 'E')
1095 g.fillRect(lastSSX, y + 4 + iconOffset,
1096 (x * charWidth) - lastSSX - 4, 7);
1097 g.fillPolygon(new int[]
1098 { (x * charWidth) - 4, (x * charWidth) - 4, (x * charWidth) },
1100 { y + iconOffset, y + 14 + iconOffset, y + 7 + iconOffset },
1105 g.fillRect(lastSSX, y + 4 + iconOffset,
1106 (x + 1) * charWidth - lastSSX, 7);
1111 public void drawHelixAnnot(Graphics g, Annotation[] row,
1112 int lastSSX, int x, int y, int iconOffset, int startRes,
1113 int column, boolean validRes, boolean validEnd)
1115 g.setColor(HELIX_COLOUR);
1117 int sCol = (lastSSX / charWidth) + startRes;
1119 int x2 = (x * charWidth);
1123 int ofs = charWidth / 2;
1124 // Off by 1 offset when drawing rects and ovals
1125 // to offscreen image on the MAC
1126 g.fillRoundRect(lastSSX, y + 4 + iconOffset, x2 - x1, 8, 8, 8);
1127 if (sCol == 0 || row[sCol - 1] == null
1128 || row[sCol - 1].secondaryStructure != 'H')
1133 // g.setColor(Color.orange);
1134 g.fillRoundRect(lastSSX, y + 4 + iconOffset, x2 - x1 - ofs + 1, 8,
1137 if (!validRes || row[column] == null
1138 || row[column].secondaryStructure != 'H')
1144 // g.setColor(Color.magenta);
1145 g.fillRoundRect(lastSSX + ofs, y + 4 + iconOffset, x2 - x1 - ofs
1153 if (sCol == 0 || row[sCol - 1] == null
1154 || row[sCol - 1].secondaryStructure != 'H')
1156 g.fillArc(lastSSX, y + 4 + iconOffset, charWidth, 8, 90, 180);
1157 x1 += charWidth / 2;
1160 if (!validRes || row[column] == null
1161 || row[column].secondaryStructure != 'H')
1163 g.fillArc((x * charWidth) - charWidth, y + 4 + iconOffset, charWidth,
1165 x2 -= charWidth / 2;
1168 g.fillRect(x1, y + 4 + iconOffset, x2 - x1, 8);
1171 public void drawLineGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
1172 int eRes, int y, float min, float max, int graphHeight)
1174 if (sRes > aa_annotations.length)
1181 // Adjustment for fastpaint to left
1187 eRes = Math.min(eRes, aa_annotations.length);
1195 float range = max - min;
1200 y2 = y - (int) ((0 - min / range) * graphHeight);
1203 g.setColor(Color.gray);
1204 g.drawLine(x - charWidth, y2, (eRes - sRes + 1) * charWidth, y2);
1206 eRes = Math.min(eRes, aa_annotations.length);
1209 int aaMax = aa_annotations.length - 1;
1211 while (x < eRes - sRes)
1214 if (hasHiddenColumns)
1216 column = columnSelection.adjustForHiddenColumns(column);
1224 if (aa_annotations[column] == null
1225 || aa_annotations[column - 1] == null)
1231 if (aa_annotations[column].colour == null)
1232 g.setColor(Color.black);
1234 g.setColor(aa_annotations[column].colour);
1237 - (int) (((aa_annotations[column - 1].value - min) / range) * graphHeight);
1239 - (int) (((aa_annotations[column].value - min) / range) * graphHeight);
1241 g.drawLine(x * charWidth - charWidth / 2, y1, x * charWidth
1242 + charWidth / 2, y2);
1246 if (_aa.threshold != null)
1248 g.setColor(_aa.threshold.colour);
1249 Graphics2D g2 = (Graphics2D) g;
1250 g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
1251 BasicStroke.JOIN_ROUND, 3f, new float[]
1254 y2 = (int) (y - ((_aa.threshold.value - min) / range) * graphHeight);
1255 g.drawLine(0, y2, (eRes - sRes) * charWidth, y2);
1256 g2.setStroke(new BasicStroke());
1260 public void drawBarGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int sRes,
1261 int eRes, float min, float max, int y)
1263 if (sRes > aa_annotations.length)
1267 Font ofont = g.getFont();
1268 eRes = Math.min(eRes, aa_annotations.length);
1270 int x = 0, y1 = y, y2 = y;
1272 float range = max - min;
1276 y2 = y - (int) ((0 - min / (range)) * _aa.graphHeight);
1279 g.setColor(Color.gray);
1281 g.drawLine(x, y2, (eRes - sRes) * charWidth, y2);
1284 int aaMax = aa_annotations.length - 1;
1285 boolean renderHistogram = true, renderProfile = true, normaliseProfile = false;
1286 // if (aa.autoCalculated && aa.label.startsWith("Consensus"))
1288 // TODO: generalise this to have render styles for consensus/profile data
1289 if (_aa.groupRef != null)
1291 renderHistogram = _aa.groupRef.isShowConsensusHistogram();
1292 renderProfile = _aa.groupRef.isShowSequenceLogo();
1293 normaliseProfile = _aa.groupRef.isNormaliseSequenceLogo();
1297 renderHistogram = av_renderHistogram;
1298 renderProfile = av_renderProfile;
1299 normaliseProfile = av_normaliseProfile;
1302 while (x < eRes - sRes)
1305 if (hasHiddenColumns)
1307 column = columnSelection.adjustForHiddenColumns(column);
1315 if (aa_annotations[column] == null)
1320 if (aa_annotations[column].colour == null)
1321 g.setColor(Color.black);
1323 g.setColor(aa_annotations[column].colour);
1326 - (int) (((aa_annotations[column].value - min) / (range)) * _aa.graphHeight);
1328 if (renderHistogram)
1332 g.fillRect(x * charWidth, y2, charWidth, y1 - y2);
1336 g.fillRect(x * charWidth, y1, charWidth, y2 - y1);
1339 // draw profile if available
1343 int profl[] = getProfileFor(_aa, column);
1344 // just try to draw the logo if profl is not null
1345 if (profl != null && profl[1] != 0)
1347 float ht = normaliseProfile ? y - _aa.graphHeight : y1;
1348 double htn = normaliseProfile ? _aa.graphHeight : (y2 - y1);// aa.graphHeight;
1355 * profl.length == 74 indicates that the profile of a secondary
1356 * structure conservation row was accesed. Therefore dc gets length 2,
1357 * to have space for a basepair instead of just a single nucleotide
1359 if (profl.length == 74)
1367 LineMetrics lm = g.getFontMetrics(ofont).getLineMetrics("Q", g);
1368 double scale = 1f / (normaliseProfile ? profl[1] : 100f);
1369 float ofontHeight = 1f / lm.getAscent();// magnify to fill box
1371 for (int c = 2; c < profl[0];)
1373 dc[0] = (char) profl[c++];
1375 if (_aa.label.startsWith("StrucConsensus"))
1377 dc[1] = (char) profl[c++];
1381 wdth /= fm.charsWidth(dc, 0, dc.length);
1385 scl = htn * scale * profl[c++];
1386 lm = ofont.getLineMetrics(dc, 0, 1, g.getFontMetrics()
1387 .getFontRenderContext());
1388 g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(
1389 wdth, scl / lm.getAscent())));
1390 lm = g.getFontMetrics().getLineMetrics(dc, 0, 1, g);
1392 // Debug - render boxes around characters
1393 // g.setColor(Color.red);
1394 // g.drawRect(x*av.charWidth, (int)ht, av.charWidth,
1396 // g.setColor(profcolour.findColour(dc[0]).darker());
1397 g.setColor(profcolour.findColour(dc[0], column,null));
1399 hght = (ht + (scl - lm.getDescent() - lm.getBaselineOffsets()[lm
1400 .getBaselineIndex()]));
1402 g.drawChars(dc, 0, dc.length, x * charWidth, (int) hght);
1410 if (_aa.threshold != null)
1412 g.setColor(_aa.threshold.colour);
1413 Graphics2D g2 = (Graphics2D) g;
1414 g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE,
1415 BasicStroke.JOIN_ROUND, 3f, new float[]
1418 y2 = (int) (y - ((_aa.threshold.value - min) / range) * _aa.graphHeight);
1419 g.drawLine(0, y2, (eRes - sRes) * charWidth, y2);
1420 g2.setStroke(new BasicStroke());
1424 // used by overview window
1425 public void drawGraph(Graphics g, AlignmentAnnotation _aa, Annotation[] aa_annotations, int width,
1426 int y, int sRes, int eRes)
1428 eRes = Math.min(eRes, aa_annotations.length);
1429 g.setColor(Color.white);
1430 g.fillRect(0, 0, width, y);
1431 g.setColor(new Color(0, 0, 180));
1435 for (int j = sRes; j < eRes; j++)
1437 if (aa_annotations[j] != null)
1439 if (aa_annotations[j].colour == null)
1440 g.setColor(Color.black);
1442 g.setColor(aa_annotations[j].colour);
1444 height = (int) ((aa_annotations[j].value / _aa.graphMax) * y);
1450 g.fillRect(x, y - height, charWidth, height);
1457 Color getNotCanonicalColor(char lastss)
1471 return Color.magenta;
1475 return Color.orange;
1487 return Color.yellow;
1495 return Color.darkGray;
1503 return Color.lightGray;
1515 return Color.magenta;
1519 return Color.orange;
1527 return Color.yellow;
1547 return Color.magenta;
1551 return Color.darkGray;
1555 return Color.yellow;
1563 return Color.orange;
1567 return Color.magenta;
1578 System.out.println("This is not a interaction");