From bbfdb203ce3a889600caa52478478b75ab03809f Mon Sep 17 00:00:00 2001 From: jprocter Date: Tue, 11 Oct 2011 17:03:15 +0100 Subject: [PATCH] normalised logo rendering (JAL-958) --- FEATURETODO | 8 +++++ src/jalview/analysis/AAFrequency.java | 6 ++-- src/jalview/analysis/StructureFrequency.java | 8 +++-- src/jalview/bin/Cache.java | 2 ++ src/jalview/datamodel/SequenceGroup.java | 18 +++++++++++ src/jalview/gui/AlignFrame.java | 8 ++++- src/jalview/gui/AlignViewport.java | 17 +++++++++- src/jalview/gui/AlignmentPanel.java | 2 ++ src/jalview/gui/AnnotationLabels.java | 44 +++++++++++++++++++++++++ src/jalview/gui/AnnotationPanel.java | 45 +++++++++++++++----------- src/jalview/jbgui/GAlignFrame.java | 19 +++++++++++ 11 files changed, 151 insertions(+), 26 deletions(-) create mode 100644 FEATURETODO diff --git a/FEATURETODO b/FEATURETODO new file mode 100644 index 0000000..5a5c5c1 --- /dev/null +++ b/FEATURETODO @@ -0,0 +1,8 @@ +Normalised logo feature todo + +* transfer and update calcs in applet +* add flags for normalised logo display to AnnotationFile and Jalview Project +* add parameter for applet +* add preference for application +* consider rationalising flag model for N types of consensus/logo calculation methods + diff --git a/src/jalview/analysis/AAFrequency.java b/src/jalview/analysis/AAFrequency.java index b63e600..d56fb01 100755 --- a/src/jalview/analysis/AAFrequency.java +++ b/src/jalview/analysis/AAFrequency.java @@ -321,14 +321,16 @@ public class AAFrequency } ; jalview.util.QuickSort.sort(vl, ca); - rtnval[0] = 1; + rtnval[0] = 2; + rtnval[1]=0; for (int c = ca.length - 1; profile[0][((char[]) ca[c])[0]] > 0; c--) { if (((char[]) ca[c])[0] != '-') { rtnval[rtnval[0]++] = ((char[]) ca[c])[0]; - rtnval[rtnval[0]++] = (int) (((float) profile[0][((char[]) ca[c])[0]]) * 100f / (float) profile[1][ignoreGapsInConsensusCalculation ? 1 + rtnval[rtnval[0]] = (int) (((float) profile[0][((char[]) ca[c])[0]]) * 100f / (float) profile[1][ignoreGapsInConsensusCalculation ? 1 : 0]); + rtnval[1]+=rtnval[rtnval[0]++]; } } return rtnval; diff --git a/src/jalview/analysis/StructureFrequency.java b/src/jalview/analysis/StructureFrequency.java index c15dba4..aa1e277 100644 --- a/src/jalview/analysis/StructureFrequency.java +++ b/src/jalview/analysis/StructureFrequency.java @@ -406,7 +406,7 @@ public class StructureFrequency public static int[] extractProfile(Hashtable hconsensus, boolean ignoreGapsInConsensusCalculation) { - int[] rtnval = new int[51]; // 2*(5*5)+1 + int[] rtnval = new int[52]; // 2*(5*5)+2 int[][] profile = (int[][]) hconsensus.get(StructureFrequency.PROFILE); int[][] pairs = (int[][]) hconsensus .get(StructureFrequency.PAIRPROFILE); @@ -430,15 +430,17 @@ public class StructureFrequency } jalview.util.QuickSort.sort(vl, ca); - rtnval[0] = 1; + rtnval[0] = 2; + rtnval[1] = 0; for (int c = 624; c > 0; c--) { if (vl[c] > 0) { rtnval[rtnval[0]++] = ((int[]) ca[c])[0]; rtnval[rtnval[0]++] = ((int[]) ca[c])[1]; - rtnval[rtnval[0]++] = (int) ((float) vl[c] * 100f / (float) profile[1][ignoreGapsInConsensusCalculation ? 1 + rtnval[rtnval[0]] = (int) ((float) vl[c] * 100f / (float) profile[1][ignoreGapsInConsensusCalculation ? 1 : 0]); + rtnval[1]+=rtnval[rtnval[0]++]; } } diff --git a/src/jalview/bin/Cache.java b/src/jalview/bin/Cache.java index 63a3412..5dbf5bc 100755 --- a/src/jalview/bin/Cache.java +++ b/src/jalview/bin/Cache.java @@ -124,6 +124,8 @@ import org.biojava.dasobert.dasregistry.Das1Source; * histogram. *
  • SHOW_CONSENSUS_LOGO (false) Show consensus annotation row's sequence * logo.
  • + *
  • NORMALISE_CONSENSUS_LOGO (false) Show consensus annotation row's sequence + * logo normalised to row height rather than histogram height.
  • *
  • FOLLOW_SELECTIONS (true) Controls whether a new alignment view should * respond to selections made in other alignments containing the same sequences. *
  • diff --git a/src/jalview/datamodel/SequenceGroup.java b/src/jalview/datamodel/SequenceGroup.java index 3d848a2..6bee416 100755 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@ -91,6 +91,11 @@ public class SequenceGroup * consensus calculation property */ private boolean showSequenceLogo = false; + /** + * flag indicating if logo should be rendered normalised + */ + private boolean normaliseSequenceLogo; + /** * @return the includeAllConsSymbols @@ -1167,4 +1172,17 @@ public class SequenceGroup { return showConsensusHistogram; } + + /** + * set flag indicating if logo should be normalised when rendered + * @param norm + */ + public void setNormaliseSequenceLogo(boolean norm) + { + normaliseSequenceLogo=norm; + } + public boolean isNormaliseSequenceLogo() + { + return normaliseSequenceLogo; + } } diff --git a/src/jalview/gui/AlignFrame.java b/src/jalview/gui/AlignFrame.java index 9b91255..94a7848 100755 --- a/src/jalview/gui/AlignFrame.java +++ b/src/jalview/gui/AlignFrame.java @@ -711,6 +711,8 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, showGroupConservation.setSelected(av.showGroupConservation); showConsensusHistogram.setSelected(av.showConsensusHistogram); showSequenceLogo.setSelected(av.showSequenceLogo); + normaliseSequenceLogo.setSelected(av.normaliseSequenceLogo); + setColourSelected(ColourSchemeProperty.getColourName(av .getGlobalColourScheme())); @@ -5041,7 +5043,11 @@ public class AlignFrame extends GAlignFrame implements DropTargetListener, viewport.setShowSequenceLogo(showSequenceLogo.getState()); alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState()); } - + protected void normaliseSequenceLogo_actionPerformed(ActionEvent e) + { + viewport.setNormaliseSequenceLogo(normaliseSequenceLogo.getState()); + alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState()); + } protected void applyAutoAnnotationSettings_actionPerformed(ActionEvent e) { alignPanel.updateAnnotation(applyAutoAnnotationSettings.getState()); diff --git a/src/jalview/gui/AlignViewport.java b/src/jalview/gui/AlignViewport.java index f5bc6e4..5ac946a 100644 --- a/src/jalview/gui/AlignViewport.java +++ b/src/jalview/gui/AlignViewport.java @@ -404,6 +404,7 @@ public class AlignViewport implements SelectionSource, VamsasSource showConsensusHistogram = Cache.getDefault("SHOW_CONSENSUS_HISTOGRAM", true); showSequenceLogo = Cache.getDefault("SHOW_CONSENSUS_LOGO", false); + normaliseSequenceLogo = Cache.getDefault("NORMALISE_CONSENSUS_LOGO", false); showGroupConsensus = Cache.getDefault("SHOW_GROUP_CONSENSUS", false); // TODO: add menu option action that nulls or creates consensus object // depending on if the user wants to see the annotation or not in a @@ -2302,7 +2303,10 @@ public class AlignViewport implements SelectionSource, VamsasSource * should consensus profile be rendered by default */ public boolean showSequenceLogo = false; - + /** + * should consensus profile be rendered normalised to row height + */ + public boolean normaliseSequenceLogo = false; /** * should consensus histograms be rendered by default */ @@ -2466,4 +2470,15 @@ public class AlignViewport implements SelectionSource, VamsasSource } return seqvectors.toArray(new SequenceI[seqvectors.size()][]); } + + + public boolean isNormaliseSequenceLogo() + { + return normaliseSequenceLogo; + } + + public void setNormaliseSequenceLogo(boolean state) + { + normaliseSequenceLogo = state; + } } diff --git a/src/jalview/gui/AlignmentPanel.java b/src/jalview/gui/AlignmentPanel.java index f7c465c..2b4c0db 100644 --- a/src/jalview/gui/AlignmentPanel.java +++ b/src/jalview/gui/AlignmentPanel.java @@ -1357,6 +1357,7 @@ public class AlignmentPanel extends GAlignmentPanel implements boolean cons = av.isShowGroupConsensus(); boolean showprf = av.isShowSequenceLogo(); boolean showConsHist = av.isShowConsensusHistogram(); + boolean normLogo = av.isNormaliseSequenceLogo(); boolean sortg = true; @@ -1392,6 +1393,7 @@ public class AlignmentPanel extends GAlignmentPanel implements // set defaults for this group's conservation/consensus sg.setshowSequenceLogo(showprf); sg.setShowConsensusHistogram(showConsHist); + sg.setNormaliseSequenceLogo(normLogo); } if (conv) { diff --git a/src/jalview/gui/AnnotationLabels.java b/src/jalview/gui/AnnotationLabels.java index 19e6f67..7967ae6 100755 --- a/src/jalview/gui/AnnotationLabels.java +++ b/src/jalview/gui/AnnotationLabels.java @@ -630,6 +630,28 @@ public class AnnotationLabels extends JPanel implements MouseListener, } }); pop.add(cprofl); + final JCheckBoxMenuItem cproflnorm = new JCheckBoxMenuItem( + "Normalise Group Logo", + aa[selectedRow].groupRef.isNormaliseSequenceLogo()); + cproflnorm.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + + // TODO: pass on reference + // to ap + // so the + // view + // can be + // updated. + aaa.groupRef.setNormaliseSequenceLogo(cproflnorm.getState()); + // automatically enable logo display if we're clicked + aaa.groupRef.setshowSequenceLogo(true); + ap.repaint(); + // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); + } + }); + pop.add(cproflnorm); } else { @@ -646,6 +668,7 @@ public class AnnotationLabels extends JPanel implements MouseListener, // can be // updated. av.setShowConsensusHistogram(chist.getState()); + ap.alignFrame.setMenusForViewport(); ap.repaint(); // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); } @@ -664,11 +687,32 @@ public class AnnotationLabels extends JPanel implements MouseListener, // can be // updated. av.setShowSequenceLogo(cprof.getState()); + ap.alignFrame.setMenusForViewport(); ap.repaint(); // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); } }); pop.add(cprof); + final JCheckBoxMenuItem cprofnorm = new JCheckBoxMenuItem( + "Normalise Logo", av.isNormaliseSequenceLogo()); + cprofnorm.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) + { + // TODO: pass on reference + // to ap + // so the + // view + // can be + // updated. + av.setShowSequenceLogo(true); + av.setNormaliseSequenceLogo(cprofnorm.getState()); + ap.alignFrame.setMenusForViewport(); + ap.repaint(); + // ap.annotationPanel.paint(ap.annotationPanel.getGraphics()); + } + }); + pop.add(cprofnorm); } final JMenuItem consclipbrd = new JMenuItem(COPYCONS_SEQ); consclipbrd.addActionListener(this); diff --git a/src/jalview/gui/AnnotationPanel.java b/src/jalview/gui/AnnotationPanel.java index a88aa4a..a611bd0 100755 --- a/src/jalview/gui/AnnotationPanel.java +++ b/src/jalview/gui/AnnotationPanel.java @@ -1496,19 +1496,21 @@ public class AnnotationPanel extends JPanel implements MouseListener, int column; int aaMax = aa.annotations.length - 1; - boolean renderHistogram = true, renderProfile = true; - if (aa.autoCalculated && aa.label.startsWith("Consensus")) + boolean renderHistogram = true, renderProfile = true, normaliseProfile=false; +// if (aa.autoCalculated && aa.label.startsWith("Consensus")) { // TODO: generalise this to have render styles for consensus/profile data if (aa.groupRef != null) { renderHistogram = aa.groupRef.isShowConsensusHistogram(); renderProfile = aa.groupRef.isShowSequenceLogo(); + normaliseProfile= aa.groupRef.isNormaliseSequenceLogo(); } else { renderHistogram = av.isShowConsensusHistogram(); renderProfile = av.isShowSequenceLogo(); + normaliseProfile= av.isNormaliseSequenceLogo(); } } while (x < eRes - sRes) @@ -1557,18 +1559,19 @@ public class AnnotationPanel extends JPanel implements MouseListener, if (profl != null) { - int ht = y1, htn = y2 - y1;// aa.graphHeight; + float ht = normaliseProfile ? y-aa.graphHeight : y1; + double htn = normaliseProfile ? aa.graphHeight : (y2 - y1);// aa.graphHeight; float wdth; double ht2 = 0; char[] dc; /** - * profl.length == 51 indicates that the profile of a secondary + * profl.length == 52 indicates that the profile of a secondary * structure conservation row was accesed. * Therefore dc gets length 2, to have space for a basepair instead of * just a single nucleotide */ - if (profl.length == 51) + if (profl.length == 52) { dc = new char[2]; } @@ -1576,9 +1579,11 @@ public class AnnotationPanel extends JPanel implements MouseListener, { dc = new char[1]; } - - LineMetrics lm; - for (int c = 1; profl != null && c < profl[0];) + LineMetrics lm=g.getFontMetrics(ofont).getLineMetrics("Q", g); + double scale = 1f/(normaliseProfile ? profl[1] : 100f); + float ofontHeight = 1f/lm.getAscent();// magnify to fill box + double scl=0.0; + for (int c = 2; profl != null && c < profl[0];) { dc[0] = (char) profl[c++]; @@ -1589,34 +1594,36 @@ public class AnnotationPanel extends JPanel implements MouseListener, wdth = av.charWidth; wdth /= (float) fm.charsWidth(dc, 0, dc.length); - - if (c > 2) - { - ht += (int) ht2; - } + + ht += scl; { // if (aa.annotations[column].value==0) { // g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance(wdth, // (ht2=(aa.graphHeight*0.1/av.charHeight))))); // ht = y2-(int)ht2; // } else { + scl=((double)htn)*scale* ((double) profl[c++]); + lm = ofont.getLineMetrics(dc, 0, 1, g.getFontMetrics().getFontRenderContext()); g.setFont(ofont.deriveFont(AffineTransform.getScaleInstance( - wdth, (ht2 = (htn * ((double) profl[c++]) / 100.0)) - / av.charHeight))); + wdth, scl/lm.getAscent()))); lm = g.getFontMetrics().getLineMetrics(dc, 0, 1, g); + // htn -=ht2; // } - g.setColor(profcolour.findColour(dc[0])); // (av.globalColourScheme!=null) // ? );// try to get a // colourscheme for the // group(aa.groupRef.cs==null) // ? av.textColour2 : // cs.findColour(dc)); // System.out.println(dc[0]); - + // Debug - render boxes around characters + // g.setColor(Color.red); + // g.drawRect(x*av.charWidth, (int)ht, av.charWidth, (int)(scl)); + // g.setColor(profcolour.findColour(dc[0]).darker()); + g.setColor(profcolour.findColour(dc[0])); + // (av.globalColourScheme!=null) g.drawChars(dc, 0, dc.length, x * av.charWidth, - (int) (ht + lm.getHeight())); - + (int) (ht + (scl-lm.getDescent()-lm.getBaselineOffsets()[lm.getBaselineIndex()]))); // ht+=g.getFontMetrics().getAscent()-g.getFontMetrics().getDescent(); } } diff --git a/src/jalview/jbgui/GAlignFrame.java b/src/jalview/jbgui/GAlignFrame.java index 4a7c3f0..439a67d 100755 --- a/src/jalview/jbgui/GAlignFrame.java +++ b/src/jalview/jbgui/GAlignFrame.java @@ -314,6 +314,8 @@ public class GAlignFrame extends JInternalFrame protected JCheckBoxMenuItem showSequenceLogo = new JCheckBoxMenuItem(); + protected JCheckBoxMenuItem normaliseSequenceLogo = new JCheckBoxMenuItem(); + protected JCheckBoxMenuItem applyAutoAnnotationSettings = new JCheckBoxMenuItem(); private JMenuItem grpsFromSelection = new JMenuItem(); @@ -1113,6 +1115,16 @@ public class GAlignFrame extends JInternalFrame } }); + normaliseSequenceLogo.setText("Normalise Consensus Logo"); + normaliseSequenceLogo.addActionListener(new ActionListener() + { + + public void actionPerformed(ActionEvent e) + { + normaliseSequenceLogo_actionPerformed(e); + } + + }); applyAutoAnnotationSettings.setText("Apply to all groups"); applyAutoAnnotationSettings.setState(false); applyAutoAnnotationSettings.setVisible(true); @@ -1783,6 +1795,7 @@ public class GAlignFrame extends JInternalFrame autoAnnMenu.add(applyAutoAnnotationSettings); autoAnnMenu.add(showConsensusHistogram); autoAnnMenu.add(showSequenceLogo); + autoAnnMenu.add(normaliseSequenceLogo); autoAnnMenu.addSeparator(); autoAnnMenu.add(showGroupConservation); autoAnnMenu.add(showGroupConsensus); @@ -1894,6 +1907,12 @@ public class GAlignFrame extends JInternalFrame //selectMenu.add(listenToViewSelections); } + protected void normaliseSequenceLogo_actionPerformed(ActionEvent e) + { + // TODO Auto-generated method stub + + } + protected void listenToViewSelections_actionPerformed(ActionEvent e) { // TODO Auto-generated method stub -- 1.7.10.2