updated jalview version of dasobert 1.53e client and added Das Sequence Source discov...
[jalview.git] / src / jalview / ws / DasSequenceFeatureFetcher.java
index 2d4e73f..137bdb8 100644 (file)
@@ -41,12 +41,33 @@ import jalview.gui.*;
 public class DasSequenceFeatureFetcher\r
 {\r
   SequenceI[] sequences;\r
+\r
   AlignFrame af;\r
+\r
   FeatureSettings fsettings;\r
+\r
   StringBuffer sbuffer = new StringBuffer();\r
+\r
   Vector selectedSources;\r
-  boolean cancelled = false;\r
 \r
+  boolean cancelled = false;\r
+  private void debug(String mesg)\r
+  {\r
+    debug(mesg, null);\r
+  }\r
+  private void debug(String mesg, Exception e)\r
+  {\r
+    if (Cache.log!=null)\r
+    {\r
+      debug(mesg, e);\r
+    } else {\r
+      System.err.println(mesg);\r
+      if (e!=null)\r
+      { \r
+        e.printStackTrace(); \r
+      }\r
+    }\r
+  }\r
   long startTime;\r
 \r
   /**\r
@@ -57,14 +78,21 @@ public class DasSequenceFeatureFetcher
    * @param ap DOCUMENT ME!\r
    */\r
   public DasSequenceFeatureFetcher(SequenceI[] sequences,\r
-                                   FeatureSettings fsettings,\r
-                                   Vector selectedSources)\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
     this.selectedSources = selectedSources;\r
     this.sequences = sequences;\r
-    this.af = fsettings.af;\r
-    this.fsettings = fsettings;\r
-\r
+    if (fsettings!=null)\r
+    {\r
+      this.fsettings = fsettings;\r
+      this.af = fsettings.af;\r
+      af.getViewport().setShowSequenceFeatures(true);\r
+    }\r
     int uniprotCount = 0;\r
     for (int i = 0; i < selectedSources.size(); i++)\r
     {\r
@@ -88,8 +116,8 @@ public class DasSequenceFeatureFetcher
       {\r
         for (int j = 0; j < dbref.length; j++)\r
         {\r
-          if (dbref[j].getSource()\r
-              .equals(jalview.datamodel.DBRefSource.UNIPROT))\r
+          if (dbref[j].getSource().equals(\r
+                  jalview.datamodel.DBRefSource.UNIPROT))\r
           {\r
             refCount++;\r
             break;\r
@@ -98,15 +126,19 @@ public class DasSequenceFeatureFetcher
       }\r
     }\r
 \r
-    if (refCount < sequences.length && uniprotCount > 0)\r
+    if (checkDbrefs && refCount < sequences.length && uniprotCount > 0)\r
     {\r
 \r
-      int 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",\r
-          JOptionPane.YES_NO_OPTION,\r
-          JOptionPane.QUESTION_MESSAGE);\r
+      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
+      }\r
+              \r
 \r
       if (reply == JOptionPane.YES_OPTION)\r
       {\r
@@ -116,17 +148,16 @@ public class DasSequenceFeatureFetcher
       else\r
       {\r
         startFetching();\r
-    }\r
+      }\r
     }\r
     else\r
     {\r
       startFetching();\r
     }\r
 \r
-    }\r
+  }\r
 \r
-  class FetchDBRefs\r
-      implements Runnable\r
+  class FetchDBRefs implements Runnable\r
   {\r
     public void run()\r
     {\r
@@ -135,331 +166,401 @@ public class DasSequenceFeatureFetcher
     }\r
   }\r
 \r
+  /**\r
+   * Spawns a number of dasobert Fetcher threads to add features to sequences in the dataset\r
+   */\r
+  void startFetching()\r
+  {\r
+    cancelled = false;\r
+    startTime = System.currentTimeMillis();\r
+    if (af!=null)\r
+    {\r
+      af.setProgressBar("Fetching DAS Sequence Features", startTime);\r
+    }\r
 \r
-   /**\r
-    * Spawns a number of dasobert Fetcher threads to add features to sequences in the dataset\r
-    */\r
-   void startFetching()\r
-   {\r
-     cancelled = false;\r
-     startTime = System.currentTimeMillis();\r
-     af.setProgressBar("Fetching DAS Sequence Features", startTime);\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
-       {\r
-         token = st.nextToken();\r
-         for (int i = 0; i < sources.length; i++)\r
-         {\r
-           if (sources[i].getNickname().equals(token))\r
-           {\r
-             selectedSources.addElement(sources[i]);\r
-             break;\r
-           }\r
-         }\r
-       }\r
-     }\r
+    DasSource[] sources = new jalview.gui.DasSourceBrowser().getDASSource();\r
 \r
-     if (selectedSources == null || selectedSources.size() == 0)\r
-     {\r
-       System.out.println("No DAS Sources active");\r
-       af.setProgressBar("No DAS Sources Active", startTime);\r
-       cancelled = true;\r
-       fsettings.noDasSourceActive();\r
-       return;\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
+      {\r
+        token = st.nextToken();\r
+        for (int i = 0; i < sources.length; i++)\r
+        {\r
+          if (sources[i].getNickname().equals(token))\r
+          {\r
+            selectedSources.addElement(sources[i]);\r
+            break;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if (selectedSources == null || selectedSources.size() == 0)\r
+    {\r
+      System.out.println("No DAS Sources active");\r
+      cancelled = true;\r
+      setGuiNoDassourceActive();\r
+      return;\r
+    }\r
+\r
+    sourcesRemaining = selectedSources.size();\r
+    //Now sending requests one at a time to each server\r
+    for (int sourceIndex = 0; sourceIndex < selectedSources.size()\r
+            && !cancelled; sourceIndex++)\r
+    {\r
+      DasSource dasSource = (DasSource) selectedSources\r
+              .elementAt(sourceIndex);\r
+\r
+      nextSequence(dasSource, sequences[0]);\r
+    }\r
+  }\r
 \r
-       sourcesRemaining = selectedSources.size();\r
-       //Now sending requests one at a time to each server\r
-       for (int sourceIndex = 0;\r
-            sourceIndex < selectedSources.size()\r
-            && !cancelled;\r
-            sourceIndex++)\r
-       {\r
-         DasSource dasSource = (DasSource) selectedSources.elementAt(\r
-             sourceIndex);\r
-\r
-         nextSequence(dasSource, sequences[0]);\r
-       }\r
-   }\r
-\r
-   public void cancel()\r
-   {\r
-     af.setProgressBar("DAS Feature Fetching Cancelled", startTime);\r
-     cancelled = true;\r
-   }\r
-\r
-   int sourcesRemaining=0;\r
-   void responseComplete(DasSource dasSource, SequenceI seq)\r
-   {\r
-     if (seq != null)\r
-     {\r
-       for (int seqIndex = 0;\r
-            seqIndex < sequences.length-1\r
-            && !cancelled; seqIndex++)\r
-       {\r
-         if (sequences[seqIndex] == seq)\r
-         {\r
-           nextSequence(dasSource, sequences[++seqIndex]);\r
-           return;\r
-         }\r
-       }\r
+  private void setGuiNoDassourceActive()\r
+  {\r
+\r
+    if (af!=null)\r
+    {\r
+      af.setProgressBar("No DAS Sources Active", startTime);\r
+    }\r
+    if (getFeatSettings()!=null)\r
+    {\r
+      fsettings.noDasSourceActive();\r
      }\r
+  }\r
 \r
-     sourcesRemaining --;\r
+  /**\r
+   * Update our fsettings dialog reference if we didn't have one when we were first initialised.\r
+   * @return fsettings\r
+   */\r
+  private FeatureSettings getFeatSettings()\r
+  {\r
+    if (fsettings == null)\r
+    {\r
+      if (af != null)\r
+      {\r
+        fsettings = af.featureSettings;\r
+      }\r
+    }\r
+    return fsettings;\r
+  }\r
+\r
+  public void cancel()\r
+  {\r
+    if (af!=null)\r
+    {\r
+      af.setProgressBar("DAS Feature Fetching Cancelled", startTime);\r
+    }\r
+    cancelled = true;\r
+  }\r
 \r
-     if(sourcesRemaining==0)\r
-     {\r
-       af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
+  int sourcesRemaining = 0;\r
 \r
-       if(af.featureSettings!=null)\r
+  void responseComplete(DasSource dasSource, SequenceI seq)\r
+  {\r
+    if (seq != null)\r
+    {\r
+      for (int seqIndex = 0; seqIndex < sequences.length - 1 && !cancelled; seqIndex++)\r
       {\r
-         af.featureSettings.setTableData();\r
+        if (sequences[seqIndex] == seq)\r
+        {\r
+          nextSequence(dasSource, sequences[++seqIndex]);\r
+          return;\r
+        }\r
       }\r
+    }\r
 \r
-       fsettings.complete();\r
-     }\r
+    sourcesRemaining--;\r
 \r
-   }\r
+    if (sourcesRemaining == 0)\r
+    {\r
+      System.err.println("Fetching Complete.");\r
+      setGuiFetchComplete();\r
+    }\r
+\r
+  }\r
+\r
+  private void setGuiFetchComplete()\r
+  {\r
+\r
+    if (af != null)\r
+    {\r
+      af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
+    }\r
+\r
+    if (af != null && af.featureSettings != null)\r
+    {\r
+      af.featureSettings.setTableData();\r
+    }\r
 \r
-   void featuresAdded(SequenceI seq)\r
-   {\r
-     af.getFeatureRenderer().featuresAdded();\r
+    if (getFeatSettings() != null)\r
+    {\r
+      fsettings.complete();\r
+    }\r
+  }\r
+\r
+  void featuresAdded(SequenceI seq)\r
+  {\r
+    if (af==null)\r
+    {\r
+      // no gui to update with features.\r
+      return;\r
+    }\r
+    af.getFeatureRenderer().featuresAdded();\r
 \r
-     int start = af.getViewport().getStartSeq();\r
-     int end = af.getViewport().getEndSeq();\r
-     int index;\r
-     for(index=start; index<end; index++)\r
-       {\r
-      if (seq ==\r
-          af.getViewport().getAlignment().getSequenceAt(index).getDatasetSequence())\r
+    int start = af.getViewport().getStartSeq();\r
+    int end = af.getViewport().getEndSeq();\r
+    int index;\r
+    for (index = start; index < end; index++)\r
+    {\r
+      if (seq == af.getViewport().getAlignment().getSequenceAt(index)\r
+              .getDatasetSequence())\r
       {\r
         af.alignPanel.paintAlignment(true);\r
-         break;\r
-       }\r
-   }\r
+        break;\r
+      }\r
+    }\r
   }\r
 \r
-\r
   void nextSequence(DasSource dasSource, SequenceI seq)\r
   {\r
     if (cancelled)\r
       return;\r
-    DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(seq.getDBRef(),\r
-          new String[]\r
-          {\r
-        //  jalview.datamodel.DBRefSource.PDB,\r
-          jalview.datamodel.DBRefSource.UNIPROT,\r
-        //  jalview.datamodel.DBRefSource.EMBL - not tested on any EMBL coord sys sources\r
-      });\r
-// TODO: minimal list of DAS queries to make by querying with untyped ID if distinct from any typed IDs\r
+    DBRefEntry[] uprefs = jalview.util.DBRefUtils.selectRefs(\r
+            seq.getDBRef(), new String[]\r
+            {\r
+            //  jalview.datamodel.DBRefSource.PDB,\r
+            jalview.datamodel.DBRefSource.UNIPROT,\r
+            //  jalview.datamodel.DBRefSource.EMBL - not tested on any EMBL coord sys sources\r
+            });\r
+    // TODO: minimal list of DAS queries to make by querying with untyped ID if distinct from any typed IDs\r
 \r
-      boolean dasCoordSysFound = false;\r
+    boolean dasCoordSysFound = false;\r
 \r
-      if (uprefs != null)\r
+    if (uprefs != null)\r
+    {\r
+      // do any of these ids match the source's coordinate system ?\r
+      for (int j = 0; !dasCoordSysFound && j < uprefs.length; j++)\r
+      {\r
+        DasCoordinateSystem cs[] = dasSource.getCoordinateSystem();\r
+\r
+        for (int csIndex = 0; csIndex < cs.length && !dasCoordSysFound; csIndex++)\r
         {\r
-          // do any of these ids match the source's coordinate system ?\r
-          for (int j = 0; !dasCoordSysFound && j < uprefs.length; j++)\r
+          if (cs.length > 0\r
+                  && jalview.util.DBRefUtils.isDasCoordinateSystem(\r
+                          cs[csIndex].getName(), uprefs[j]))\r
           {\r
-            DasCoordinateSystem cs[] = dasSource.getCoordinateSystem();\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
 \r
-            for(int csIndex=0; csIndex<cs.length && !dasCoordSysFound; csIndex++)\r
-            {\r
-              if (cs.length > 0 && jalview.util.DBRefUtils\r
-                  .isDasCoordinateSystem(cs[csIndex].getName(), uprefs[j]))\r
-              {\r
-                Cache.log.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
-\r
-                System.out.println(seq.getName() + " " + (seq.getDatasetSequence() == null)\r
-                                   + " " + dasSource.getUrl());\r
-\r
-                dasCoordSysFound = true; // break's out of the loop\r
-                createFeatureFetcher(seq,\r
-                                     dasSource,\r
-                                     uprefs[j]);\r
-              }\r
-              else\r
-                System.out.println("IGNORE " + cs[csIndex].getName());\r
-            }\r
+            System.out.println(seq.getName() + " "\r
+                    + (seq.getDatasetSequence() == null) + " "\r
+                    + dasSource.getUrl());\r
+\r
+            dasCoordSysFound = true; // break's out of the loop\r
+            createFeatureFetcher(seq, dasSource, uprefs[j]);\r
           }\r
+          else\r
+            System.out.println("IGNORE " + cs[csIndex].getName());\r
         }\r
+      }\r
+    }\r
 \r
-        if(!dasCoordSysFound)\r
+    if (!dasCoordSysFound)\r
+    {\r
+      String id = null;\r
+      // try and use the name as the sequence id\r
+      if (seq.getName().indexOf("|") > -1)\r
+      {\r
+        id = seq.getName().substring(seq.getName().lastIndexOf("|") + 1);\r
+        if (id.trim().length()<4)\r
         {\r
-          String id = null;\r
-          // try and use the name as the sequence id\r
-          if (seq.getName().indexOf("|") > -1)\r
-          {\r
-            id = seq.getName().substring(\r
-                seq.getName().lastIndexOf("|") + 1);\r
-          }\r
-          else\r
-          {\r
-            id = seq.getName();\r
-          }\r
-          if (id != null)\r
+          // hack - we regard a significant ID as being at least 4 non-whitespace characters\r
+          id = seq.getName().substring(0, seq.getName().lastIndexOf("|"));\r
+          if (id.indexOf("|")>-1)\r
           {\r
-            // Should try to call a general feature fetcher that\r
-            // queries many sources with name to discover applicable ID references\r
-            createFeatureFetcher(seq,\r
-                                 dasSource,\r
-                                 id);\r
+            id = id.substring(id.lastIndexOf("|")+1);\r
           }\r
         }\r
+      }\r
+      else\r
+      {\r
+        id = seq.getName();\r
+      }\r
+      if (id != null)\r
+      {\r
+        // Should try to call a general feature fetcher that\r
+        // queries many sources with name to discover applicable ID references\r
+        createFeatureFetcher(seq, dasSource, id);\r
+      }\r
+    }\r
 \r
-   }\r
-\r
+  }\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
- * @param seq\r
- * @param SourceUrl\r
- * @param dbref\r
- */\r
-  protected void createFeatureFetcher(final SequenceI seq, final DasSource dasSource,\r
-        final DBRefEntry dbref) {\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
+   * @param seq\r
+   * @param SourceUrl\r
+   * @param dbref\r
+   */\r
+  protected void createFeatureFetcher(final SequenceI seq,\r
+          final DasSource dasSource, final DBRefEntry dbref)\r
+  {\r
 \r
     //////////////\r
     /// fetch DAS features\r
     final Das1Source source = new Das1Source();\r
     source.setUrl(dasSource.getUrl());\r
     source.setNickname(dasSource.getNickname());\r
-    if (dbref==null || dbref.getAccessionId()==null || dbref.getAccessionId().length()<1)\r
+    if (dbref == null || dbref.getAccessionId() == null\r
+            || dbref.getAccessionId().length() < 1)\r
     {\r
+      responseComplete(dasSource, seq); // reduce thread count anyhow\r
       return;\r
     }\r
-    Cache.log.debug("new Das Feature Fetcher for " + dbref.getSource()+":"+dbref.getAccessionId() + " querying " +\r
-                    dasSource.getUrl());\r
+    debug("new Das Feature Fetcher for " + dbref.getSource()\r
+            + ":" + dbref.getAccessionId() + " querying "\r
+            + dasSource.getUrl());\r
     FeatureThread fetcher = new FeatureThread(dbref.getAccessionId()\r
-                                                //  +  ":" + start + "," + end,\r
-                                                , source);\r
+    //  +  ":" + start + "," + end,\r
+            , source);\r
 \r
-      fetcher.addFeatureListener(new FeatureListener()\r
+    fetcher.addFeatureListener(new FeatureListener()\r
+    {\r
+      public void comeBackLater(FeatureEvent e)\r
       {\r
-        public void comeBackLater(FeatureEvent e)\r
-        {\r
-          responseComplete(dasSource, seq);\r
-          Cache.log.debug("das source " + e.getDasSource().getNickname() +\r
-                          " asked us to come back in " + e.getComeBackLater() +\r
-                          " secs.");\r
-        }\r
+        responseComplete(dasSource, seq);\r
+        debug("das source " + e.getSource().getNickname()\r
+                + " asked us to come back in " + e.getComeBackLater()\r
+                + " secs.");\r
+      }\r
 \r
-        public void newFeatures(FeatureEvent e)\r
-        {\r
+      public void newFeatures(FeatureEvent e)\r
+      {\r
 \r
-          Das1Source ds = e.getDasSource();\r
+        Das1Source ds = e.getSource();\r
 \r
-          Map[] features = e.getFeatures();\r
-          // add features to sequence\r
-          Cache.log.debug("das source " + ds.getUrl() + " returned " +\r
-                          features.length + " features");\r
+        Map[] features = e.getFeatures();\r
+        // add features to sequence\r
+        debug("das source " + ds.getUrl() + " returned "\r
+                + features.length + " features");\r
 \r
-          if (features.length > 0)\r
+        if (features.length > 0)\r
+        {\r
+          for (int i = 0; i < features.length; i++)\r
           {\r
-            for (int i = 0; i < features.length; i++)\r
+            SequenceFeature f = newSequenceFeature(features[i], source\r
+                    .getNickname());\r
+            if (dbref.getMap() != null && f.getBegin() > 0\r
+                    && f.getEnd() > 0)\r
             {\r
-              SequenceFeature f = newSequenceFeature(features[i],\r
-                  source.getNickname());\r
-              if (dbref.getMap()!=null && f.getBegin()>0 && f.getEnd()>0) {\r
-                Cache.log.debug("mapping from "+f.getBegin()+" - "+f.getEnd());\r
-                SequenceFeature vf[]=null;\r
-                \r
-                try {\r
-                  vf = dbref.getMap().locateFeature(f);\r
-                }\r
-                catch (Exception ex)\r
+              debug("mapping from " + f.getBegin() + " - "\r
+                      + f.getEnd());\r
+              SequenceFeature vf[] = null;\r
+\r
+              try\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
+\r
+              if (vf != null)\r
+              {\r
+                for (int v = 0; v < vf.length; v++)\r
                 {\r
-                  Cache.log.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()+" to "+f.getEnd()+" in dbref "+dbref.getAccessionId()+" in "+dbref.getSource());\r
-                  Cache.log.info("using das Source "+ds.getUrl());\r
-                  Cache.log.info("Exception", ex);\r
+                  debug("mapping to " + v + ": "\r
+                          + vf[v].getBegin() + " - " + vf[v].getEnd());\r
+                  seq.addSequenceFeature(vf[v]);\r
                 }\r
-                \r
-                if (vf!=null) {\r
-                  for (int v=0;v<vf.length;v++)\r
-                  {\r
-                    Cache.log.debug("mapping to "+v+": "+vf[v].getBegin()+" - "+vf[v].getEnd());\r
-                    seq.addSequenceFeature(vf[v]);\r
-                  }\r
-                }\r
-              } else {\r
-                seq.addSequenceFeature(f);\r
               }\r
             }\r
-\r
-            featuresAdded(seq);\r
+            else\r
+            {\r
+              seq.addSequenceFeature(f);\r
+            }\r
           }\r
-          else\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
-          }\r
-          responseComplete(dasSource, seq);\r
-\r
         }\r
+        responseComplete(dasSource, seq);\r
+\r
       }\r
+    }\r
 \r
-      );\r
+    );\r
+\r
+    fetcher.start();\r
+  }\r
 \r
-      fetcher.start();\r
-    }\r
   protected void createFeatureFetcher(final SequenceI seq,\r
-                                      final DasSource dasSource,\r
-                                      String id)\r
+          final DasSource dasSource, String id)\r
   {\r
     //////////////\r
     /// fetch DAS features\r
     final Das1Source source = new Das1Source();\r
     source.setUrl(dasSource.getUrl());\r
     source.setNickname(dasSource.getNickname());\r
-\r
-    Cache.log.debug("new Das Feature Fetcher for " + id + " querying " +\r
-                    dasSource.getUrl());\r
-\r
+    \r
+    if (id!=null)\r
+    {\r
+      id = id.trim();\r
+    }\r
     if (id != null && id.length() > 0)\r
     {\r
+      debug("new Das Feature Fetcher for " + id + " querying "\r
+              + dasSource.getUrl());\r
       FeatureThread fetcher = new FeatureThread(id\r
-                                                //  +  ":" + start + "," + end,\r
-                                                , source);\r
+      //  +  ":" + start + "," + end,\r
+              , source);\r
 \r
       fetcher.addFeatureListener(new FeatureListener()\r
       {\r
         public void comeBackLater(FeatureEvent e)\r
         {\r
           responseComplete(dasSource, seq);\r
-          Cache.log.debug("das source " + e.getDasSource().getNickname() +\r
-                          " asked us to come back in " + e.getComeBackLater() +\r
-                          " secs.");\r
+          debug("das source " + e.getSource().getNickname()\r
+                  + " asked us to come back in " + e.getComeBackLater()\r
+                  + " secs.");\r
         }\r
 \r
         public void newFeatures(FeatureEvent e)\r
         {\r
 \r
-          Das1Source ds = e.getDasSource();\r
+          Das1Source ds = e.getSource();\r
 \r
           Map[] features = e.getFeatures();\r
           // add features to sequence\r
-          Cache.log.debug("das source " + ds.getUrl() + " returned " +\r
-                          features.length + " features");\r
+          debug("das source " + ds.getUrl() + " returned "\r
+                  + features.length + " features");\r
 \r
           if (features.length > 0)\r
           {\r
             for (int i = 0; i < features.length; i++)\r
             {\r
-              SequenceFeature f = newSequenceFeature(features[i],\r
-                  source.getNickname());\r
+              SequenceFeature f = newSequenceFeature(features[i], source\r
+                      .getNickname());\r
 \r
               seq.addSequenceFeature(f);\r
             }\r
@@ -468,8 +569,8 @@ public class DasSequenceFeatureFetcher
           }\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
@@ -479,6 +580,11 @@ public class DasSequenceFeatureFetcher
       );\r
 \r
       fetcher.start();\r
+    } else {\r
+      // invalid fetch - indicate it is finished.\r
+      debug("Skipping empty ID for querying "\r
+              + dasSource.getUrl());\r
+      responseComplete(dasSource, seq);\r
     }\r
   }\r
 \r
@@ -489,7 +595,7 @@ public class DasSequenceFeatureFetcher
    */\r
   SequenceFeature newSequenceFeature(Map dasfeature, String nickname)\r
   {\r
-    if (dasfeature==null)\r
+    if (dasfeature == null)\r
     {\r
       return null;\r
     }\r
@@ -517,55 +623,61 @@ public class DasSequenceFeatureFetcher
       try\r
       {\r
         start = Integer.parseInt(dasfeature.get("START").toString());\r
+      } catch (Exception ex)\r
+      {\r
       }\r
-      catch (Exception ex)\r
-      {}\r
       try\r
       {\r
         end = Integer.parseInt(dasfeature.get("END").toString());\r
+      } catch (Exception ex)\r
+      {\r
       }\r
-      catch (Exception ex)\r
-      {}\r
       try\r
       {\r
         score = Integer.parseInt(dasfeature.get("SCORE").toString());\r
+      } catch (Exception ex)\r
+      {\r
       }\r
-      catch (Exception ex)\r
-      {}\r
 \r
-      SequenceFeature f = new SequenceFeature(\r
-          (String) dasfeature.get("TYPE"),\r
-          desc,\r
-          start,\r
-          end,\r
-          score,\r
-          nickname);\r
+      SequenceFeature f = new SequenceFeature((String) dasfeature\r
+              .get("TYPE"), desc, start, end, score, nickname);\r
 \r
       if (dasfeature.containsKey("LINK"))\r
       {\r
-        f.addLink(f.getType() + " " + f.begin + "_" + f.end\r
-                  + "|" + dasfeature.get("LINK"));\r
+        f.addLink(f.getType() + " " + f.begin + "_" + f.end + "|"\r
+                + dasfeature.get("LINK"));\r
       }\r
 \r
       return f;\r
-    }\r
-    catch (Exception e)\r
+    } catch (Exception e)\r
     {\r
       System.out.println("ERRR " + e);\r
       e.printStackTrace();\r
       System.out.println("############");\r
-      Cache.log.debug("Failed to parse " + dasfeature.toString(), e);\r
+      debug("Failed to parse " + dasfeature.toString(), e);\r
       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
+   * @return list of sources\r
+   */\r
   public static DasSource[] getDASSources()\r
   {\r
-    DasSourceReaderImpl reader = new DasSourceReaderImpl();\r
 \r
     String registryURL = jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
-        DasSourceBrowser.DEFAULT_REGISTRY\r
-        );\r
+            DasSourceBrowser.DEFAULT_REGISTRY);\r
+    return getDASSources(registryURL);\r
+  }\r
+  /**\r
+   * query the given URL for DasSources.\r
+   * @param registryURL\r
+   * return sources from registryURL\r
+   */\r
+  public static DasSource[] getDASSources(String registryURL)\r
+  {\r
+    DasSourceReaderImpl reader = new DasSourceReaderImpl();\r
 \r
     try\r
     {\r
@@ -589,13 +701,13 @@ public class DasSequenceFeatureFetcher
         }\r
         else if (ds instanceof Das1Source)\r
         {\r
-          das1sources.add( (Das1Source) ds);\r
+          das1sources.add((Das1Source) ds);\r
         }\r
       }\r
 \r
-      return (Das1Source[]) das1sources.toArray(new Das1Source[das1sources.size()]);\r
-    }\r
-    catch (Exception ex)\r
+      return (Das1Source[]) das1sources.toArray(new Das1Source[das1sources\r
+              .size()]);\r
+    } catch (Exception ex)\r
     {\r
       ex.printStackTrace();\r
       return null;\r
@@ -603,4 +715,3 @@ public class DasSequenceFeatureFetcher
   }\r
 \r
 }\r
-\r