normalised logo rendering (JAL-958)
authorjprocter <jprocter@compbio.dundee.ac.uk>
Tue, 11 Oct 2011 16:03:15 +0000 (17:03 +0100)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Tue, 11 Oct 2011 16:03:15 +0000 (17:03 +0100)
FEATURETODO [new file with mode: 0644]
src/jalview/analysis/AAFrequency.java
src/jalview/analysis/StructureFrequency.java
src/jalview/bin/Cache.java
src/jalview/datamodel/SequenceGroup.java
src/jalview/gui/AlignFrame.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AlignmentPanel.java
src/jalview/gui/AnnotationLabels.java
src/jalview/gui/AnnotationPanel.java
src/jalview/jbgui/GAlignFrame.java

diff --git a/FEATURETODO b/FEATURETODO
new file mode 100644 (file)
index 0000000..5a5c5c1
--- /dev/null
@@ -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
+
index b63e600..d56fb01 100755 (executable)
@@ -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;
index c15dba4..aa1e277 100644 (file)
@@ -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]++];
       }
     }
 
index 63a3412..5dbf5bc 100755 (executable)
@@ -124,6 +124,8 @@ import org.biojava.dasobert.dasregistry.Das1Source;
  * histogram.</li>
  * <li>SHOW_CONSENSUS_LOGO (false) Show consensus annotation row's sequence
  * logo.</li>
+ * <li>NORMALISE_CONSENSUS_LOGO (false) Show consensus annotation row's sequence
+ * logo normalised to row height rather than histogram height.</li>
  * <li>FOLLOW_SELECTIONS (true) Controls whether a new alignment view should
  * respond to selections made in other alignments containing the same sequences.
  * </li>
index 3d848a2..6bee416 100755 (executable)
@@ -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;
+  }
 }
index 9b91255..94a7848 100755 (executable)
@@ -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());
index f5bc6e4..5ac946a 100644 (file)
@@ -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;
+  }
 }
index f7c465c..2b4c0db 100644 (file)
@@ -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)
         {
index 19e6f67..7967ae6 100755 (executable)
@@ -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);
index a88aa4a..a611bd0 100755 (executable)
@@ -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();
             }
           }
index 4a7c3f0..439a67d 100755 (executable)
@@ -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