JAL-2629 add simple jackhmmer functionality
[jalview.git] / src / jalview / io / StockholmFile.java
index 71e369e..f7a2df2 100644 (file)
@@ -76,25 +76,36 @@ public class StockholmFile extends AlignFile
 {
   private static final String ANNOTATION = "annotation";
 
+  private static final char UNDERSCORE = '_';
+  
   private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
 
   private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
 
+  // private static final Regex OPEN_PAREN = new Regex("(<|\\[)", "(");
+  // private static final Regex CLOSE_PAREN = new Regex("(>|\\])", ")");
+
   public static final Regex DETECT_BRACKETS = new Regex(
           "(<|>|\\[|\\]|\\(|\\)|\\{|\\})");
 
-  public static final String RNASS_BRACKETS = "<>[]() {}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+  // WUSS extended symbols. Avoid ambiguity with protein SS annotations by using NOT_RNASS first.
+  public static final String RNASS_BRACKETS = "<>[](){}AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
+
+  // use the following regex to decide an annotations (whole) line is NOT an RNA
+  // SS (it contains only E,H,e,h and other non-brace/non-alpha chars)
+  private static final Regex NOT_RNASS = new Regex(
+          "^[^<>[\\](){}A-DF-Za-df-z]*$");
 
   StringBuffer out; // output buffer
 
-  AlignmentI al;
+  private AlignmentI al;
 
   public StockholmFile()
   {
   }
 
   /**
-   * Creates a new StockholmFile object for output.
+   * Creates a new StockholmFile object for output
    */
   public StockholmFile(AlignmentI al)
   {
@@ -221,7 +232,7 @@ public class StockholmFile extends AlignFile
       // logger.debug("Stockholm version: " + version);
     }
 
-    // We define some Regexes here that will be used regularily later
+    // We define some Regexes here that will be used regularly later
     rend = new Regex("^\\s*\\/\\/"); // Find the end of an alignment
     p = new Regex("(\\S+)\\/(\\d+)\\-(\\d+)"); // split sequence id in
     // id/from/to
@@ -629,14 +640,15 @@ public class StockholmFile extends AlignFile
             if (features.containsKey(this.id2type(type)))
             {
               // logger.debug("Found content for " + this.id2type(type));
-              content = (Hashtable) features.get(this.id2type(type));
+              content = (Hashtable) features
+                      .get(this.id2type(type));
             }
             else
             {
               // logger.debug("Creating new content holder for " +
               // this.id2type(type));
               content = new Hashtable();
-              features.put(this.id2type(type), content);
+              features.put(id2type(type), content);
             }
             String ns = (String) content.get(ANNOTATION);
 
@@ -811,17 +823,10 @@ public class StockholmFile extends AlignFile
           Vector<AlignmentAnnotation> annotation, String label,
           String annots)
   {
-    String convert1, convert2 = null;
-
-    // convert1 = OPEN_PAREN.replaceAll(annots);
-    // convert2 = CLOSE_PAREN.replaceAll(convert1);
+         String convert1, convert2 = null;
+    // String convert1 = OPEN_PAREN.replaceAll(annots);
+    // String convert2 = CLOSE_PAREN.replaceAll(convert1);
     // annots = convert2;
-    
-    // DEBUG
-    System.out.println(
-            "*** parseAnnotationRow called with\n      annotation='"
-                    + annotation + "'\n      label='" + label
-                    + "'\n      annots='" + annots + "'");
 
     String type = label;
     if (label.contains("_cons"))
@@ -834,10 +839,13 @@ public class StockholmFile extends AlignFile
     type = id2type(type);
 
     boolean isrnass = false;
+
     if (type.equalsIgnoreCase("secondary structure"))
     {
       ss = true;
-      isrnass = DETECT_BRACKETS.search(annots);
+      isrnass = !NOT_RNASS.search(annots); // sorry about the double negative
+                                           // here (it's easier for dealing with
+                                           // other non-alpha-non-brace chars)
     }
     if (type.equalsIgnoreCase("posterior probability"))
     {
@@ -848,6 +856,10 @@ public class StockholmFile extends AlignFile
     for (int i = 0; i < annots.length(); i++)
     {
       String pos = annots.substring(i, i + 1);
+      if (UNDERSCORE == pos.charAt(0))
+      {
+        pos = " ";
+      }
       Annotation ann;
       ann = new Annotation(pos, "", ' ', 0f); // 0f is 'valid' null - will not
       // be written out
@@ -1014,48 +1026,45 @@ public class StockholmFile extends AlignFile
       if (alAnot != null)
       {
         Annotation[] ann;
+
         for (int j = 0; j < alAnot.length; j++)
         {
-
-          String key = type2id(alAnot[j].label);
-          boolean isrna = alAnot[j].isValidStruc();
-          // bs debug
-          System.out.println("SEQUENCE " + i + "/" + s.length + " ISRNA="
-                  + isrna + ".");
-          if (isrna)
-          {
-            // hardwire to secondary structure if there is RNA secondary
-            // structure on the annotation
-            key = "SS";
-          }
-          if (key == null)
+          if (alAnot[j].annotations != null)
           {
+            String key = type2id(alAnot[j].label);
+            boolean isrna = alAnot[j].isValidStruc();
 
-            continue;
-          }
+            if (isrna)
+            {
+              // hardwire to secondary structure if there is RNA secondary
+              // structure on the annotation
+              key = "SS";
+            }
+            if (key == null)
+            {
 
-          // out.append("#=GR ");
-          out.append(new Format("%-" + maxid + "s").form(
-                  "#=GR " + printId(s[i], jvSuffix) + " " + key + " "));
-          ann = alAnot[j].annotations;
-          String seq = "";
-          for (int k = 0; k < ann.length; k++)
-          {
-            seq += outputCharacter(key, k, isrna, ann, s[i]);
+              continue;
+            }
+
+            // out.append("#=GR ");
+            out.append(new Format("%-" + maxid + "s").form(
+                    "#=GR " + printId(s[i], jvSuffix) + " " + key + " "));
+            ann = alAnot[j].annotations;
+            String seq = "";
+            for (int k = 0; k < ann.length; k++)
+            {
+              seq += outputCharacter(key, k, isrna, ann, s[i]);
+            }
+            out.append(seq);
+            out.append(newline);
           }
-          // bs debug
-          System.out.println("APPENDING SEQ: KEY=" + key + " ISRNA=" + isrna
-                  + ".\n" + "SEQ=" + seq + "\n");
-          out.append(seq);
-          out.append(newline);
         }
+
       }
 
       out.append(new Format("%-" + maxid + "s")
               .form(printId(s[i], jvSuffix) + " "));
       out.append(s[i].getSequenceAsString());
-      // bs debug
-      System.out.println("ALSO APPENDING " + s[i].getSequenceAsString());
       out.append(newline);
       i++;
     }
@@ -1103,12 +1112,6 @@ public class StockholmFile extends AlignFile
         {
           seq += outputCharacter(key, j, isrna, aa.annotations, null);
         }
-        
-        // bs debug
-        System.out.println(
-                "PRINTING SEQ: KEY=" + key + " ISRNA=" + isrna + ".\n"
-                        + "SEQ=" + seq + "\n");
-        
         out.append(seq);
         out.append(newline);
       }
@@ -1120,6 +1123,7 @@ public class StockholmFile extends AlignFile
     return out.toString();
   }
 
+
   /**
    * add an annotation character to the output row
    * 
@@ -1138,7 +1142,13 @@ public class StockholmFile extends AlignFile
     String ch = (annot == null)
             ? ((sequenceI == null) ? "-"
                     : Character.toString(sequenceI.getCharAt(k)))
-            : annot.displayCharacter;
+            : (annot.displayCharacter == null
+                    ? String.valueOf(annot.secondaryStructure)
+                    : annot.displayCharacter);
+    if (ch == null)
+    {
+      ch = " ";
+    }
     if (key != null && key.equals("SS"))
     {
       char ssannotchar = ' ';
@@ -1160,11 +1170,7 @@ public class StockholmFile extends AlignFile
       }
       if (charset)
       {
-        if (ssannotchar == ' ' && isrna)
-        {
-          ssannotchar = '.';
-        }
-        return ssannotchar;
+        return (ssannotchar == ' ' && isrna) ? '.' : ssannotchar;
       }
     }
 
@@ -1185,6 +1191,26 @@ public class StockholmFile extends AlignFile
             : seq;
   }
 
+  /**
+   * make a friendly ID string.
+   * 
+   * @param dataName
+   * @return truncated dataName to after last '/'
+   */
+  private String safeName(String dataName)
+  {
+    int b = 0;
+    while ((b = dataName.indexOf("/")) > -1 && b < dataName.length())
+    {
+      dataName = dataName.substring(b + 1).trim();
+
+    }
+    int e = (dataName.length() - dataName.indexOf(".")) + 1;
+    dataName = dataName.substring(1, e).trim();
+    return dataName;
+  }
+  
+  
   public String print()
   {
     out = new StringBuffer();
@@ -1222,7 +1248,7 @@ public class StockholmFile extends AlignFile
 
     }
   }
-
+  
   protected static String id2type(String id)
   {
     if (typeIds.containsKey(id))
@@ -1255,23 +1281,4 @@ public class StockholmFile extends AlignFile
             "Warning : Unknown Stockholm annotation type: " + type);
     return key;
   }
-
-  /**
-   * make a friendly ID string.
-   * 
-   * @param dataName
-   * @return truncated dataName to after last '/'
-   */
-  private String safeName(String dataName)
-  {
-    int b = 0;
-    while ((b = dataName.indexOf("/")) > -1 && b < dataName.length())
-    {
-      dataName = dataName.substring(b + 1).trim();
-
-    }
-    int e = (dataName.length() - dataName.indexOf(".")) + 1;
-    dataName = dataName.substring(1, e).trim();
-    return dataName;
-  }
 }