JAL-629 Change all stdout and stderr output to use Console.outPrintln and Console...
[jalview.git] / src / jalview / analysis / StructureFrequency.java
index 29d02fe..3f5099b 100644 (file)
@@ -24,9 +24,9 @@ import jalview.datamodel.AlignmentAnnotation;
 import jalview.datamodel.Annotation;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceI;
+import jalview.util.Comparison;
 import jalview.util.Format;
 
-import java.util.ArrayList;
 import java.util.Hashtable;
 
 /**
@@ -93,11 +93,11 @@ public class StructureFrequency
    * @param rnaStruc
    */
   public static final void calculate(SequenceI[] sequences, int start,
-          int end, Hashtable[] result, boolean profile,
+          int end, Hashtable<String, Object>[] result, boolean profile,
           AlignmentAnnotation rnaStruc)
   {
 
-    Hashtable residueHash;
+    Hashtable<String, Object> residueHash;
     String maxResidue;
     char[] struc = rnaStruc.getRNAStruc().toCharArray();
 
@@ -111,8 +111,9 @@ public class StructureFrequency
 
     for (int i = start; i < end; i++) // foreach column
     {
-      int canonicalOrWobblePairCount = 0;
+      int canonicalOrWobblePairCount = 0, canonical = 0;
       int otherPairCount = 0;
+      int nongap = 0;
       maxResidue = "-";
       values = new int[255];
       pairs = new int[255][255];
@@ -147,25 +148,20 @@ public class StructureFrequency
           {
             if (sequences[j] == null)
             {
-              System.err
-                      .println("WARNING: Consensus skipping null sequence - possible race condition.");
+              jalview.bin.Console.errPrintln(
+                      "WARNING: Consensus skipping null sequence - possible race condition.");
               continue;
             }
-            c = sequences[j].getCharAt(i);
 
-            // standard representation for gaps in sequence and structure
-            if (c == '.' || c == ' ')
-            {
-              c = '-';
-            }
+            c = sequences[j].getCharAt(i);
+            cEnd = sequences[j].getCharAt(bpEnd);
 
-            if (c == '-')
+            if (Comparison.isGap(c) || Comparison.isGap(cEnd))
             {
               values['-']++;
               continue;
             }
-            cEnd = sequences[j].getCharAt(bpEnd);
-
+            nongap++;
             /*
              * ensure upper-case for counting purposes
              */
@@ -179,45 +175,66 @@ public class StructureFrequency
             }
             if (Rna.isCanonicalOrWobblePair(c, cEnd))
             {
-              values['(']++;
-              maxResidue = "(";
               canonicalOrWobblePairCount++;
+              if (Rna.isCanonicalPair(c, cEnd))
+              {
+                canonical++;
+              }
             }
             else
             {
-              values['[']++;
-              maxResidue = "[";
               otherPairCount++;
             }
             pairs[c][cEnd]++;
           }
         }
-        // nonGap++;
       }
 
-      residueHash = new Hashtable();
+      residueHash = new Hashtable<>();
       if (profile)
       {
         // TODO 1-dim array with jsize in [0], nongapped in [1]; or Pojo
-        residueHash.put(PROFILE, new int[][] { values,
-            new int[] { jSize, (jSize - values['-']) } });
+        residueHash.put(PROFILE,
+                new int[][]
+                { values, new int[] { jSize, (jSize - values['-']) } });
 
         residueHash.put(PAIRPROFILE, pairs);
       }
-      int count = Math.max(canonicalOrWobblePairCount, otherPairCount);
-      if (!maxResidue.equals("-"))
+      values['('] = canonicalOrWobblePairCount;
+      values['['] = canonical;
+      values['{'] = otherPairCount;
+      /*
+       * the count is the number of valid pairs (as a percentage, determines
+       * the relative size of the profile logo)
+       */
+      int count = canonicalOrWobblePairCount;
+
+      /*
+       * display '(' if most pairs are canonical, or as
+       * '[' if there are more wobble pairs. 
+       */
+      if (canonicalOrWobblePairCount > 0 || otherPairCount > 0)
       {
-        maxResidue = canonicalOrWobblePairCount >= otherPairCount ? "("
-                : "[";
+        if (canonicalOrWobblePairCount >= otherPairCount)
+        {
+          maxResidue = (canonicalOrWobblePairCount - canonical) < canonical
+                  ? "("
+                  : "[";
+        }
+        else
+        {
+          maxResidue = "{";
+        }
       }
-      residueHash.put(MAXCOUNT, new Integer(count));
+      residueHash.put(MAXCOUNT, Integer.valueOf(count));
       residueHash.put(MAXRESIDUE, maxResidue);
 
       percentage = ((float) count * 100) / jSize;
-      residueHash.put(PID_GAPS, new Float(percentage));
+      residueHash.put(PID_GAPS, Float.valueOf(percentage));
+
+      percentage = ((float) count * 100) / nongap;
+      residueHash.put(PID_NOGAPS, Float.valueOf(percentage));
 
-      // percentage = ((float) count * 100) / (float) nongap;
-      // residueHash.put(PID_NOGAPS, new Float(percentage));
       if (result[i] == null)
       {
         result[i] = residueHash;
@@ -226,24 +243,31 @@ public class StructureFrequency
       {
         values[')'] = values['('];
         values[']'] = values['['];
+        values['}'] = values['{'];
         values['('] = 0;
         values['['] = 0;
-        maxResidue = maxResidue.equals("(") ? ")" : "]";
+        values['{'] = 0;
+        maxResidue = maxResidue.equals("(") ? ")"
+                : maxResidue.equals("[") ? "]" : "}";
 
-        residueHash = new Hashtable();
+        residueHash = new Hashtable<>();
         if (profile)
         {
-          residueHash.put(PROFILE, new int[][] { values,
-              new int[] { jSize, (jSize - values['-']) } });
+          residueHash.put(PROFILE,
+                  new int[][]
+                  { values, new int[] { jSize, (jSize - values['-']) } });
 
           residueHash.put(PAIRPROFILE, pairs);
         }
 
-        residueHash.put(MAXCOUNT, new Integer(count));
+        residueHash.put(MAXCOUNT, Integer.valueOf(count));
         residueHash.put(MAXRESIDUE, maxResidue);
 
         percentage = ((float) count * 100) / jSize;
-        residueHash.put(PID_GAPS, new Float(percentage));
+        residueHash.put(PID_GAPS, Float.valueOf(percentage));
+
+        percentage = ((float) count * 100) / nongap;
+        residueHash.put(PID_NOGAPS, Float.valueOf(percentage));
 
         result[bpEnd] = residueHash;
       }
@@ -263,7 +287,7 @@ public class StructureFrequency
    * @param includeAllConsSymbols
    */
   public static void completeConsensus(AlignmentAnnotation consensus,
-          Hashtable[] hconsensus, int iStart, int width,
+          Hashtable<String, Object>[] hconsensus, int iStart, int width,
           boolean ignoreGapsInConsensusCalculation,
           boolean includeAllConsSymbols, long nseq)
   {
@@ -290,7 +314,7 @@ public class StructureFrequency
 
     for (int i = iStart; i < width; i++)
     {
-      Hashtable hci;
+      Hashtable<String, Object> hci;
       if (i >= hconsensus.length || ((hci = hconsensus[i]) == null))
       {
         // happens if sequences calculated over were shorter than alignment
@@ -390,7 +414,7 @@ public class StructureFrequency
    * @param hconsensus
    * @return profile of the given column
    */
-  public static int[] extractProfile(Hashtable hconsensus,
+  public static int[] extractProfile(Hashtable<String, Object> hconsensus,
           boolean ignoreGapsInConsensusCalculation)
   {
     int[] rtnval = new int[STRUCTURE_PROFILE_LENGTH]; // 2*(5*5)+2
@@ -422,7 +446,8 @@ public class StructureFrequency
     int valuesCount = 0;
     rtnval[1] = 0;
     int offset = 2;
-    final int divisor = profile[1][ignoreGapsInConsensusCalculation ? 1 : 0];
+    final int divisor = profile[1][ignoreGapsInConsensusCalculation ? 1
+            : 0];
     for (int c = 624; c > 0; c--)
     {
       if (vl[c] > 0)
@@ -442,23 +467,4 @@ public class StructureFrequency
     System.arraycopy(rtnval, 0, result, 1, rtnval.length);
     return result;
   }
-
-  public static void main(String args[])
-  {
-    // Short test to see if checkBpType works
-    ArrayList<String> test = new ArrayList<String>();
-    test.add("A");
-    test.add("c");
-    test.add("g");
-    test.add("T");
-    test.add("U");
-    for (String i : test)
-    {
-      for (String j : test)
-      {
-        System.out.println(i + "-" + j + ": "
-                + Rna.isCanonicalOrWobblePair(i.charAt(0), j.charAt(0)));
-      }
-    }
-  }
 }