This commit was manufactured by cvs2svn to create branch 'VamJalview'.
[jalview.git] / src / jalview / io / DasSequenceFeatureFetcher.java
diff --git a/src/jalview/io/DasSequenceFeatureFetcher.java b/src/jalview/io/DasSequenceFeatureFetcher.java
new file mode 100755 (executable)
index 0000000..f78f943
--- /dev/null
@@ -0,0 +1,474 @@
+/*\r
+* Jalview - A Sequence Alignment Editor and Viewer\r
+* Copyright (C) 2006 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
+*/\r
+package jalview.io;\r
+\r
+import jalview.datamodel.*;\r
+\r
+import jalview.gui.*;\r
+\r
+import java.util.*;\r
+\r
+import java.net.URL;\r
+\r
+import org.biojava.dasobert.das.FeatureThread;\r
+import org.biojava.dasobert.eventmodel.FeatureEvent;\r
+import org.biojava.dasobert.eventmodel.FeatureListener;\r
+import org.biojava.dasobert.dasregistry.DasSource;\r
+\r
+import org.biojava.dasobert.das2.io.DasSourceReaderImpl;\r
+import org.biojava.dasobert.dasregistry.Das1Source;\r
+import org.biojava.dasobert.dasregistry.DasSource;\r
+import org.biojava.dasobert.das2.Das2Source;\r
+import org.biojava.dasobert.das2.DasSourceConverter;\r
+\r
+\r
+import jalview.bin.Cache;\r
+import org.biojava.dasobert.dasregistry.DasCoordinateSystem;\r
+\r
+import javax.swing.*;\r
+\r
+/**\r
+ * DOCUMENT ME!\r
+ *\r
+ * @author $author$\r
+ * @version $Revision$\r
+ */\r
+public class DasSequenceFeatureFetcher implements Runnable\r
+{\r
+  SequenceI [] sequences;\r
+  AlignFrame af;\r
+  StringBuffer sbuffer = new StringBuffer();\r
+  Vector selectedSources;\r
+\r
+  long startTime;\r
+  int threadsRunning = 0;\r
+\r
+\r
+  /**\r
+   * Creates a new SequenceFeatureFetcher object.\r
+   * Uses default\r
+   *\r
+   * @param align DOCUMENT ME!\r
+   * @param ap DOCUMENT ME!\r
+   */\r
+  public DasSequenceFeatureFetcher(SequenceI [] sequences,\r
+                                   final AlignFrame af,\r
+                                   Vector selectedSources)\r
+  {\r
+    this.selectedSources = selectedSources;\r
+    this.sequences = sequences;\r
+    this.af = af;\r
+\r
+    int uniprotCount = 0;\r
+    for (int i = 0; i < selectedSources.size(); i++)\r
+    {\r
+      DasSource source = (DasSource) selectedSources.elementAt(i);\r
+      DasCoordinateSystem[] coords = source.getCoordinateSystem();\r
+      for (int c = 0; c < coords.length; c++)\r
+      {\r
+        if (coords[c].getName().indexOf("UniProt")>-1)\r
+        {\r
+          uniprotCount++;\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    int refCount = 0;\r
+    for(int i=0; i<sequences.length; i++)\r
+    {\r
+      DBRefEntry [] dbref = sequences[i].getDBRef();\r
+      if(dbref!=null)\r
+      {\r
+        for(int j=0; j<dbref.length; j++)\r
+        {\r
+          if(dbref[j].getSource()\r
+             .equals(jalview.datamodel.DBRefSource.UNIPROT))\r
+          {\r
+            refCount++;\r
+            break;\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    if(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
+\r
+     if(reply == JOptionPane.YES_OPTION)\r
+     {\r
+       Thread thread = new Thread(new FetchDBRefs());\r
+       thread.start();\r
+     }\r
+     else\r
+      startFetching();\r
+    }\r
+    else\r
+      startFetching();\r
+\r
+  /* System.out.println("User selection is "   +\r
+                       ( ( (float) uniprotCount / (float) selectedSources.size()) * 100)\r
+                      + " % Uniprot,  and "+refCount+" / " +sequences.length+" have uniprot accession");\r
+*/\r
+  }\r
+\r
+  void startFetching()\r
+  {\r
+    Thread thread = new Thread(this);\r
+    thread.start();\r
+  }\r
+\r
+  class FetchDBRefs implements Runnable\r
+  {\r
+    public void run()\r
+    {\r
+      new DBRefFetcher(\r
+             af.getViewport().getAlignment(), af).fetchDBRefs(true);\r
+      startFetching();\r
+    }\r
+  }\r
+\r
+\r
+  /**\r
+   * creates a jalview sequence feature from a das feature document\r
+   * @param dasfeature\r
+   * @return sequence feature object created using dasfeature information\r
+   */\r
+  SequenceFeature newSequenceFeature(Map dasfeature, String nickname)\r
+  {\r
+         try {\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
+          */\r
+                 String desc = new String();\r
+                 if (dasfeature.containsKey("NOTE"))\r
+                               desc+=(String) dasfeature.get("NOTE");\r
+\r
+\r
+                  int start = 0, end = 0;\r
+                  float score = 0f;\r
+\r
+                  try{ start = Integer.parseInt( dasfeature.get("START").toString()); }\r
+                  catch( Exception ex){}\r
+                  try{ end = Integer.parseInt( dasfeature.get("END").toString()); }\r
+                  catch (Exception ex){}\r
+                  try{ score = Integer.parseInt( dasfeature.get("SCORE").toString()); }\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
+\r
+                  if (dasfeature.containsKey("LINK"))\r
+                 {\r
+                      f.addLink(f.getType()+" "+f.begin+"_"+f.end\r
+                                +"|"+ dasfeature.get("LINK"));\r
+                 }\r
+                  // (String) dasfeature.get("ID"),\r
+                  ////  (String) dasfeature.get("METHOD"),\r
+                               //  (String) dasfeature.get("SCORE"),\r
+                               //  null\r
+                       // );\r
+\r
+         return f;\r
+         }\r
+         catch (Exception e) {\r
+            e.printStackTrace();\r
+                 Cache.log.debug("Failed to parse "+dasfeature.toString(), e);\r
+                 return null;\r
+         }\r
+  }\r
+  /**\r
+   * fetch and add das features to a sequence using the given source URL and Id to create a feature request\r
+   * @param seq\r
+   * @param SourceUrl\r
+   * @param id\r
+   */\r
+  protected void createFeatureFetcher(final SequenceI seq,\r
+                                      final String sourceUrl,\r
+                                      String id,\r
+                                      String nickname)\r
+  {\r
+         //////////////\r
+         /// fetch DAS features\r
+          final Das1Source source = new Das1Source();\r
+          source.setUrl(sourceUrl);\r
+          source.setNickname(nickname);\r
+\r
+\r
+          Cache.log.debug("new Das Feature Fetcher for " + id + " querying " +\r
+                          sourceUrl);\r
+\r
+          if (id != null && id.length() > 0)\r
+          {\r
+            setThreadsRunning(+1);\r
+\r
+          //  int start=seq.getStart(), end = seq.getEnd();\r
+          /*  if(af.getViewport().getSelectionGroup()!=null)\r
+            {\r
+              SequenceI tmp = af.getViewport().getAlignment().findName(seq.getName());\r
+              start = tmp.findPosition(\r
+              af.getViewport().getSelectionGroup().getStartRes()\r
+                  );\r
+\r
+              end = tmp.findPosition(\r
+                 af.getViewport().getSelectionGroup().getEndRes()\r
+                 );\r
+            }*/\r
+\r
+            FeatureThread fetcher = new FeatureThread(id\r
+                                                   //  +  ":" + start + "," + end,\r
+                                                      , source);\r
+\r
+\r
+            fetcher.addFeatureListener(new FeatureListener()\r
+            {\r
+              public void comeBackLater(FeatureEvent e)\r
+              {\r
+                setThreadsRunning(-1);\r
+                Cache.log.debug("das source " + e.getDasSource().getNickname() +\r
+                                " asked us to come back in " + e.getComeBackLater() +\r
+                                " secs.");\r
+              }\r
+\r
+              public void newFeatures(FeatureEvent e)\r
+              {\r
+                setThreadsRunning(-1);\r
+                Das1Source ds = e.getDasSource();\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
+\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
+\r
+                      seq.addSequenceFeature(f);\r
+                  }\r
+                }\r
+                else\r
+                {\r
+                  System.out.println("No features found for sequence " +seq.getName()\r
+                                     +" from: "+ e.getDasSource().getNickname());\r
+                }\r
+\r
+              }\r
+            }\r
+\r
+            );\r
+\r
+            //NOTE alignPanel listener will be called after the previous\r
+            //anonymous listener!!!\r
+            fetcher.addFeatureListener(af);\r
+\r
+            fetcher.start();\r
+         }\r
+  }\r
+\r
+  synchronized void setThreadsRunning(int i)\r
+  {\r
+    threadsRunning += i;\r
+    if(threadsRunning<1)\r
+    {\r
+      af.setProgressBar("DAS Feature Fetching Complete", startTime);\r
+\r
+      if(af.featureSettings!=null)\r
+        af.featureSettings.setTableData();\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Spawns a number of dasobert Fetcher threads to add features to sequences in the dataset\r
+   */\r
+  public void run()\r
+  {\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", "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
+      af.setProgressBar("No DAS Sources Active", startTime);\r
+      return;\r
+    }\r
+\r
+    try\r
+    {\r
+      int seqIndex = 0;\r
+      while (seqIndex < sequences.length)\r
+      {\r
+          DBRefEntry [] uprefs = jalview.util.DBRefUtils.selectRefs(sequences[seqIndex].getDBRef(),\r
+              new String[]  {\r
+              jalview.datamodel.DBRefSource.PDB,\r
+              jalview.datamodel.DBRefSource.UNIPROT});\r
+\r
+          for(int sourceIndex=0; sourceIndex<selectedSources.size(); sourceIndex++)\r
+          {\r
+            DasSource dasSource = (DasSource)selectedSources.elementAt(sourceIndex);\r
+\r
+            if (uprefs != null)\r
+            {\r
+              // we know the id for this entry, so don't note its ID in the unknownSequences list\r
+              for (int j = 0;  j < uprefs.length; j++)\r
+              {\r
+\r
+                // Will have to pass any mapping information to the fetcher - the start/end for the DBRefEntry may not be the same as the sequence's start/end\r
+                DasCoordinateSystem cs[] = dasSource.getCoordinateSystem();\r
+                for (int l=0; l<cs.length; l++)\r
+                {\r
+                  if (jalview.util.DBRefUtils.isDasCoordinateSystem(cs[l].getName(), uprefs[j]))\r
+                  {\r
+                    Cache.log.debug("Launched fetcher for coordinate system " +\r
+                                    cs[l].getName());\r
+\r
+\r
+                    createFeatureFetcher(sequences[seqIndex],\r
+                                         dasSource.getUrl(),\r
+                                          uprefs[j].getAccessionId(),\r
+                                         dasSource.getNickname());\r
+                  }\r
+                }\r
+              }\r
+            }\r
+            else\r
+            {\r
+              String id = null;\r
+              // try and use the name as the sequence id\r
+              if (sequences[seqIndex].getName().indexOf("|") > -1)\r
+              {\r
+                id = sequences[seqIndex].getName().substring(\r
+                    sequences[seqIndex].getName().lastIndexOf("|") + 1);\r
+              }\r
+              else\r
+              {\r
+                id = sequences[seqIndex].getName();\r
+              }\r
+              if (id != null)\r
+              {\r
+                // Should try to call a general feature fetcher that queries many sources with name to discover applicable ID references\r
+                createFeatureFetcher(sequences[seqIndex],\r
+                                     dasSource.getUrl(),\r
+                                     id,\r
+                                     dasSource.getNickname());\r
+              }\r
+            }\r
+          }\r
+\r
+          seqIndex++;\r
+    }\r
+    }\r
+    catch (Exception ex)\r
+    {\r
+      ex.printStackTrace();\r
+    }\r
+  }\r
+\r
+\r
+  public static DasSource[] getDASSources()\r
+  {\r
+    DasSourceReaderImpl reader = new DasSourceReaderImpl();\r
+\r
+    String registryURL =jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",\r
+        "http://das.sanger.ac.uk/registry/das1/sources/"\r
+      );\r
+\r
+    try\r
+    {\r
+      URL url = new URL(registryURL);\r
+\r
+      DasSource[] sources = reader.readDasSource(url);\r
+\r
+      List das1sources = new ArrayList();\r
+      for (int i = 0; i < sources.length; i++)\r
+      {\r
+        DasSource ds = sources[i];\r
+        if (ds instanceof Das2Source)\r
+        {\r
+          Das2Source d2s = (Das2Source) ds;\r
+          if (d2s.hasDas1Capabilities())\r
+          {\r
+            Das1Source d1s = DasSourceConverter.toDas1Source(d2s);\r
+            das1sources.add(d1s);\r
+          }\r
+\r
+        }\r
+        else if (ds instanceof Das1Source)\r
+        {\r
+          das1sources.add( (Das1Source) ds);\r
+        }\r
+      }\r
+\r
+      return (Das1Source[]) das1sources.toArray(new Das1Source[das1sources.size()]);\r
+    }\r
+    catch (Exception ex)\r
+    {\r
+      ex.printStackTrace();\r
+      return null;\r
+    }\r
+\r
+  }\r
+}\r
+\r
+\r