refactored form of vamsas document interaction code
[jalview.git] / src / jalview / io / vamsas / Tree.java
index 3946a98..12c471e 100644 (file)
@@ -5,10 +5,14 @@ import java.util.Hashtable;
 import java.util.Vector;\r
 \r
 import jalview.analysis.NJTree;\r
+import jalview.bin.Cache;\r
 import jalview.datamodel.AlignmentI;\r
+import jalview.datamodel.AlignmentView;\r
 import jalview.datamodel.SeqCigar;\r
 import jalview.datamodel.SequenceI;\r
+import jalview.gui.AlignViewport;\r
 import jalview.gui.TreePanel;\r
+import jalview.io.NewickFile;\r
 import jalview.io.VamsasAppDatastore;\r
 import uk.ac.vamsas.client.Vobject;\r
 import uk.ac.vamsas.objects.core.Entry;\r
@@ -25,7 +29,51 @@ public class Tree extends DatastoreItem
   AlignmentI jal;\r
   TreePanel tp;\r
   uk.ac.vamsas.objects.core.Tree tree;\r
-  uk.ac.vamsas.objects.core.Alignment alignment; // may be null => dataset or other kind of tree\r
+  uk.ac.vamsas.objects.core.Alignment alignment; // may be null => dataset or\r
+                                                  // other kind of tree\r
+  private NewickFile ntree;\r
+  private String title;\r
+  private AlignmentView inputData = null;\r
+  public static void updateFrom(VamsasAppDatastore datastore, jalview.gui.AlignFrame alignFrame, uk.ac.vamsas.objects.core.Tree vtree) {\r
+    Tree toTree = new Tree(datastore, alignFrame, vtree);\r
+    \r
+  }\r
+  public Tree(VamsasAppDatastore datastore, jalview.gui.AlignFrame alignFrame, uk.ac.vamsas.objects.core.Tree vtree)\r
+  {\r
+    super(datastore);\r
+    tree = vtree;\r
+    TreePanel tp = (TreePanel) getvObj2jv(tree);\r
+    if (tp != null) {\r
+      if (tree.isUpdated())\r
+      {\r
+        Cache.log.info(\r
+                "Update from vamsas document to alignment associated tree not implemented yet.");\r
+      }\r
+    }\r
+    else\r
+    {\r
+      // make a new tree\r
+      Object[] idata = this.recoverInputData(tree.getProvenance());\r
+      try\r
+      {\r
+        if (idata != null && idata[0] != null)\r
+        {\r
+          inputData = (AlignmentView) idata[0];\r
+        }\r
+        ntree = new jalview.io.NewickFile(tree.getNewick(0).getContent());\r
+        title = tree.getNewick(0).getTitle();\r
+        if (title==null || title.length()==0)\r
+        {\r
+          title = tree.getTitle(); // hack!!!!\r
+        }\r
+      }\r
+      catch (Exception e)\r
+      {\r
+        Cache.log.warn("Problems parsing treefile '" +\r
+                       tree.getNewick(0).getContent() + "'", e);\r
+      }\r
+    }\r
+  }\r
   public Tree(VamsasAppDatastore datastore, TreePanel tp2, AlignmentI jal2, uk.ac.vamsas.objects.core.Alignment alignment2)\r
   {\r
     super(datastore);\r
@@ -58,13 +106,14 @@ public class Tree extends DatastoreItem
   /**\r
    * correctly creates provenance for trees calculated on an alignment by\r
    * jalview.\r
-   *\r
+   * \r
    * @param jal\r
    * @param tp\r
    * @return\r
    */\r
   private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp)\r
   {\r
+    Cache.log.debug("Making Tree provenance for "+tp.getTitle());\r
     Provenance prov = new Provenance();\r
     prov.addEntry(new Entry());\r
     prov.getEntry(0).setAction("imported " + tp.getTitle());\r
@@ -75,7 +124,8 @@ public class Tree extends DatastoreItem
     {\r
       Input vInput = new Input();\r
       // LATER: check to see if tree input data is contained in this alignment -\r
-      // or just correctly resolve the tree's seqData to the correct alignment in\r
+      // or just correctly resolve the tree's seqData to the correct alignment\r
+      // in\r
       // the document.\r
       Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal, tp.getTree().seqData.getSequences()));\r
       Object[] alsqs = new Object[alsqrefs.size()];\r
@@ -91,7 +141,8 @@ public class Tree extends DatastoreItem
       prov.getEntry(0).getParam(0).setType("utf8");\r
       prov.getEntry(0).getParam(0).setContent("NJ");\r
       int ranges[] = tp.getTree().seqData.getVisibleContigs();\r
-      // VisibleContigs are with respect to alignment coordinates. Still need offsets\r
+      // VisibleContigs are with respect to alignment coordinates. Still need\r
+      // offsets\r
       int start = tp.getTree().seqData.getAlignmentOrigin();\r
       for (int r = 0; r < ranges.length; r += 2)\r
       {\r
@@ -102,13 +153,16 @@ public class Tree extends DatastoreItem
         vInput.addSeg(visSeg);\r
       }\r
     }\r
+    Cache.log.debug("Finished Tree provenance for "+tp.getTitle());\r
     return prov;\r
   }\r
   /**\r
    * look up SeqCigars in an existing alignment.\r
+   * \r
    * @param jal\r
    * @param sequences\r
-   * @return vector of alignment sequences in order of SeqCigar array (but missing unfound seqcigars)\r
+   * @return vector of alignment sequences in order of SeqCigar array (but\r
+   *         missing unfound seqcigars)\r
    */\r
   private Vector findAlignmentSequences(AlignmentI jal, SeqCigar[] sequences)\r
   {\r
@@ -122,16 +176,24 @@ public class Tree extends DatastoreItem
       for (int t = 0; t<sequences.length; t++)\r
       {\r
         if (tseqs[t]!=null \r
-                && (tseqs[t].getRefSeq()==asq || tseqs[t].getRefSeq() == asq.getDatasetSequence())\r
-                && tseqs[t].getStart()>=asq.getStart() && tseqs[t].getEnd()<=asq.getEnd())\r
+                && (tseqs[t].getRefSeq()==asq || tseqs[t].getRefSeq() == asq.getDatasetSequence()))\r
+                // && tseqs[t].getStart()>=asq.getStart() && tseqs[t].getEnd()<=asq.getEnd())\r
         {\r
           tseqs[t] = null;\r
           alsq.add(asq);\r
         }\r
       }\r
     }\r
+    if (alsq.size()<sequences.length)\r
+      Cache.log.warn("Not recovered all alignment sequences for given set of input sequence CIGARS");\r
     return alsq;\r
   }\r
+  /**\r
+   * construct treenode mappings for mapped sequences\r
+   * \r
+   * @param ntree\r
+   * @return\r
+   */\r
   public Treenode[] makeTreeNodes(NJTree ntree) {\r
     Vector leaves = new Vector();\r
     ntree.findLeaves(ntree.getTopNode(), leaves);\r
@@ -190,8 +252,10 @@ public class Tree extends DatastoreItem
   }\r
   /**\r
    * call to match up Treenode specs to NJTree parsed from document object.\r
+   * \r
    * @param nodespec\r
-   * @param leaves as returned from NJTree.findLeaves( .., ..) .. \r
+   * @param leaves\r
+   *          as returned from NJTree.findLeaves( .., ..) ..\r
    * @return\r
    */\r
   private jalview.datamodel.BinaryNode findNodeSpec(String nodespec, Vector leaves)\r
@@ -222,7 +286,10 @@ public class Tree extends DatastoreItem
     }\r
     return bn;\r
   }\r
-  \r
+  /**\r
+   * add jalview object to vamsas document\r
+   * \r
+   */\r
   public void add() {\r
     tree = new uk.ac.vamsas.objects.core.Tree();\r
     bindjvvobj(tp, tree);\r
@@ -236,4 +303,104 @@ public class Tree extends DatastoreItem
     \r
     alignment.addTree(tree);\r
   }\r
+\r
+  /**\r
+   * note: this function assumes that all sequence and alignment objects\r
+   * referenced in input data has already been associated with jalview objects.\r
+   * \r
+   * @param tp\r
+   * @return Object[] { AlignmentView, AlignmentI - reference alignment for\r
+   *         input }\r
+   */\r
+  public Object[] recoverInputData(Provenance tp)\r
+  {\r
+    AlignViewport javport=null;\r
+    jalview.datamodel.AlignmentI jal=null;\r
+    jalview.datamodel.CigarArray view=null;\r
+    for (int pe = 0; pe < tp.getEntryCount(); pe++)\r
+    {\r
+      if (tp.getEntry(pe).getInputCount() > 0)\r
+      {\r
+        if (tp.getEntry(pe).getInputCount() > 1)\r
+        {\r
+          Cache.log.warn("Ignoring additional input spec in provenance entry "\r
+                         + tp.getEntry(pe).toString());\r
+        }\r
+        // LATER: deal sensibly with multiple inputs\r
+        Input vInput = tp.getEntry(pe).getInput(0);\r
+        // is this the whole alignment or a specific set of sequences ?\r
+        if (vInput.getObjRefCount()==0)\r
+          continue;\r
+        if (vInput.getObjRefCount()==1 && vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.Alignment)\r
+        {\r
+          // recover an AlignmentView for the input data\r
+          javport = (AlignViewport) getvObj2jv( (uk.ac.vamsas.\r
+              client.Vobject) vInput\r
+              .getObjRef(0));\r
+          jal = javport.getAlignment();\r
+          view = javport.getAlignment().\r
+              getCompactAlignment();\r
+        } else \r
+          if (vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.AlignmentSequence) {\r
+            // recover an AlignmentView for the input data\r
+            javport = (AlignViewport) getvObj2jv(((Vobject)vInput.getObjRef(0)).getV_parent());\r
+            jal = javport.getAlignment();\r
+            jalview.datamodel.SequenceI[] seqs = new jalview.datamodel.SequenceI[vInput.getObjRefCount()];\r
+            for (int i=0,iSize=vInput.getObjRefCount(); i<iSize; i++)\r
+            {\r
+              SequenceI seq = (SequenceI) getvObj2jv((Vobject) vInput.getObjRef(i));\r
+              seqs[i] = seq;\r
+            }\r
+            view = new jalview.datamodel.Alignment(seqs).getCompactAlignment();\r
+              \r
+            \r
+        }\r
+        int from = 1, to = jal.getWidth();\r
+        int offset = 0; // deleteRange modifies its frame of reference\r
+        for (int r = 0, s = vInput.getSegCount(); r < s; r++)\r
+        {\r
+          Seg visSeg = vInput.getSeg(r);\r
+          int se[] = getSegRange(visSeg, true); // jalview doesn't do\r
+                                                // bidirection alignments yet.\r
+          if (to < se[1])\r
+          {\r
+            Cache.log.warn("Ignoring invalid segment in InputData spec.");\r
+              }\r
+            else\r
+            {\r
+              if (se[0] > from)\r
+              {\r
+                view.deleteRange(offset + from - 1, offset + se[0] - 2);\r
+                offset -= se[0] - from;\r
+              }\r
+              from = se[1] + 1;\r
+            }\r
+          }\r
+          if (from < to)\r
+          {\r
+            view.deleteRange(offset + from - 1, offset + to - 1); // final\r
+                                                                  // deletion -\r
+                                                                  // TODO: check\r
+                                                                  // off by\r
+            // one for to\r
+          }\r
+          return new Object[]{new AlignmentView(view), jal};\r
+        }\r
+    }\r
+    Cache.log.debug("Returning null for input data recovery from provenance.");\r
+    return null;\r
+  }\r
+  public NewickFile getNewickTree()\r
+  {\r
+    return ntree;\r
+  }\r
+  public String getTitle()\r
+  {\r
+    return title;\r
+  }\r
+  public AlignmentView getInputData()\r
+  {\r
+    return inputData;\r
+  }\r
+\r
 }\r