JAL-722 alignment properties as table, additional data (redone)
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 6 Mar 2019 16:57:56 +0000 (16:57 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Wed, 6 Mar 2019 16:57:56 +0000 (16:57 +0000)
src/jalview/io/AlignmentProperties.java

index c1d6129..a65b83d 100644 (file)
@@ -21,6 +21,7 @@
 package jalview.io;
 
 import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
 
 import java.util.Arrays;
 import java.util.Comparator;
@@ -36,7 +37,11 @@ import java.util.Map;
 public class AlignmentProperties
 {
   private static final String BR_TAG = "<br>";
+
   private static final String NEWLINE = System.getProperty("line.separator");
+
+  private static final String PCT_FORMAT = "%.1f%%";
+
   AlignmentI alignment;
 
   public AlignmentProperties(AlignmentI alignment)
@@ -53,31 +58,58 @@ public class AlignmentProperties
   {
     StringBuilder sb = new StringBuilder(256);
     final String nl = html ? BR_TAG : NEWLINE;
-    float avg = 0;
-    int min = Integer.MAX_VALUE, max = 0;
-    for (int i = 0; i < alignment.getHeight(); i++)
+    int totalLength = 0;
+    int totalGaps = 0;
+    int minLength = Integer.MAX_VALUE;
+    int maxLength = 0;
+    float maxUngapped = 0f;
+    float minUngapped = Float.MAX_VALUE;
+
+    final int height = alignment.getHeight();
+    final int width = alignment.getWidth();
+
+    for (int i = 0; i < height; i++)
     {
-      int size = 1 + alignment.getSequenceAt(i).getEnd()
-              - alignment.getSequenceAt(i).getStart();
-      avg += size;
-      if (size > max)
-      {
-        max = size;
-      }
-      if (size < min)
-      {
-        min = size;
-      }
+      SequenceI seq = alignment.getSequenceAt(i);
+      // sequence length including gaps:
+      int seqWidth = seq.getLength();
+      // sequence length excluding gaps:
+      int seqLength = 1 + seq.getEnd() - seq.getStart();
+      int gapCount = seqWidth - seqLength; // includes padding
+      totalLength += seqLength;
+      totalGaps += gapCount;
+      maxLength = Math.max(maxLength, seqLength);
+      minLength = Math.min(minLength, seqLength);
+
+      /*
+       * proportion of aligned sequence that is ungapped
+       * (note: not normalised by alignment width here)
+       */
+      float ungapped = (seqLength - gapCount) / (float) seqLength;
+      maxUngapped = Math.max(maxUngapped, ungapped);
+      minUngapped = Math.min(minUngapped, ungapped);
     }
-    avg = avg / alignment.getHeight();
-    sb.append(nl);
-    sb.append("Sequences: " + alignment.getHeight());
-    sb.append(nl);
-    sb.append("Minimum Sequence Length: " + min);
-    sb.append(nl);
-    sb.append("Maximum Sequence Length: " + max);
-    sb.append(nl);
-    sb.append("Average Length: " + (int) avg);
+    float avgLength = totalLength / (float) height;
+
+    sb.append(html ? "<table border=\"1\">" : nl);
+    appendRow(sb, "Sequences", String.valueOf(height), html);
+    appendRow(sb, "Alignment width", String.valueOf(width),
+            html);
+    appendRow(sb, "Minimum Sequence Length", String.valueOf(minLength),
+            html);
+    appendRow(sb, "Maximum Sequence Length", String.valueOf(maxLength),
+            html);
+    appendRow(sb, "Average Length", String.valueOf((int) avgLength), html);
+    appendRow(sb, "Minimum (sequence length / width)",
+            String.format(PCT_FORMAT, minUngapped * 100f), html);
+    appendRow(sb, "Maximum (sequence length / width)",
+            String.format(PCT_FORMAT, maxUngapped * 100f), html);
+    appendRow(sb, "Residue density", String.format(PCT_FORMAT,
+            (totalLength - totalGaps) * 100f / totalLength), html);
+    appendRow(sb, "Gap density",
+            String.format(PCT_FORMAT, totalGaps * 100f / totalLength),
+            html);
+    sb.append(html ? "</table>" : nl);
 
     Map<Object, Object> props = alignment.getProperties();
     if (props != null && !props.isEmpty())