JAL-1007 refactored code and patched calculation bug
[jalview.git] / src / jalview / analysis / StructureFrequency.java
index 0c9f830..67d8b9b 100644 (file)
@@ -1,18 +1,18 @@
 /*
  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, 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 
+ * 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 
+ *
+ * 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 <http://www.gnu.org/licenses/>.
  */
 
@@ -27,7 +27,7 @@ import jalview.datamodel.*;
  * returns a new Hashtable[] of size maxSeqLength, if Hashtable not supplied.
  * This class is used extensively in calculating alignment colourschemes that
  * depend on the amount of conservation in each alignment column.
- * 
+ *
  * @author $author$
  * @version $Revision$
  */
@@ -49,7 +49,7 @@ public class StructureFrequency
 
   /**
    * Returns the 3' position of a base pair
-   * 
+   *
    * @param pairs
    *          Secondary structure annotation
    * @param indice
@@ -71,7 +71,7 @@ public class StructureFrequency
   /**
    * Method to calculate a 'base pair consensus row', very similar to nucleotide
    * consensus but takes into account a given structure
-   * 
+   *
    * @param sequences
    * @param start
    * @param end
@@ -175,7 +175,7 @@ public class StructureFrequency
       residueHash.put(MAXCOUNT, new Integer(count));
       residueHash.put(MAXRESIDUE, maxResidue);
 
-      percentage = ((float) count * 100) / (float) jSize;
+      percentage = ((float) count * 100) / jSize;
       residueHash.put(PID_GAPS, new Float(percentage));
 
       // percentage = ((float) count * 100) / (float) nongap;
@@ -204,7 +204,7 @@ public class StructureFrequency
         residueHash.put(MAXCOUNT, new Integer(count));
         residueHash.put(MAXRESIDUE, maxResidue);
 
-        percentage = ((float) count * 100) / (float) jSize;
+        percentage = ((float) count * 100) / jSize;
         residueHash.put(PID_GAPS, new Float(percentage));
 
         result[bpEnd] = residueHash;
@@ -214,7 +214,7 @@ public class StructureFrequency
 
   /**
    * Method to check if a base-pair is a canonical or a wobble bp
-   * 
+   *
    * @param up
    *          5' base
    * @param down
@@ -286,7 +286,7 @@ public class StructureFrequency
   /**
    * Compute all or part of the annotation row from the given consensus
    * hashtable
-   * 
+   *
    * @param consensus
    *          - pre-allocated annotation row
    * @param hconsensus
@@ -310,7 +310,8 @@ public class StructureFrequency
     }
     for (int i = iStart; i < width; i++)
     {
-      if (i >= hconsensus.length)
+      Hashtable hci;
+      if (i >= hconsensus.length || ((hci=hconsensus[i])==null))
       {
         // happens if sequences calculated over were shorter than alignment
         // width
@@ -318,29 +319,34 @@ public class StructureFrequency
         continue;
       }
       value = 0;
+      Float fv;
       if (ignoreGapsInConsensusCalculation)
       {
-        value = ((Float) hconsensus[i].get(StructureFrequency.PID_NOGAPS))
-                .floatValue();
+        fv =(Float) hci.get(StructureFrequency.PID_NOGAPS);
       }
       else
       {
-        value = ((Float) hconsensus[i].get(StructureFrequency.PID_GAPS))
-                .floatValue();
+        fv = (Float) hci.get(StructureFrequency.PID_GAPS);
       }
-
-      String maxRes = hconsensus[i].get(StructureFrequency.MAXRESIDUE)
+      if (fv==null)
+      {
+        consensus.annotations[i] = null;
+        // data has changed below us .. give up and
+        continue;
+      }
+      value = fv.floatValue();
+      String maxRes = hci.get(StructureFrequency.MAXRESIDUE)
               .toString();
-      String mouseOver = hconsensus[i].get(StructureFrequency.MAXRESIDUE)
+      String mouseOver = hci.get(StructureFrequency.MAXRESIDUE)
               + " ";
       if (maxRes.length() > 1)
       {
         mouseOver = "[" + maxRes + "] ";
         maxRes = "+";
       }
-      int[][] profile = (int[][]) hconsensus[i]
+      int[][] profile = (int[][]) hci
               .get(StructureFrequency.PROFILE);
-      int[][] pairs = (int[][]) hconsensus[i]
+      int[][] pairs = (int[][]) hci
               .get(StructureFrequency.PAIRPROFILE);
 
       if (pairs != null && includeAllConsSymbols) // Just responsible for the
@@ -350,7 +356,7 @@ public class StructureFrequency
         mouseOver = "";
 
         /* TODO It's not sure what is the purpose of the alphabet and wheter it is useful for structure?
-         * 
+         *
          * if (alphabet != null) { for (int c = 0; c < alphabet.length; c++) {
          * tval = ((float) profile[0][alphabet[c]]) 100f / (float)
          * profile[1][ignoreGapsInConsensusCalculation ? 1 : 0]; mouseOver +=
@@ -366,7 +372,7 @@ public class StructureFrequency
           {
             ca[x] = new int[]
             { c, d };
-            vl[x] = (float) pairs[c][d];
+            vl[x] = pairs[c][d];
             x++;
           }
         }
@@ -377,7 +383,7 @@ public class StructureFrequency
         {
           if (vl[c] > 0)
           {
-            tval = ((float) vl[c] * 100f / (float) profile[1][ignoreGapsInConsensusCalculation ? 1
+            tval = (vl[c] * 100f / profile[1][ignoreGapsInConsensusCalculation ? 1
                     : 0]);
             mouseOver += ((p == 0) ? "" : "; ") + (char) ((int[]) ca[c])[0]
                     + (char) ((int[]) ca[c])[1] + " " + ((int) tval) + "%";
@@ -399,14 +405,14 @@ public class StructureFrequency
 
   /**
    * get the sorted base-pair profile for the given position of the consensus
-   * 
+   *
    * @param hconsensus
    * @return profile of the given column
    */
   public static int[] extractProfile(Hashtable hconsensus,
           boolean ignoreGapsInConsensusCalculation)
   {
-    int[] rtnval = new int[52]; // 2*(5*5)+2
+    int[] rtnval = new int[74]; // 2*(5*5)+2
     int[][] profile = (int[][]) hconsensus.get(StructureFrequency.PROFILE);
     int[][] pairs = (int[][]) hconsensus
             .get(StructureFrequency.PAIRPROFILE);
@@ -424,7 +430,7 @@ public class StructureFrequency
       {
         ca[x] = new int[]
         { c, d };
-        vl[x] = (float) pairs[c][d];
+        vl[x] = pairs[c][d];
         x++;
       }
     }
@@ -438,7 +444,7 @@ public class StructureFrequency
       {
         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) (vl[c] * 100f / profile[1][ignoreGapsInConsensusCalculation ? 1
                 : 0]);
         rtnval[1]+=rtnval[rtnval[0]++];
       }