update author list in license for (JAL-826)
[jalview.git] / src / jalview / ws / DasSequenceFeatureFetcher.java
index 137bdb8..fd4d092 100644 (file)
@@ -1,20 +1,19 @@
 /*\r
- * Jalview - A Sequence Alignment Editor and Viewer\r
- * Copyright (C) 2007 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
- *\r
- * This program is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU General Public License\r
- * as published by the Free Software Foundation; either version 2\r
- * of the License, or (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)\r
+ * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle\r
+ * \r
+ * This file is part of Jalview.\r
+ * \r
+ * Jalview is free software: you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License \r
+ * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\r
+ * \r
+ * Jalview is distributed in the hope that it will be useful, but \r
+ * WITHOUT ANY WARRANTY; without even the implied warranty \r
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR \r
+ * PURPOSE.  See the GNU General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.\r
  */\r
 package jalview.ws;\r
 \r
@@ -31,10 +30,11 @@ import org.biojava.dasobert.eventmodel.*;
 import jalview.bin.Cache;\r
 import jalview.datamodel.*;\r
 import jalview.gui.*;\r
+import jalview.util.UrlLink;\r
 \r
 /**\r
  * DOCUMENT ME!\r
- *\r
+ * \r
  * @author $author$\r
  * @version $Revision$\r
  */\r
@@ -51,47 +51,78 @@ public class DasSequenceFeatureFetcher
   Vector selectedSources;\r
 \r
   boolean cancelled = false;\r
+\r
   private void debug(String mesg)\r
   {\r
     debug(mesg, null);\r
   }\r
+\r
   private void debug(String mesg, Exception e)\r
   {\r
-    if (Cache.log!=null)\r
+    if (Cache.log != null)\r
+    {\r
+      Cache.log.debug(mesg, e);\r
+    }\r
+    else\r
     {\r
-      debug(mesg, e);\r
-    } else {\r
       System.err.println(mesg);\r
-      if (e!=null)\r
-      { \r
-        e.printStackTrace(); \r
+      if (e != null)\r
+      {\r
+        e.printStackTrace();\r
       }\r
     }\r
   }\r
+\r
   long startTime;\r
 \r
   /**\r
-   * Creates a new SequenceFeatureFetcher object.\r
-   * Uses default\r
-   *\r
-   * @param align DOCUMENT ME!\r
-   * @param ap DOCUMENT ME!\r
+   * Creates a new SequenceFeatureFetcher object. Uses default\r
+   * \r
+   * @param align\r
+   *          DOCUMENT ME!\r
+   * @param ap\r
+   *          DOCUMENT ME!\r
    */\r
   public DasSequenceFeatureFetcher(SequenceI[] sequences,\r
           FeatureSettings fsettings, Vector selectedSources)\r
   {\r
     this(sequences, fsettings, selectedSources, true, true);\r
   }\r
-  public DasSequenceFeatureFetcher(SequenceI[] sequences,\r
-          FeatureSettings fsettings, Vector selectedSources, boolean checkDbrefs, boolean promptFetchDbrefs)\r
+\r
+  public DasSequenceFeatureFetcher(SequenceI[] oursequences,\r
+          FeatureSettings fsettings, Vector ourselectedSources,\r
+          boolean checkDbrefs, boolean promptFetchDbrefs)\r
   {\r
-    this.selectedSources = selectedSources;\r
-    this.sequences = sequences;\r
-    if (fsettings!=null)\r
+    this.selectedSources = new Vector();\r
+    Enumeration sources = ourselectedSources.elements();\r
+    // filter both sequences and sources to eliminate duplicates\r
+    while (sources.hasMoreElements())\r
+    {\r
+      Object src = sources.nextElement();\r
+      if (!selectedSources.contains(src))\r
+      {\r
+        selectedSources.addElement(src);\r
+      }\r
+      ;\r
+    }\r
+    Vector sqs = new Vector();\r
+    for (int i = 0; i < oursequences.length; i++)\r
+    {\r
+      if (!sqs.contains(oursequences[i]))\r
+      {\r
+        sqs.addElement(oursequences[i]);\r
+      }\r
+    }\r
+    sequences = new SequenceI[sqs.size()];\r
+    for (int i = 0; i < sequences.length; i++)\r
+    {\r
+      sequences[i] = (SequenceI) sqs.elementAt(i);\r
+    }\r
+    if (fsettings != null)\r
     {\r
       this.fsettings = fsettings;\r
       this.af = fsettings.af;\r
-      af.getViewport().setShowSequenceFeatures(true);\r
+      af.setShowSeqFeatures(true);\r
     }\r
     int uniprotCount = 0;\r
     for (int i = 0; i < selectedSources.size(); i++)\r
@@ -100,6 +131,8 @@ public class DasSequenceFeatureFetcher
       DasCoordinateSystem[] coords = source.getCoordinateSystem();\r
       for (int c = 0; c < coords.length; c++)\r
       {\r
+        // TODO: match UniProt coord system canonically (?) - does\r
+        // UniProt==uniprot==UNIPROT ?\r
         if (coords[c].getName().indexOf("UniProt") > -1)\r
         {\r
           uniprotCount++;\r
@@ -132,13 +165,15 @@ public class DasSequenceFeatureFetcher
       int reply = JOptionPane.YES_OPTION;\r
       if (promptFetchDbrefs)\r
       {\r
-        reply = JOptionPane.showInternalConfirmDialog(Desktop.desktop,\r
-             "Do you want Jalview to find\n"\r
-                      + "Uniprot Accession ids for given sequence names?",\r
-              "Find Uniprot Accession Ids", JOptionPane.YES_NO_OPTION,\r
-              JOptionPane.QUESTION_MESSAGE);\r
+        reply = JOptionPane\r
+                .showInternalConfirmDialog(\r
+                        Desktop.desktop,\r
+                        "Do you want Jalview to find\n"\r
+                                + "Uniprot Accession ids for given sequence names?",\r
+                        "Find Uniprot Accession Ids",\r
+                        JOptionPane.YES_NO_OPTION,\r
+                        JOptionPane.QUESTION_MESSAGE);\r
       }\r
-              \r
 \r
       if (reply == JOptionPane.YES_OPTION)\r
       {\r
@@ -167,37 +202,46 @@ public class DasSequenceFeatureFetcher
   }\r
 \r
   /**\r
-   * Spawns a number of dasobert Fetcher threads to add features to sequences in the dataset\r
+   * Spawns a number of dasobert Fetcher threads to add features to sequences in\r
+   * the dataset\r
    */\r
   void startFetching()\r
   {\r
     cancelled = false;\r
     startTime = System.currentTimeMillis();\r
-    if (af!=null)\r
+    if (af != null)\r
     {\r
       af.setProgressBar("Fetching DAS Sequence Features", startTime);\r
     }\r
 \r
-    DasSource[] sources = new jalview.gui.DasSourceBrowser().getDASSource();\r
-\r
     if (selectedSources == null || selectedSources.size() == 0)\r
     {\r
-      String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE",\r
-              "uniprot");\r
-      StringTokenizer st = new StringTokenizer(active, "\t");\r
-      Vector selectedSources = new Vector();\r
-      String token;\r
-      while (st.hasMoreTokens())\r
+      try\r
       {\r
-        token = st.nextToken();\r
-        for (int i = 0; i < sources.length; i++)\r
+        DasSource[] sources = new jalview.gui.DasSourceBrowser()\r
+                .getDASSource();\r
+\r
+        String active = jalview.bin.Cache.getDefault("DAS_ACTIVE_SOURCE",\r
+                "uniprot");\r
+        StringTokenizer st = new StringTokenizer(active, "\t");\r
+        selectedSources = new Vector();\r
+        String token;\r
+        while (st.hasMoreTokens())\r
         {\r
-          if (sources[i].getNickname().equals(token))\r
+          token = st.nextToken();\r
+          for (int i = 0; i < sources.length; i++)\r
           {\r
-            selectedSources.addElement(sources[i]);\r
-            break;\r
+            if (sources[i].getNickname().equals(token))\r
+            {\r
+              selectedSources.addElement(sources[i]);\r
+              break;\r
+            }\r
           }\r
         }\r
+      } catch (Exception ex)\r
+      {\r
+        debug("Exception whilst setting default feature sources from registry and local preferences.",\r
+                ex);\r
       }\r
     }\r
 \r
@@ -210,7 +254,7 @@ public class DasSequenceFeatureFetcher
     }\r
 \r
     sourcesRemaining = selectedSources.size();\r
-    //Now sending requests one at a time to each server\r
+    // Now sending requests one at a time to each server\r
     for (int sourceIndex = 0; sourceIndex < selectedSources.size()\r
             && !cancelled; sourceIndex++)\r
     {\r
@@ -224,18 +268,20 @@ public class DasSequenceFeatureFetcher
   private void setGuiNoDassourceActive()\r
   {\r
 \r
-    if (af!=null)\r
+    if (af != null)\r
     {\r
       af.setProgressBar("No DAS Sources Active", startTime);\r
     }\r
-    if (getFeatSettings()!=null)\r
+    if (getFeatSettings() != null)\r
     {\r
       fsettings.noDasSourceActive();\r
-     }\r
+    }\r
   }\r
 \r
   /**\r
-   * Update our fsettings dialog reference if we didn't have one when we were first initialised.\r
+   * Update our fsettings dialog reference if we didn't have one when we were\r
+   * first initialised.\r
+   * \r
    * @return fsettings\r
    */\r
   private FeatureSettings getFeatSettings()\r
@@ -252,7 +298,7 @@ public class DasSequenceFeatureFetcher
 \r
   public void cancel()\r
   {\r
-    if (af!=null)\r
+    if (af != null)\r
     {\r
       af.setProgressBar("DAS Feature Fetching Cancelled", startTime);\r
     }\r
@@ -288,8 +334,9 @@ public class DasSequenceFeatureFetcher
   private void setGuiFetchComplete()\r
   {\r
 \r
-    if (af != null)\r
+    if (!cancelled && af != null)\r
     {\r
+      // only update the progress bar if we've completed the fetch normally\r
       af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
     }\r
 \r
@@ -306,7 +353,7 @@ public class DasSequenceFeatureFetcher
 \r
   void featuresAdded(SequenceI seq)\r
   {\r
-    if (af==null)\r
+    if (af == null)\r
     {\r
       // no gui to update with features.\r
       return;\r
@@ -334,11 +381,13 @@ public class DasSequenceFeatureFetcher
     DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(\r
             seq.getDBRef(), new String[]\r
             {\r
-            //  jalview.datamodel.DBRefSource.PDB,\r
+            // jalview.datamodel.DBRefSource.PDB,\r
             jalview.datamodel.DBRefSource.UNIPROT,\r
-            //  jalview.datamodel.DBRefSource.EMBL - not tested on any EMBL coord sys sources\r
+            // jalview.datamodel.DBRefSource.EMBL - not tested on any EMBL coord\r
+            // sys sources\r
             });\r
-    // TODO: minimal list of DAS queries to make by querying with untyped ID if distinct from any typed IDs\r
+    // TODO: minimal list of DAS queries to make by querying with untyped ID if\r
+    // distinct from any typed IDs\r
 \r
     boolean dasCoordSysFound = false;\r
 \r
@@ -357,8 +406,9 @@ public class DasSequenceFeatureFetcher
           {\r
             debug("Launched fetcher for coordinate system "\r
                     + cs[0].getName());\r
-            //  Will have to pass any mapping information to the fetcher\r
-            //- the start/end for the DBRefEntry may not be the same as the sequence's start/end\r
+            // Will have to pass any mapping information to the fetcher\r
+            // - the start/end for the DBRefEntry may not be the same as the\r
+            // sequence's start/end\r
 \r
             System.out.println(seq.getName() + " "\r
                     + (seq.getDatasetSequence() == null) + " "\r
@@ -380,13 +430,14 @@ public class DasSequenceFeatureFetcher
       if (seq.getName().indexOf("|") > -1)\r
       {\r
         id = seq.getName().substring(seq.getName().lastIndexOf("|") + 1);\r
-        if (id.trim().length()<4)\r
+        if (id.trim().length() < 4)\r
         {\r
-          // hack - we regard a significant ID as being at least 4 non-whitespace characters\r
+          // hack - we regard a significant ID as being at least 4\r
+          // non-whitespace characters\r
           id = seq.getName().substring(0, seq.getName().lastIndexOf("|"));\r
-          if (id.indexOf("|")>-1)\r
+          if (id.indexOf("|") > -1)\r
           {\r
-            id = id.substring(id.lastIndexOf("|")+1);\r
+            id = id.substring(id.lastIndexOf("|") + 1);\r
           }\r
         }\r
       }\r
@@ -405,8 +456,10 @@ public class DasSequenceFeatureFetcher
   }\r
 \r
   /**\r
-   * fetch and add das features to a sequence using the given source URL and compatible DbRef id.\r
-   * new features are mapped using the DbRef mapping to the local coordinate system.\r
+   * fetch and add das features to a sequence using the given source URL and\r
+   * compatible DbRef id. new features are mapped using the DbRef mapping to the\r
+   * local coordinate system.\r
+   * \r
    * @param seq\r
    * @param SourceUrl\r
    * @param dbref\r
@@ -415,8 +468,8 @@ public class DasSequenceFeatureFetcher
           final DasSource dasSource, final DBRefEntry dbref)\r
   {\r
 \r
-    //////////////\r
-    /// fetch DAS features\r
+    // ////////////\r
+    // / fetch DAS features\r
     final Das1Source source = new Das1Source();\r
     source.setUrl(dasSource.getUrl());\r
     source.setNickname(dasSource.getNickname());\r
@@ -426,11 +479,10 @@ public class DasSequenceFeatureFetcher
       responseComplete(dasSource, seq); // reduce thread count anyhow\r
       return;\r
     }\r
-    debug("new Das Feature Fetcher for " + dbref.getSource()\r
-            + ":" + dbref.getAccessionId() + " querying "\r
-            + dasSource.getUrl());\r
+    debug("new Das Feature Fetcher for " + dbref.getSource() + ":"\r
+            + dbref.getAccessionId() + " querying " + dasSource.getUrl());\r
     FeatureThread fetcher = new FeatureThread(dbref.getAccessionId()\r
-    //  +  ":" + start + "," + end,\r
+    // + ":" + start + "," + end,\r
             , source);\r
 \r
     fetcher.addFeatureListener(new FeatureListener()\r
@@ -450,59 +502,61 @@ public class DasSequenceFeatureFetcher
 \r
         Map[] features = e.getFeatures();\r
         // add features to sequence\r
-        debug("das source " + ds.getUrl() + " returned "\r
-                + features.length + " features");\r
+        debug("das source " + ds.getUrl() + " returned " + features.length\r
+                + " features");\r
 \r
         if (features.length > 0)\r
         {\r
           for (int i = 0; i < features.length; i++)\r
           {\r
-            SequenceFeature f = newSequenceFeature(features[i], source\r
-                    .getNickname());\r
-            if (dbref.getMap() != null && f.getBegin() > 0\r
-                    && f.getEnd() > 0)\r
+            // standard DAS feature-> jalview sequence feature transformation\r
+            SequenceFeature f = newSequenceFeature(features[i],\r
+                    source.getNickname());\r
+            if (!parseSeqFeature(seq, f, features[i], source))\r
             {\r
-              debug("mapping from " + f.getBegin() + " - "\r
-                      + f.getEnd());\r
-              SequenceFeature vf[] = null;\r
-\r
-              try\r
+              if (dbref.getMap() != null && f.getBegin() > 0\r
+                      && f.getEnd() > 0)\r
               {\r
-                vf = dbref.getMap().locateFeature(f);\r
-              } catch (Exception ex)\r
-              {\r
-                Cache.log\r
-                        .info("Error in 'experimental' mapping of features. Please try to reproduce and then report info to help@jalview.org.");\r
-                Cache.log.info("Mapping feature from " + f.getBegin()\r
-                        + " to " + f.getEnd() + " in dbref "\r
-                        + dbref.getAccessionId() + " in "\r
-                        + dbref.getSource());\r
-                Cache.log.info("using das Source " + ds.getUrl());\r
-                Cache.log.info("Exception", ex);\r
-              }\r
+                debug("mapping from " + f.getBegin() + " - " + f.getEnd());\r
+                SequenceFeature vf[] = null;\r
 \r
-              if (vf != null)\r
-              {\r
-                for (int v = 0; v < vf.length; v++)\r
+                try\r
                 {\r
-                  debug("mapping to " + v + ": "\r
-                          + vf[v].getBegin() + " - " + vf[v].getEnd());\r
-                  seq.addSequenceFeature(vf[v]);\r
+                  vf = dbref.getMap().locateFeature(f);\r
+                } catch (Exception ex)\r
+                {\r
+                  Cache.log\r
+                          .info("Error in 'experimental' mapping of features. Please try to reproduce and then report info to jalview-discuss@jalview.org.");\r
+                  Cache.log.info("Mapping feature from " + f.getBegin()\r
+                          + " to " + f.getEnd() + " in dbref "\r
+                          + dbref.getAccessionId() + " in "\r
+                          + dbref.getSource());\r
+                  Cache.log.info("using das Source " + ds.getUrl());\r
+                  Cache.log.info("Exception", ex);\r
+                }\r
+\r
+                if (vf != null)\r
+                {\r
+                  for (int v = 0; v < vf.length; v++)\r
+                  {\r
+                    debug("mapping to " + v + ": " + vf[v].getBegin()\r
+                            + " - " + vf[v].getEnd());\r
+                    seq.addSequenceFeature(vf[v]);\r
+                  }\r
                 }\r
               }\r
-            }\r
-            else\r
-            {\r
-              seq.addSequenceFeature(f);\r
+              else\r
+              {\r
+                seq.addSequenceFeature(f);\r
+              }\r
             }\r
           }\r
-\r
           featuresAdded(seq);\r
         }\r
         else\r
         {\r
-          //  System.out.println("No features found for " + seq.getName()\r
-          //                     + " from: " + e.getDasSource().getNickname());\r
+          // System.out.println("No features found for " + seq.getName()\r
+          // + " from: " + e.getDasSource().getNickname());\r
         }\r
         responseComplete(dasSource, seq);\r
 \r
@@ -517,13 +571,13 @@ public class DasSequenceFeatureFetcher
   protected void createFeatureFetcher(final SequenceI seq,\r
           final DasSource dasSource, String id)\r
   {\r
-    //////////////\r
-    /// fetch DAS features\r
+    // ////////////\r
+    // / fetch DAS features\r
     final Das1Source source = new Das1Source();\r
     source.setUrl(dasSource.getUrl());\r
     source.setNickname(dasSource.getNickname());\r
-    \r
-    if (id!=null)\r
+\r
+    if (id != null)\r
     {\r
       id = id.trim();\r
     }\r
@@ -532,7 +586,7 @@ public class DasSequenceFeatureFetcher
       debug("new Das Feature Fetcher for " + id + " querying "\r
               + dasSource.getUrl());\r
       FeatureThread fetcher = new FeatureThread(id\r
-      //  +  ":" + start + "," + end,\r
+      // + ":" + start + "," + end,\r
               , source);\r
 \r
       fetcher.addFeatureListener(new FeatureListener()\r
@@ -559,18 +613,22 @@ public class DasSequenceFeatureFetcher
           {\r
             for (int i = 0; i < features.length; i++)\r
             {\r
-              SequenceFeature f = newSequenceFeature(features[i], source\r
-                      .getNickname());\r
-\r
-              seq.addSequenceFeature(f);\r
+              // standard DAS feature-> jalview sequence feature transformation\r
+              SequenceFeature f = newSequenceFeature(features[i],\r
+                      source.getNickname());\r
+              if (!parseSeqFeature(seq, f, features[i], source))\r
+              {\r
+                // just add as a simple sequence feature\r
+                seq.addSequenceFeature(f);\r
+              }\r
             }\r
 \r
             featuresAdded(seq);\r
           }\r
           else\r
           {\r
-            //  System.out.println("No features found for " + seq.getName()\r
-            //                     + " from: " + e.getDasSource().getNickname());\r
+            // System.out.println("No features found for " + seq.getName()\r
+            // + " from: " + e.getDasSource().getNickname());\r
           }\r
           responseComplete(dasSource, seq);\r
 \r
@@ -580,16 +638,122 @@ public class DasSequenceFeatureFetcher
       );\r
 \r
       fetcher.start();\r
-    } else {\r
+    }\r
+    else\r
+    {\r
       // invalid fetch - indicate it is finished.\r
-      debug("Skipping empty ID for querying "\r
-              + dasSource.getUrl());\r
+      debug("Skipping empty ID for querying " + dasSource.getUrl());\r
       responseComplete(dasSource, seq);\r
     }\r
   }\r
 \r
   /**\r
+   * examine the given sequence feature to determine if it should actually be\r
+   * turned into sequence annotation or database cross references rather than a\r
+   * simple sequence feature.\r
+   * \r
+   * @param seq\r
+   *          the sequence to annotate\r
+   * @param f\r
+   *          the jalview sequence feature generated from the DAS feature\r
+   * @param map\r
+   *          the sequence feature attributes\r
+   * @param source\r
+   *          the source that emitted the feature\r
+   * @return true if feature was consumed as another kind of annotation.\r
+   */\r
+  protected boolean parseSeqFeature(SequenceI seq, SequenceFeature f,\r
+          Map map, Das1Source source)\r
+  {\r
+    SequenceI mseq = seq;\r
+    while (seq.getDatasetSequence() != null)\r
+    {\r
+      seq = seq.getDatasetSequence();\r
+    }\r
+    if (f.getType() != null)\r
+    {\r
+      String type = f.getType();\r
+      if (type.equalsIgnoreCase("protein_name"))\r
+      {\r
+        // parse name onto the alignment sequence or the dataset sequence.\r
+        if (seq.getDescription() == null\r
+                || seq.getDescription().trim().length() == 0)\r
+        {\r
+          // could look at the note series to pick out the first long name, for\r
+          // the moment just use the whole description string\r
+          seq.setDescription(f.getDescription());\r
+        }\r
+        if (mseq.getDescription() == null\r
+                || mseq.getDescription().trim().length() == 0)\r
+        {\r
+          // could look at the note series to pick out the first long name, for\r
+          // the moment just use the whole description string\r
+          mseq.setDescription(f.getDescription());\r
+        }\r
+        return true;\r
+      }\r
+      // check if source has biosapiens or other sequence ontology label\r
+      if (type.equalsIgnoreCase("DBXREF") || type.equalsIgnoreCase("DBREF"))\r
+      {\r
+        // try to parse the accession out\r
+\r
+        DBRefEntry dbr = new DBRefEntry();\r
+        dbr.setVersion(source.getNickname());\r
+        StringTokenizer st = new StringTokenizer(f.getDescription(), ":");\r
+        if (st.hasMoreTokens())\r
+        {\r
+          dbr.setSource(st.nextToken());\r
+        }\r
+        if (st.hasMoreTokens())\r
+        {\r
+          dbr.setAccessionId(st.nextToken());\r
+        }\r
+        seq.addDBRef(dbr);\r
+\r
+        if (f.links != null && f.links.size() > 0)\r
+        {\r
+          // feature is also appended to enable links to be seen.\r
+          // TODO: consider extending dbrefs to have their own links ?\r
+          // TODO: new feature: extract dbref links from DAS servers and add the\r
+          // URL pattern to the list of DB name associated links in the user's\r
+          // preferences ?\r
+          // for the moment - just fix up the existing feature so it displays\r
+          // correctly.\r
+          // f.setType(dbr.getSource());\r
+          // f.setDescription();\r
+          f.setValue("linkonly", Boolean.TRUE);\r
+          // f.setDescription("");\r
+          Vector newlinks = new Vector();\r
+          Enumeration it = f.links.elements();\r
+          while (it.hasMoreElements())\r
+          {\r
+            String elm;\r
+            UrlLink urllink = new UrlLink(elm = (String) it.nextElement());\r
+            if (urllink.isValid())\r
+            {\r
+              urllink.setLabel(f.getDescription());\r
+              newlinks.addElement(urllink.toString());\r
+            }\r
+            else\r
+            {\r
+              // couldn't parse the link properly. Keep it anyway - just in\r
+              // case.\r
+              debug("couldn't parse link string - " + elm);\r
+              newlinks.addElement(elm);\r
+            }\r
+          }\r
+          f.links = newlinks;\r
+          seq.addSequenceFeature(f);\r
+        }\r
+        return true;\r
+      }\r
+    }\r
+    return false;\r
+  }\r
+\r
+  /**\r
    * creates a jalview sequence feature from a das feature document\r
+   * \r
    * @param dasfeature\r
    * @return sequence feature object created using dasfeature information\r
    */\r
@@ -602,14 +766,10 @@ public class DasSequenceFeatureFetcher
     try\r
     {\r
       /**\r
-       * Different qNames for a DAS Feature - are string keys to the HashMaps in features\r
-       * "METHOD") ||\r
-                  qName.equals("TYPE") ||\r
-                  qName.equals("START") ||\r
-                  qName.equals("END") ||\r
-                  qName.equals("NOTE") ||\r
-                  qName.equals("LINK") ||\r
-                  qName.equals("SCORE")\r
+       * Different qNames for a DAS Feature - are string keys to the HashMaps in\r
+       * features "METHOD") || qName.equals("TYPE") || qName.equals("START") ||\r
+       * qName.equals("END") || qName.equals("NOTE") || qName.equals("LINK") ||\r
+       * qName.equals("SCORE")\r
        */\r
       String desc = new String();\r
       if (dasfeature.containsKey("NOTE"))\r
@@ -634,18 +794,32 @@ public class DasSequenceFeatureFetcher
       }\r
       try\r
       {\r
-        score = Integer.parseInt(dasfeature.get("SCORE").toString());\r
+        Object scr = dasfeature.get("SCORE");\r
+        if (scr != null)\r
+        {\r
+          score = (float) Double.parseDouble(scr.toString());\r
+\r
+        }\r
       } catch (Exception ex)\r
       {\r
       }\r
 \r
-      SequenceFeature f = new SequenceFeature((String) dasfeature\r
-              .get("TYPE"), desc, start, end, score, nickname);\r
+      SequenceFeature f = new SequenceFeature(\r
+              (String) dasfeature.get("TYPE"), desc, start, end, score,\r
+              nickname);\r
 \r
       if (dasfeature.containsKey("LINK"))\r
       {\r
-        f.addLink(f.getType() + " " + f.begin + "_" + f.end + "|"\r
-                + dasfeature.get("LINK"));\r
+        // Do not put feature extent in link text for non-positional features\r
+        if (f.begin == 0 && f.end == 0)\r
+        {\r
+          f.addLink(f.getType() + "|" + dasfeature.get("LINK"));\r
+        }\r
+        else\r
+        {\r
+          f.addLink(f.getType() + " " + f.begin + "_" + f.end + "|"\r
+                  + dasfeature.get("LINK"));\r
+        }\r
       }\r
 \r
       return f;\r
@@ -658,9 +832,12 @@ public class DasSequenceFeatureFetcher
       return null;\r
     }\r
   }\r
+\r
   /**\r
-   * query the default DAS Source Registry for sources.\r
-   * Uses value of jalview property DAS_REGISTRY_URL and the DasSourceBrowser.DEFAULT_REGISTRY if that doesn't exist. \r
+   * query the default DAS Source Registry for sources. Uses value of jalview\r
+   * property DAS_REGISTRY_URL and the DasSourceBrowser.DEFAULT_REGISTRY if that\r
+   * doesn't exist.\r
+   * \r
    * @return list of sources\r
    */\r
   public static DasSource[] getDASSources()\r
@@ -670,10 +847,12 @@ public class DasSequenceFeatureFetcher
             DasSourceBrowser.DEFAULT_REGISTRY);\r
     return getDASSources(registryURL);\r
   }\r
+\r
   /**\r
    * query the given URL for DasSources.\r
+   * \r
    * @param registryURL\r
-   * return sources from registryURL\r
+   *          return sources from registryURL\r
    */\r
   public static DasSource[] getDASSources(String registryURL)\r
   {\r
@@ -709,6 +888,8 @@ public class DasSequenceFeatureFetcher
               .size()]);\r
     } catch (Exception ex)\r
     {\r
+      System.err.println("Failed to contact DAS1 registry at "\r
+              + registryURL);\r
       ex.printStackTrace();\r
       return null;\r
     }\r