more efficient parsing of large files, do not create sequence features from GR annota...
[jalview.git] / src / jalview / io / StockholmFile.java
index d0d84f5..945b8c5 100644 (file)
@@ -31,9 +31,15 @@ import jalview.datamodel.*;
 \r
 /**\r
  * This class is supposed to parse a Stockholm format file into Jalview\r
- * \r
+ * There are TODOs in this class: we do not know what the database source and\r
+ * version is for the file when parsing the #GS= AC tag which associates accessions\r
+ * with sequences. \r
+ * Database references are also not parsed correctly: a separate reference string\r
+ * parser must be added to parse the database reference form into Jalview's local\r
+ * representation.\r
  * @author bsb at sanger.ac.uk\r
- * @version 0.3\r
+ * @version 0.3 + jalview mods\r
+ * \r
  */\r
 public class StockholmFile extends AlignFile\r
 {\r
@@ -91,7 +97,7 @@ public class StockholmFile extends AlignFile
     rend = new Regex("\\/\\/"); // Find the end of an alignment\r
     p = new Regex("(\\S+)\\/(\\d+)\\-(\\d+)"); // split sequence id in\r
                                                 // id/from/to\r
-    s = new Regex("(\\S+)\\s+(\\w{2})\\s+(.*)"); // Parses annotation subtype\r
+    s = new Regex("(\\S+)\\s+(\\S*)\\s+(.*)"); // Parses annotation subtype\r
     r = new Regex("#=(G[FSRC]?)\\s+(.*)"); // Finds any annotation line\r
     x = new Regex("(\\S+)\\s+(\\S+)"); // split id from sequence\r
 \r
@@ -118,7 +124,7 @@ public class StockholmFile extends AlignFile
         {\r
           String acc = (String) accs.nextElement();\r
           // logger.debug("Processing sequence " + acc);\r
-          String seq = (String) seqs.get(acc);\r
+          String seq = (String) seqs.remove(acc);\r
           if (maxLength < seq.length())\r
           {\r
             maxLength = seq.length();\r
@@ -131,7 +137,7 @@ public class StockholmFile extends AlignFile
 \r
           if (seqAnn != null && seqAnn.containsKey(acc))\r
           {\r
-            accAnnotations = (Hashtable) seqAnn.get(acc);\r
+            accAnnotations = (Hashtable) seqAnn.remove(acc);\r
           }\r
 \r
           // Split accession in id and from/to\r
@@ -158,16 +164,15 @@ public class StockholmFile extends AlignFile
             {\r
               String src = dbr.substring(0, dbr.indexOf(";"));\r
               String acn = dbr.substring(dbr.indexOf(";") + 1);\r
-              DBRefEntry dbref = new DBRefEntry(jalview.util.DBRefUtils\r
-                      .getCanonicalName(src), acn, "");\r
-              seqO.addDBRef(dbref);\r
+              jalview.util.DBRefUtils.parseToDbRef(seqO, src, "0", acn);\r
+              //seqO.addDBRef(dbref);\r
             }\r
           }\r
           Hashtable features = null;\r
           // We need to adjust the positions of all features to account for gaps\r
           try\r
           {\r
-            features = (Hashtable) accAnnotations.get("features");\r
+            features = (Hashtable) accAnnotations.remove("features");\r
           } catch (java.lang.NullPointerException e)\r
           {\r
             // loggerwarn("Getting Features for " + acc + ": " +\r
@@ -177,6 +182,7 @@ public class StockholmFile extends AlignFile
           // if we have features\r
           if (features != null)\r
           {\r
+            int posmap[] = seqO.findPositionMap();\r
             Enumeration i = features.keys();\r
             while (i.hasMoreElements())\r
             {\r
@@ -185,8 +191,7 @@ public class StockholmFile extends AlignFile
               // TODO: parse out scores as annotation row\r
               // TODO: map coding region to core jalview feature types\r
               String type = i.nextElement().toString();\r
-              Hashtable content = (Hashtable) features.get(type);\r
-\r
+              Hashtable content = (Hashtable) features.remove(type);\r
               Enumeration j = content.keys();\r
               while (j.hasMoreElements())\r
               {\r
@@ -196,9 +201,9 @@ public class StockholmFile extends AlignFile
                 for (int k = 0; k < byChar.length; k++)\r
                 {\r
                   char c = byChar[k];\r
-                  if (!(c == ' ' || c == '_' || c == '-'))\r
+                  if (!(c == ' ' || c == '_' || c == '-' || c == '.')) // PFAM uses '.' for feature background\r
                   {\r
-                    int new_pos = seqO.findPosition(k);\r
+                    int new_pos = posmap[k]; // look up nearest seqeunce position to this column\r
                     SequenceFeature feat = new SequenceFeature(type, desc,\r
                             new_pos, new_pos, 0f, null);\r
 \r
@@ -208,8 +213,10 @@ public class StockholmFile extends AlignFile
               }\r
 \r
             }\r
-\r
+            \r
           }\r
+          // garbage collect\r
+          \r
           // logger.debug("Adding seq " + acc + " from " + start + " to " + end\r
           // + ": " + seq);\r
           this.seqs.addElement(seqO);\r
@@ -365,14 +372,18 @@ public class StockholmFile extends AlignFile
           {\r
             String acc = s.stringMatched(1);\r
             String type = s.stringMatched(2);\r
-            String seq = s.stringMatched(3);\r
-            String description = new String();\r
-\r
+            String seq = new String(s.stringMatched(3));\r
+            String description = null;\r
             // Check for additional information about the current annotation\r
-            if (x.search(seq))\r
+            // We use a simple  string tokenizer here for speed\r
+            StringTokenizer sep = new StringTokenizer(seq," \t");\r
+            description = sep.nextToken();\r
+            if (sep.hasMoreTokens())\r
             {\r
-              description = x.stringMatched(1);\r
-              seq = x.stringMatched(2);\r
+              seq = sep.nextToken();\r
+            } else {\r
+              seq = description;\r
+              description = new String();\r
             }\r
             // sequence id with from-to fields\r
 \r
@@ -427,7 +438,8 @@ public class StockholmFile extends AlignFile
           }\r
           else\r
           {\r
-            throw new IOException("Error parsing " + line);\r
+            System.err.println("Warning - couldn't parse sequence annotation row line:\n"+line);\r
+            // throw new IOException("Error parsing " + line);\r
           }\r
         }\r
         else\r