Must repaint whole alignPanel
[jalview.git] / src / jalview / gui / AlignViewport.java
index 05a52dd..743c8dd 100755 (executable)
@@ -84,7 +84,7 @@ public class AlignViewport
 
 
     /** DOCUMENT ME!! */
-    public Vector vconsensus;
+    public Hashtable [] hconsensus;
     AlignmentAnnotation consensus;
     AlignmentAnnotation conservation;
     AlignmentAnnotation quality;
@@ -104,6 +104,14 @@ public class AlignViewport
 
     boolean padGaps = false;
 
+    Rectangle explodedPosition;
+
+    String viewName;
+
+    String sequenceSetID;
+
+    boolean gatherViewsHere = false;
+
 
     public AlignViewport(AlignmentI al, boolean dataset)
     {
@@ -179,10 +187,46 @@ public class AlignViewport
 
         // We must set conservation and consensus before setting colour,
         // as Blosum and Clustal require this to be done
-        if(vconsensus==null && !isDataset)
+        if(hconsensus==null && !isDataset)
         {
-          updateConservation();
-          updateConsensus();
+          if(!alignment.isNucleotide())
+          {
+            conservation = new AlignmentAnnotation("Conservation",
+                "Conservation of total alignment less than " +
+                ConsPercGaps + "% gaps",
+                new Annotation[1], 0f,
+                11f,
+                AlignmentAnnotation.BAR_GRAPH);
+            conservation.hasText = true;
+
+            if (showConservation)
+            {
+              alignment.addAnnotation(conservation);
+            }
+
+            if (showQuality)
+            {
+              quality = new AlignmentAnnotation("Quality",
+                                                "Alignment Quality based on Blosum62 scores",
+                                                new Annotation[1],
+                                                0f,
+                                                11f,
+                                                AlignmentAnnotation.BAR_GRAPH);
+
+              alignment.addAnnotation(quality);
+            }
+          }
+
+          consensus = new AlignmentAnnotation("Consensus", "PID",
+                                               new Annotation[1], 0f, 100f,
+                                               AlignmentAnnotation.BAR_GRAPH);
+          consensus.hasText = true;
+
+           if (showIdentity)
+           {
+             alignment.addAnnotation(consensus);
+           }
+
         }
 
         if (jalview.bin.Cache.getProperty("DEFAULT_COLOUR") != null)
@@ -198,7 +242,7 @@ public class AlignViewport
 
             if (globalColourScheme != null)
             {
-                globalColourScheme.setConsensus(vconsensus);
+                globalColourScheme.setConsensus(hconsensus);
             }
         }
     }
@@ -220,229 +264,271 @@ public class AlignViewport
       return showSequenceFeatures;
     }
 
-    /**
-     * DOCUMENT ME!
-     */
-    public void updateConservation()
-    {
-      if(alignment.isNucleotide())
-          return;
-
-      try{
-        Conservation cons = new jalview.analysis.Conservation("All",
-            jalview.schemes.ResidueProperties.propHash, 3,
-            alignment.getSequences(), 0, alignment.getWidth() - 1);
-        cons.calculate();
-        cons.verdict(false, ConsPercGaps);
-        cons.findQuality();
-
-        int alWidth = alignment.getWidth();
-        Annotation[] annotations = new Annotation[alWidth];
-        Annotation[] qannotations = new Annotation[alWidth];
-        String sequence = cons.getConsSequence().getSequence();
-        float minR;
-        float minG;
-        float minB;
-        float maxR;
-        float maxG;
-        float maxB;
-        minR = 0.3f;
-        minG = 0.0f;
-        minB = 0f;
-        maxR = 1.0f - minR;
-        maxG = 0.9f - minG;
-        maxB = 0f - minB; // scalable range for colouring both Conservation and Quality
-
-        float min = 0f;
-        float max = 11f;
-        float qmin = cons.qualityRange[0].floatValue();
-        float qmax = cons.qualityRange[1].floatValue();
-
-        for (int i = 0; i < alWidth; i++)
+
+
+    class ConservationThread extends Thread
+    {
+      AlignmentPanel ap;
+      public ConservationThread(AlignmentPanel ap)
+      {
+        this.ap = ap;
+      }
+
+      public void run()
+      {
+        try
         {
-          float value = 0;
+          long t = System.currentTimeMillis();
+
+          Conservation cons = new jalview.analysis.Conservation("All",
+              jalview.schemes.ResidueProperties.propHash, 3,
+              alignment.getSequences(), 0, alignment.getWidth() - 1);
+
+          cons.calculate();
+          cons.verdict(false, ConsPercGaps);
 
-          try
+          if (showQuality)
           {
-            value = Integer.parseInt(sequence.charAt(i) + "");
+            cons.findQuality();
           }
-          catch (Exception ex)
+
+          System.out.println("Conservation took " + (System.currentTimeMillis() - t) +
+                             "ms");
+
+          int alWidth = alignment.getWidth();
+          String sequence = cons.getConsSequence().getSequence();
+          float minR;
+          float minG;
+          float minB;
+          float maxR;
+          float maxG;
+          float maxB;
+          minR = 0.3f;
+          minG = 0.0f;
+          minB = 0f;
+          maxR = 1.0f - minR;
+          maxG = 0.9f - minG;
+          maxB = 0f - minB; // scalable range for colouring both Conservation and Quality
+
+          float min = 0f;
+          float max = 11f;
+          float qmin = 0f;
+          float qmax = 0f;
+
+          char c;
+
+          conservation.annotations = new Annotation[alWidth];
+
+          if (showQuality)
           {
-            if (sequence.charAt(i) == '*')
-            {
+            quality.annotations = new Annotation[alWidth];
+            qmin = cons.qualityRange[0].floatValue();
+            qmax = cons.qualityRange[1].floatValue();
+          }
+
+          for (int i = 0; i < alWidth; i++)
+          {
+            float value = 0;
+
+            c = sequence.charAt(i);
+
+            if (Character.isDigit(c))
+              value = (int) (c - '0');
+            else if (c == '*')
               value = 11;
-            }
+            else if (c == '+')
+              value = 10;
 
-            if (sequence.charAt(i) == '+')
+            float vprop = value - min;
+            vprop /= max;
+            conservation.annotations[i] =
+                new Annotation(String.valueOf(c),
+                               String.valueOf(value), ' ', value,
+                               new Color(minR + (maxR * vprop),
+                                         minG + (maxG * vprop),
+                                         minB + (maxB * vprop)));
+
+            // Quality calc
+            if (showQuality)
             {
-              value = 10;
+              value = ( (Double) cons.quality.get(i)).floatValue();
+              vprop = value - qmin;
+              vprop /= qmax;
+              quality.annotations[i] = new Annotation(" ", String.valueOf(value), ' ',
+                                               value,
+                                               new Color(minR + (maxR * vprop),
+                  minG + (maxG * vprop),
+                  minB + (maxB * vprop)));
             }
           }
 
-          float vprop = value - min;
-          vprop /= max;
-          annotations[i] = new Annotation(sequence.charAt(i) + "",
-                                          String.valueOf(value), ' ', value,
-                                          new Color(minR + (maxR * vprop),
-              minG + (maxG * vprop),
-              minB + (maxB * vprop)));
-
-          // Quality calc
-          value = ( (Double) cons.quality.get(i)).floatValue();
-          vprop = value - qmin;
-          vprop /= qmax;
-          qannotations[i] = new Annotation(" ", String.valueOf(value), ' ',
-                                           value,
-                                           new Color(minR + (maxR * vprop),
-              minG + (maxG * vprop),
-              minB + (maxB * vprop)));
+          if (quality != null)
+          {
+            quality.graphMax = cons.qualityRange[1].floatValue();
+          }
         }
-
-        if (conservation == null)
+        catch (OutOfMemoryError error)
         {
-          conservation = new AlignmentAnnotation("Conservation",
-                                                 "Conservation of total alignment less than " +
-                                                 ConsPercGaps + "% gaps",
-                                                 annotations, 0f, // cons.qualityRange[0].floatValue(),
-                                                 11f, // cons.qualityRange[1].floatValue()
-                                                 AlignmentAnnotation.BAR_GRAPH);
-
-          if (showConservation)
+          javax.swing.SwingUtilities.invokeLater(new Runnable()
           {
-            alignment.addAnnotation(conservation);
-          }
+            public void run()
+            {
+              javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
+                  "Out of memory calculating conservation!!"
+                  +
+                  "\nSee help files for increasing Java Virtual Machine memory."
+                  , "Out of memory",
+                  javax.swing.JOptionPane.WARNING_MESSAGE);
+            }
+          });
 
-          quality = new AlignmentAnnotation("Quality",
-                                            "Alignment Quality based on Blosum62 scores",
-                                            qannotations,
-                                            cons.qualityRange[0].floatValue(),
-                                            cons.qualityRange[1].floatValue(),
-                                            AlignmentAnnotation.BAR_GRAPH);
+          System.out.println("Conservation calculation: " + error);
+          System.gc();
 
-          if (showQuality)
-          {
-            alignment.addAnnotation(quality);
-          }
         }
-        else
+
+        if(ap!=null)
         {
-          conservation.annotations = annotations;
-          quality.annotations = qannotations;
-          quality.graphMax = cons.qualityRange[1].floatValue();
+          ap.repaint();
         }
+        updatingConservation = false;
       }
-      catch (OutOfMemoryError error)
-      {
-        javax.swing.SwingUtilities.invokeLater(new Runnable()
-        {
-          public void run()
-          {
-            javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
-                "Out of memory calculating conservation!!"
-                +
-                "\nSee help files for increasing Java Virtual Machine memory."
-                , "Out of memory",
-                javax.swing.JOptionPane.WARNING_MESSAGE);
-          }
-        });
+    }
 
-        System.out.println("Conservation calculation: " + error);
-        System.gc();
 
-      }
-    }
+    ConservationThread conservationThread;
+
+    ConsensusThread consensusThread;
+
+    boolean consUpdateNeeded = false;
+
+    boolean updatingConsensus = false;
+
+    boolean updatingConservation = false;
 
     /**
      * DOCUMENT ME!
      */
-    public void updateConsensus()
+    public void updateConservation(AlignmentPanel ap)
     {
-      try{
-        Annotation[] annotations = new Annotation[alignment.getWidth()];
+      if (alignment.isNucleotide())
+        return;
 
-        // this routine prevents vconsensus becoming a new object each time
-        // consenus is calculated. Important for speed of Blosum62
-        // and PID colouring of alignment
-        if (vconsensus == null)
-        {
-          vconsensus = alignment.getAAFrequency();
-        }
-        else
-        {
-          Vector temp = alignment.getAAFrequency();
-          vconsensus.clear();
+      updatingConservation = true;
 
-          Enumeration e = temp.elements();
+      if (conservationThread == null || !conservationThread.isAlive())
+      {
+        conservationThread = new ConservationThread(ap);
+        conservationThread.start();
+      }
+      else
+      {
+        consUpdateNeeded = true;
+        System.out.println("come back later");
+      }
+    }
 
-          while (e.hasMoreElements())
-          {
-            vconsensus.add(e.nextElement());
-          }
-        }
+    /**
+     * DOCUMENT ME!
+     */
+    public void updateConsensus(AlignmentPanel ap)
+    {
+      updatingConsensus = true;
 
-        Hashtable hash = null;
+      if (consensusThread == null || !consensusThread.isAlive())
+      {
+        consensusThread = new ConsensusThread(ap);
+        consensusThread.start();
+      }
+      else
+      {
+        consUpdateNeeded = true;
+        System.out.println("come back later");
+      }
+    }
 
-        for (int i = 0; i < alignment.getWidth(); i++)
+
+    class ConsensusThread extends Thread
+    {
+      AlignmentPanel ap;
+      public ConsensusThread(AlignmentPanel ap)
+      {
+        this.ap = ap;
+      }
+      public void run()
+      {
+        try
         {
-          hash = (Hashtable) vconsensus.elementAt(i);
+          int aWidth = alignment.getWidth();
 
-          float value = 0;
-          if (ignoreGapsInConsensusCalculation)
-            value = ( (Float) hash.get("pid_nogaps")).floatValue();
-          else
-            value = ( (Float) hash.get("pid_gaps")).floatValue();
+          consensus.annotations = null;
+          consensus.annotations = new Annotation[aWidth];
+
+          long t = System.currentTimeMillis();
+          hconsensus = new Hashtable[aWidth];
+          AAFrequency.calculate(alignment.getSequencesArray(),
+                                0,
+                                alignment.getWidth(),
+                                hconsensus);
 
-          String maxRes = hash.get("maxResidue").toString();
-          String mouseOver = hash.get("maxResidue") + " ";
+          System.out.println("Consensus took " +
+                             (System.currentTimeMillis() - t) + "ms");
 
-          if (maxRes.length() > 1)
+          for (int i = 0; i < aWidth; i++)
           {
-            mouseOver = "[" + maxRes + "] ";
-            maxRes = "+";
+            float value = 0;
+            if (ignoreGapsInConsensusCalculation)
+              value = ( (Float) hconsensus[i].get(AAFrequency.PID_NOGAPS)).
+                  floatValue();
+            else
+              value = ( (Float) hconsensus[i].get(AAFrequency.PID_GAPS)).
+                  floatValue();
+
+            String maxRes = hconsensus[i].get(AAFrequency.MAXRESIDUE).toString();
+            String mouseOver = hconsensus[i].get(AAFrequency.MAXRESIDUE) + " ";
+
+            if (maxRes.length() > 1)
+            {
+              mouseOver = "[" + maxRes + "] ";
+              maxRes = "+";
+            }
+
+            mouseOver += ( (int) value + "%");
+            consensus.annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);
           }
 
-          mouseOver += ( (int) value + "%");
-          annotations[i] = new Annotation(maxRes, mouseOver, ' ', value);
-        }
 
-        if (consensus == null)
-        {
-          consensus = new AlignmentAnnotation("Consensus", "PID",
-                                              annotations, 0f, 100f,AlignmentAnnotation.BAR_GRAPH);
+          if (globalColourScheme != null)
+            globalColourScheme.setConsensus(hconsensus);
 
-          if (showIdentity)
-          {
-            alignment.addAnnotation(consensus);
-          }
         }
-        else
+        catch (OutOfMemoryError error)
         {
-          consensus.annotations = annotations;
-        }
+          javax.swing.SwingUtilities.invokeLater(new Runnable()
+          {
+            public void run()
+            {
+              javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
+                  "Out of memory calculating consensus!!"
+                  +
+                  "\nSee help files for increasing Java Virtual Machine memory."
+                  , "Out of memory",
+                  javax.swing.JOptionPane.WARNING_MESSAGE);
+            }
+          });
 
-        if (globalColourScheme != null)
-          globalColourScheme.setConsensus(vconsensus);
+          System.out.println("Consensus calculation: " + error);
+          System.gc();
+        }
 
-      }catch(OutOfMemoryError error)
-      {
-        javax.swing.SwingUtilities.invokeLater(new Runnable()
+        if (ap != null)
         {
-          public void run()
-          {
-            javax.swing.JOptionPane.showInternalMessageDialog(Desktop.desktop,
-                "Out of memory calculating consensus!!"
-                +
-                "\nSee help files for increasing Java Virtual Machine memory."
-                , "Out of memory",
-                javax.swing.JOptionPane.WARNING_MESSAGE);
-          }
-        });
+          ap.repaint();
+        }
 
 
-        System.out.println("Consensus calculation: " + error);
-        System.gc();
+        updatingConsensus = false;
       }
-
     }
     /**
      * get the consensus sequence as displayed under the PID consensus annotation row.
@@ -450,7 +536,7 @@ public class AlignViewport
      */
     public SequenceI getConsensusSeq() {
       if (consensus==null)
-        updateConsensus();
+        updateConsensus(null);
       if (consensus==null)
         return null;
       StringBuffer seqs=new StringBuffer();
@@ -1095,10 +1181,10 @@ public class AlignViewport
         changeSupport.firePropertyChange(prop, oldvalue, newvalue);
     }
 
-    public void setIgnoreGapsConsensus(boolean b)
+    public void setIgnoreGapsConsensus(boolean b, AlignmentPanel ap)
     {
       ignoreGapsInConsensusCalculation = b;
-      updateConsensus();
+      updateConsensus(ap);
       if(globalColourScheme!=null)
       {
         globalColourScheme.setThreshold(globalColourScheme.getThreshold(), ignoreGapsInConsensusCalculation);
@@ -1352,8 +1438,10 @@ public class AlignViewport
       // object. Refactoring of Cigar and alignment view representation should
       // be done to remove redundancy.
       CigarArray aligview = getViewAsCigars(selectedOnly);
-      if (aligview!=null)
-        return new AlignmentView(aligview);
+      if (aligview!=null) {
+        return new AlignmentView(aligview,
+            (selectedOnly && selectionGroup!=null) ? selectionGroup.getStartRes() : 0);
+      }
       return null;
     }
     /**
@@ -1406,4 +1494,13 @@ public class AlignViewport
     {
       showHiddenMarkers = show;
     }
+
+    public String getSequenceSetId()
+    {
+      if(sequenceSetID==null)
+        sequenceSetID =  alignment.hashCode()+"";
+
+      return sequenceSetID;
+    }
+
 }