refactored form of vamsas document interaction code
authorjprocter <Jim Procter>
Fri, 13 Jul 2007 14:57:26 +0000 (14:57 +0000)
committerjprocter <Jim Procter>
Fri, 13 Jul 2007 14:57:26 +0000 (14:57 +0000)
src/jalview/io/vamsas/DatastoreItem.java
src/jalview/io/vamsas/Dbref.java [new file with mode: 0644]
src/jalview/io/vamsas/Rangetype.java [new file with mode: 0644]
src/jalview/io/vamsas/Sequencemapping.java [new file with mode: 0644]
src/jalview/io/vamsas/Tree.java

index b77cc8c..c0464ff 100644 (file)
@@ -13,6 +13,8 @@ import uk.ac.vamsas.client.IClientDocument;
 import uk.ac.vamsas.client.Vobject;\r
 import uk.ac.vamsas.client.VorbaId;\r
 import uk.ac.vamsas.objects.core.Entry;\r
+import uk.ac.vamsas.objects.core.Provenance;\r
+import uk.ac.vamsas.objects.core.Seg;\r
 \r
 /**\r
  * Holds all the common machinery for binding objects to vamsas objects\r
@@ -54,6 +56,8 @@ public class DatastoreItem
    */\r
   protected Object getvObj2jv(uk.ac.vamsas.client.Vobject vobj)\r
   {\r
+    if (vobj2jv==null)\r
+      return null;\r
     VorbaId id = vobj.getVorbaId();\r
     if (id == null)\r
     {\r
@@ -143,4 +147,88 @@ public class DatastoreItem
     }\r
     return vObjs;\r
   }\r
+  // utility functions\r
+  /**\r
+   * get start<end range of segment, adjusting for inclusivity flag and\r
+   * polarity.\r
+   *\r
+   * @param visSeg\r
+   * @param ensureDirection when true - always ensure start is less than end.\r
+   * @return int[] { start, end, direction} where direction==1 for range running from end to start.\r
+   */\r
+  public int[] getSegRange(Seg visSeg, boolean ensureDirection)\r
+  {\r
+    boolean incl = visSeg.getInclusive();\r
+    // adjust for inclusive flag.\r
+    int pol = (visSeg.getStart() <= visSeg.getEnd()) ? 1 : -1; // polarity of\r
+    // region.\r
+    int start = visSeg.getStart() + (incl ? 0 : pol);\r
+    int end = visSeg.getEnd() + (incl ? 0 : -pol);\r
+    if (ensureDirection && pol == -1)\r
+    {\r
+      // jalview doesn't deal with inverted ranges, yet.\r
+      int t = end;\r
+      end = start;\r
+      start = t;\r
+    }\r
+    return new int[]\r
+        {\r
+        start, end, pol < 0 ? 1 : 0};\r
+  }\r
+  /**\r
+   * provenance bits\r
+   */\r
+  protected jalview.datamodel.Provenance getJalviewProvenance(Provenance prov)\r
+  {\r
+    // TODO: fix App and Action entries and check use of provenance in jalview.\r
+    jalview.datamodel.Provenance jprov = new jalview.datamodel.Provenance();\r
+    for (int i = 0; i < prov.getEntryCount(); i++)\r
+    {\r
+      jprov.addEntry(prov.getEntry(i).getUser(), prov.getEntry(i).getAction(),\r
+                     prov.getEntry(i).getDate(),\r
+                     prov.getEntry(i).getId());\r
+    }\r
+\r
+    return jprov;\r
+  }\r
+\r
+  /**\r
+   *\r
+   * @return default initial provenance list for a Jalview created vamsas\r
+   *         object.\r
+   */\r
+  Provenance dummyProvenance()\r
+  {\r
+    return dummyProvenance(null);\r
+  }\r
+\r
+  protected Entry dummyPEntry(String action)\r
+  {\r
+    Entry entry = new Entry();\r
+    entry.setApp(this.provEntry.getApp());\r
+    if (action != null)\r
+    {\r
+      entry.setAction(action);\r
+    }\r
+    else\r
+    {\r
+      entry.setAction("created.");\r
+    }\r
+    entry.setDate(new java.util.Date());\r
+    entry.setUser(this.provEntry.getUser());\r
+    return entry;\r
+  }\r
+\r
+  protected Provenance dummyProvenance(String action)\r
+  {\r
+    Provenance prov = new Provenance();\r
+    prov.addEntry(dummyPEntry(action));\r
+    return prov;\r
+  }\r
+\r
+  protected void addProvenance(Provenance p, String action)\r
+  {\r
+    p.addEntry(dummyPEntry(action));\r
+  }\r
+\r
 }\r
diff --git a/src/jalview/io/vamsas/Dbref.java b/src/jalview/io/vamsas/Dbref.java
new file mode 100644 (file)
index 0000000..c5ac44f
--- /dev/null
@@ -0,0 +1,115 @@
+package jalview.io.vamsas;\r
+\r
+import jalview.datamodel.DBRefEntry;\r
+import jalview.datamodel.SequenceI;\r
+import uk.ac.vamsas.objects.core.DbRef;\r
+import uk.ac.vamsas.objects.core.Map;\r
+import uk.ac.vamsas.objects.core.Sequence;\r
+import jalview.io.VamsasAppDatastore;\r
+\r
+public class Dbref extends Rangetype\r
+{\r
+  jalview.datamodel.SequenceI sq = null;\r
+  uk.ac.vamsas.objects.core.Sequence sequence = null;\r
+  DbRef dbref = null;\r
+  DBRefEntry dbentry=null;\r
+  public Dbref(VamsasAppDatastore datastore, DBRefEntry dbentry, jalview.datamodel.SequenceI sq2, uk.ac.vamsas.objects.core.Sequence sequence2)\r
+  {\r
+    super(datastore);\r
+    dbref = (DbRef) getjv2vObj(dbentry);\r
+    sq = sq2;\r
+    sequence = sequence2;\r
+    this.dbentry = dbentry;\r
+    if (dbref==null)\r
+    {\r
+      add();\r
+    } else {\r
+      if (dbref.isUpdated())\r
+      {\r
+        conflict();\r
+      } else {\r
+        update();\r
+      }\r
+        \r
+    }\r
+    \r
+  }\r
+\r
+  public Dbref(VamsasAppDatastore datastore, DbRef ref, Sequence vdseq, SequenceI dsseq)\r
+  {\r
+    super(datastore);\r
+    dbref = ref;\r
+    sequence = vdseq;\r
+    sq = dsseq;\r
+    dbentry = (jalview.datamodel.DBRefEntry) getvObj2jv(dbref);\r
+    if (dbentry == null)\r
+    {\r
+      addFromDocument();\r
+    } else {\r
+      if (dbref.isUpdated())\r
+      {\r
+        update();\r
+      }\r
+    }\r
+  }\r
+\r
+  private void update()\r
+  {\r
+    // TODO: verify and update dbrefs in vamsas document\r
+    // there will be trouble when a dataset sequence is modified to\r
+    // contain more residues than were originally referenced - we must\r
+    // then make a number of dataset sequence entries - this info is already stored \r
+    jalview.bin.Cache.log.debug("TODO verify update of dataset sequence database references.");\r
+  }\r
+\r
+  private void conflict()\r
+  {\r
+    jalview.bin.Cache.log.debug("Conflict in dbentry update for "+dbref.getAccessionId()+dbref.getSource()+" "+dbref.getVorbaId());\r
+    // TODO Auto-generated method stub\r
+    \r
+  }\r
+  private void addFromDocument()\r
+  {\r
+    // add new dbref\r
+    sq.addDBRef(dbentry = new jalview.datamodel.DBRefEntry\r
+            (\r
+                    dbref.getSource().toString(),\r
+                 dbref.getVersion().toString(),\r
+                 dbref.getAccessionId().toString()));\r
+    if (dbref.getMapCount()>0)\r
+    {\r
+      // TODO: Jalview ignores all the other maps\r
+      if (dbref.getMapCount()>1)\r
+      {\r
+        jalview.bin.Cache.log.debug("Ignoring additional mappings on DbRef: "+dbentry.getSource()+":"+dbentry.getAccessionId());\r
+      }\r
+      jalview.datamodel.Mapping mp = new jalview.datamodel.Mapping(parsemapType(dbref.getMap(0)));\r
+      dbentry.setMap(mp);\r
+    }\r
+    // TODO: jalview ignores links and properties because it doesn't know what to do with them.\r
+    \r
+    bindjvvobj(dbentry, dbref);\r
+  }\r
+  private void add()\r
+  {\r
+    DbRef dbref = new DbRef();\r
+    bindjvvobj(dbentry, dbref);\r
+    dbref.setAccessionId(dbentry.getAccessionId());\r
+    dbref.setSource(dbentry.getSource());\r
+    dbref.setVersion(dbentry.getVersion());\r
+    if (dbentry.getMap()!=null)\r
+    {\r
+      jalview.datamodel.Mapping mp = dbentry.getMap();\r
+      if (mp.getMap()!=null)\r
+      {\r
+        Map vMap = new Map();\r
+        initMapType(vMap, mp.getMap(), true);\r
+        dbref.addMap(vMap);\r
+      } else {\r
+        jalview.bin.Cache.log.debug("Ignoring mapless DbRef.Map "+dbentry.getSrcAccString());\r
+      }\r
+    }\r
+    sequence.addDbRef(dbref);\r
+  }\r
+\r
+}\r
diff --git a/src/jalview/io/vamsas/Rangetype.java b/src/jalview/io/vamsas/Rangetype.java
new file mode 100644 (file)
index 0000000..f6a6ecc
--- /dev/null
@@ -0,0 +1,270 @@
+package jalview.io.vamsas;\r
+\r
+\r
+import java.util.Vector;\r
+\r
+import uk.ac.vamsas.objects.core.Local;\r
+import uk.ac.vamsas.objects.core.Map;\r
+import uk.ac.vamsas.objects.core.MapType;\r
+import uk.ac.vamsas.objects.core.Mapped;\r
+import uk.ac.vamsas.objects.core.RangeType;\r
+import uk.ac.vamsas.objects.core.Seg;\r
+import jalview.datamodel.Mapping;\r
+import jalview.io.VamsasAppDatastore;\r
+\r
+public class Rangetype extends DatastoreItem\r
+{\r
+\r
+  public Rangetype()\r
+  {\r
+    super();\r
+  }\r
+\r
+  public Rangetype(VamsasAppDatastore datastore)\r
+  {\r
+    super(datastore);\r
+  }\r
+\r
+  /**\r
+   * get real bounds of a RangeType's specification. start and end are an\r
+   * inclusive range within which all segments and positions lie.\r
+   * TODO: refactor to vamsas utils\r
+   * @param dseta\r
+   * @return int[] { start, end}\r
+   */\r
+  protected int[] getBounds(RangeType dseta)\r
+  {\r
+    if (dseta != null)\r
+    {\r
+      int[] se = null;\r
+      if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)\r
+      {\r
+        throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+      }\r
+      if (dseta.getSegCount() > 0)\r
+      {\r
+        se = getSegRange(dseta.getSeg(0), true);\r
+        for (int s = 1, sSize = dseta.getSegCount(); s < sSize; s++)\r
+        {\r
+          int nse[] = getSegRange(dseta.getSeg(s), true);\r
+          if (se[0] > nse[0])\r
+          {\r
+            se[0] = nse[0];\r
+          }\r
+          if (se[1] < nse[1])\r
+          {\r
+            se[1] = nse[1];\r
+          }\r
+        }\r
+      }\r
+      if (dseta.getPosCount() > 0)\r
+      {\r
+        // could do a polarity for pos range too. and pass back indication of discontinuities.\r
+        int pos = dseta.getPos(0).getI();\r
+        se = new int[]\r
+            {\r
+            pos, pos};\r
+        for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
+        {\r
+          pos = dseta.getPos(p).getI();\r
+          if (se[0] > pos)\r
+          {\r
+            se[0] = pos;\r
+          }\r
+          if (se[1] < pos)\r
+          {\r
+            se[1] = pos;\r
+          }\r
+        }\r
+      }\r
+      return se;\r
+    }\r
+    return null;\r
+  }\r
+\r
+  /**\r
+   * map from a rangeType's internal frame to the referenced object's coordinate frame.\r
+   * @param dseta\r
+   * @return int [] { ref(pos)...} for all pos in rangeType's frame.\r
+   */\r
+  protected int[] getMapping(RangeType dseta)\r
+  {\r
+    Vector posList = new Vector();\r
+    if (dseta != null)\r
+    {\r
+      int[] se = null;\r
+      if (dseta.getSegCount() > 0 && dseta.getPosCount() > 0)\r
+      {\r
+        throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+      }\r
+      if (dseta.getSegCount() > 0)\r
+      {\r
+        for (int s = 0, sSize = dseta.getSegCount(); s < sSize; s++)\r
+        {\r
+          se = getSegRange(dseta.getSeg(s), false);\r
+          int se_end = se[1 - se[2]] + (se[2] == 0 ? 1 : -1);\r
+          for (int p = se[se[2]]; p != se_end; p += se[2] == 0 ? 1 : -1)\r
+          {\r
+            posList.add(new Integer(p));\r
+          }\r
+        }\r
+      }\r
+      else if (dseta.getPosCount() > 0)\r
+      {\r
+        int pos = dseta.getPos(0).getI();\r
+  \r
+        for (int p = 0, pSize = dseta.getPosCount(); p < pSize; p++)\r
+        {\r
+          pos = dseta.getPos(p).getI();\r
+          posList.add(new Integer(pos));\r
+        }\r
+      }\r
+    }\r
+    if (posList != null && posList.size() > 0)\r
+    {\r
+      int[] range = new int[posList.size()];\r
+      for (int i = 0; i < range.length; i++)\r
+      {\r
+        range[i] = ( (Integer) posList.elementAt(i)).intValue();\r
+      }\r
+      posList.clear();\r
+      return range;\r
+    }\r
+    return null;\r
+  }\r
+\r
+  protected int[] getIntervals(RangeType range)\r
+  {\r
+    int[] intervals=null;\r
+    Vector posList = new Vector();\r
+    if (range != null)\r
+    {\r
+      int[] se = null;\r
+      if (range.getSegCount() > 0 && range.getPosCount() > 0)\r
+      {\r
+        throw new Error("Invalid vamsas RangeType - cannot resolve both lists of Pos and Seg from choice!");\r
+      }\r
+      if (range.getSegCount() > 0)\r
+      {\r
+        for (int s = 0, sSize = range.getSegCount(); s < sSize; s++)\r
+        {\r
+          se = getSegRange(range.getSeg(s), false);\r
+          posList.addElement(new Integer(se[0]));\r
+          posList.addElement(new Integer(se[1]));\r
+        }\r
+      }\r
+      else if (range.getPosCount() > 0)\r
+      {\r
+        int pos = range.getPos(0).getI();\r
+  \r
+        for (int p = 0, pSize = range.getPosCount(); p < pSize; p++)\r
+        {\r
+          pos = range.getPos(p).getI();\r
+          posList.add(new Integer(pos));\r
+          posList.add(new Integer(pos));\r
+        }\r
+      }\r
+    }\r
+    if (posList != null && posList.size() > 0)\r
+    {\r
+      intervals=new int[posList.size()];\r
+      java.util.Enumeration e = posList.elements();\r
+      int i=0;\r
+      while (e.hasMoreElements())\r
+      {\r
+        intervals[i++] = ((Integer)e.nextElement()).intValue();\r
+      }\r
+    }\r
+    return intervals;\r
+  }\r
+  /**\r
+   * initialise a range type object from a set of start/end inclusive intervals\r
+   * @param mrt\r
+   * @param range\r
+   */\r
+  protected void initRangeType(RangeType mrt, int[] range)\r
+  {\r
+    for (int i=0; i<range.length; i+=2)\r
+    {\r
+      Seg vSeg = new Seg();\r
+      vSeg.setStart(range[i]);\r
+      vSeg.setEnd(range[i+1]);\r
+      vSeg.setInclusive(true);\r
+      mrt.addSeg(vSeg);\r
+    }\r
+  }\r
+\r
+  /**\r
+   * \r
+   * @param maprange where the from range is the local mapped range, and the to range is the 'mapped' range in the MapRangeType\r
+   * @param default unit for local\r
+   * @param default unit for mapped\r
+   * @return MapList\r
+   */\r
+  protected jalview.util.MapList parsemapType(MapType maprange, int localu, int mappedu)\r
+  {\r
+    jalview.util.MapList ml = null;\r
+    int[] localRange = getIntervals(maprange.getLocal());\r
+    int[] mappedRange = getIntervals(maprange.getMapped());\r
+    long lu = maprange.getLocal().hasUnit() ? maprange.getLocal().getUnit() : localu;\r
+    long mu = maprange.getMapped().hasUnit() ? maprange.getMapped().getUnit() : mappedu;\r
+    ml = new jalview.util.MapList(localRange, mappedRange, (int)lu, (int)mu);\r
+    return ml;\r
+  }\r
+  protected jalview.util.MapList parsemapType(MapType map)\r
+  {\r
+    if (!map.getLocal().hasUnit() || map.getMapped().hasUnit())\r
+    {\r
+      jalview.bin.Cache.log.warn("using default mapping length of 1:1 for map "\r
+              +(map.isRegistered() ? map.getVorbaId().toString() : ("<no Id registered> "+map.toString())));\r
+    }\r
+    return parsemapType(map, 1, 1); \r
+  }\r
+\r
+  /**\r
+   * initialise a MapType object from a MapList object.\r
+   * @param maprange\r
+   * @param ml\r
+   * @param setUnits\r
+   */\r
+  protected void initMapType(MapType maprange, jalview.util.MapList ml, boolean setUnits)\r
+  {\r
+    initMapType(maprange, ml, setUnits, false);\r
+  }\r
+  /**\r
+   * \r
+   * @param maprange\r
+   * @param ml\r
+   * @param setUnits\r
+   * @param reverse - reverse MapList mapping for Local and Mapped ranges and units \r
+   */\r
+  protected void initMapType(MapType maprange, jalview.util.MapList ml, boolean setUnits, boolean reverse)\r
+  {\r
+    if (ml==null)\r
+    {\r
+      throw new Error("Implementation error. MapList is null for initMapType.");\r
+    }\r
+    maprange.setLocal(new Local());\r
+    maprange.setMapped(new Mapped());\r
+    if (!reverse)\r
+      {\r
+      initRangeType(maprange.getLocal(), ml.getFromRanges());\r
+      initRangeType(maprange.getMapped(), ml.getToRanges());\r
+      } else {\r
+        initRangeType(maprange.getLocal(), ml.getToRanges());\r
+        initRangeType(maprange.getMapped(), ml.getFromRanges());\r
+      }\r
+    if (setUnits)\r
+    {\r
+      if (!reverse)\r
+      { \r
+        maprange.getLocal().setUnit(ml.getFromRatio());\r
+        maprange.getMapped().setUnit(ml.getToRatio());\r
+      } else {\r
+        maprange.getLocal().setUnit(ml.getToRatio());\r
+        maprange.getMapped().setUnit(ml.getFromRatio());\r
+      }\r
+    }\r
+  }\r
+\r
+}
\ No newline at end of file
diff --git a/src/jalview/io/vamsas/Sequencemapping.java b/src/jalview/io/vamsas/Sequencemapping.java
new file mode 100644 (file)
index 0000000..48b2982
--- /dev/null
@@ -0,0 +1,245 @@
+package jalview.io.vamsas;\r
+\r
+import java.util.Vector;\r
+\r
+import jalview.datamodel.AlignedCodonFrame;\r
+import jalview.datamodel.Mapping;\r
+import jalview.datamodel.SequenceI;\r
+import jalview.io.VamsasAppDatastore;\r
+import uk.ac.vamsas.client.Vobject;\r
+import uk.ac.vamsas.objects.core.AlignmentSequence;\r
+import uk.ac.vamsas.objects.core.DataSet;\r
+import uk.ac.vamsas.objects.core.Local;\r
+import uk.ac.vamsas.objects.core.RangeType;\r
+import uk.ac.vamsas.objects.core.Seg;\r
+import uk.ac.vamsas.objects.core.Sequence;\r
+import uk.ac.vamsas.objects.core.SequenceMapping;\r
+import uk.ac.vamsas.objects.core.SequenceType;\r
+\r
+public class Sequencemapping extends Rangetype\r
+{\r
+  public Sequencemapping(VamsasAppDatastore datastore, SequenceMapping sequenceMapping)\r
+  {\r
+    super(datastore);\r
+    Object mjvmapping = getvObj2jv(sequenceMapping);\r
+    if (mjvmapping==null)\r
+    {\r
+      add(sequenceMapping);\r
+    } else {\r
+      if (sequenceMapping.isUpdated())\r
+      {\r
+        update((jalview.datamodel.Mapping) mjvmapping, sequenceMapping);\r
+      }\r
+    }\r
+  }\r
+  /**\r
+   * create or update a vamsas sequence mapping corresponding to a jalview\r
+   * Mapping between two dataset sequences\r
+   * \r
+   * @param datastore\r
+   * @param mjvmapping\r
+   * @param from\r
+   * @param ds\r
+   */\r
+  public Sequencemapping(VamsasAppDatastore datastore, jalview.datamodel.Mapping mjvmapping, uk.ac.vamsas.objects.core.SequenceType from, uk.ac.vamsas.objects.core.DataSet ds)\r
+  {\r
+    super(datastore);\r
+    SequenceMapping sequenceMapping = (SequenceMapping) getjv2vObj(mjvmapping);\r
+    if (sequenceMapping==null)\r
+    {\r
+      add(mjvmapping, from, ds);\r
+    } else {\r
+      if (from!=null && sequenceMapping.getLoc()!=from)\r
+      {\r
+        jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: "+from+" doesn't match the local mapping sequence.");\r
+      }\r
+      if (ds!=null && sequenceMapping.getV_parent()!=ds)\r
+      {\r
+        jalview.bin.Cache.log.warn("Probable IMPLEMENTATION ERROR: "+ds+" doesn't match the parent of the bound sequence mapping object.");\r
+      }\r
+      if (sequenceMapping.isUpdated())\r
+      { \r
+        conflict(mjvmapping, sequenceMapping);\r
+      } else {\r
+        update(mjvmapping, sequenceMapping);\r
+      }\r
+    }\r
+  }\r
+  private void conflict(Mapping mjvmapping, SequenceMapping sequenceMapping)\r
+  {\r
+    // TODO Auto-generated method stub\r
+\r
+  }\r
+  private void add(Mapping mjvmapping, uk.ac.vamsas.objects.core.SequenceType from, DataSet ds)\r
+  {\r
+    SequenceI jvto = mjvmapping.getTo();\r
+    while (jvto.getDatasetSequence()!=null)\r
+    {\r
+      jvto = jvto.getDatasetSequence();\r
+    }\r
+    SequenceType to = (SequenceType) getjv2vObj(jvto);\r
+    if (to==null)\r
+    {\r
+      jalview.bin.Cache.log.warn("NONFATAL - do a second update: Ignoring Forward Reference to seuqence not yet bound to vamsas seuqence object");\r
+      return;\r
+    } \r
+    SequenceMapping sequenceMapping = new SequenceMapping();\r
+    sequenceMapping.setLoc(from);\r
+    sequenceMapping.setMap(to);\r
+    boolean dnaToProt=false,sense=false;\r
+    // ensure that we create a mapping with the correct sense\r
+    if (((Sequence) sequenceMapping.getLoc())\r
+            .getDictionary()\r
+            .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))\r
+    {\r
+      if (((Sequence) sequenceMapping.getMap())\r
+              .getDictionary()\r
+              .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA))\r
+      {\r
+        dnaToProt=true;\r
+        sense=true;\r
+      } \r
+    } else {\r
+      if (((Sequence) sequenceMapping.getMap())\r
+              .getDictionary()\r
+              .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))\r
+      {\r
+        dnaToProt=true;\r
+        sense=false;\r
+      } \r
+    }\r
+\r
+    if (!dnaToProt)\r
+    {\r
+      jalview.bin.Cache.log.warn("Ignoring Mapping - don't support protein to protein mapping in vamsas document yet.");\r
+      return;\r
+    }\r
+    if (ds==null)\r
+    {\r
+      // locate dataset for storage of SequenceMapping\r
+      if (sense)\r
+      {\r
+        ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping.getLoc()).getV_parent();\r
+      } else {\r
+        ds = (DataSet) ((uk.ac.vamsas.client.Vobject) sequenceMapping.getMap()).getV_parent();\r
+      } \r
+    }\r
+    if (sense)\r
+    {\r
+      this.initMapType(sequenceMapping, mjvmapping.getMap(), true);\r
+    } else {\r
+      this.initMapType(sequenceMapping, mjvmapping.getMap().getInverse(), true);\r
+    }\r
+    ds.addSequenceMapping(sequenceMapping);\r
+    sequenceMapping.setProvenance(this.dummyProvenance("user defined coding region translation")); // TODO:\r
+    // correctly\r
+    // construct\r
+    // provenance\r
+    // based\r
+    // on\r
+    // source\r
+    // of\r
+    // mapping\r
+    bindjvvobj(mjvmapping, sequenceMapping);\r
+\r
+    jalview.bin.Cache.log.debug("Successfully created mapping "+sequenceMapping.getVorbaId());\r
+  }\r
+  private void update(jalview.datamodel.Mapping mjvmapping, SequenceMapping sequenceMapping)\r
+  {\r
+    jalview.bin.Cache.log.error("Not implemented: Jalview Update Mapping"); \r
+  }\r
+  /**\r
+   * limitations: Currently, jalview only deals with mappings between dataset\r
+   * sequences, and even then, only between those that map from DNA to Protein.\r
+   * \r
+   * @param sequenceMapping\r
+   */\r
+  private void add(SequenceMapping sequenceMapping)\r
+  {\r
+    Object mobj;\r
+    SequenceI from=null,to=null;\r
+    boolean dnaToProt=false,sense=false;\r
+    Sequence sdloc=null, sdmap=null;\r
+    if (sequenceMapping.getLoc() instanceof AlignmentSequence)\r
+    {\r
+      sdloc = (Sequence) ((AlignmentSequence) sequenceMapping.getLoc()).getRefid();\r
+    } else {\r
+      sdloc = ((Sequence) sequenceMapping.getLoc());\r
+    }\r
+    if (sequenceMapping.getMap() instanceof AlignmentSequence)\r
+    {\r
+      sdmap = (Sequence) ((AlignmentSequence) sequenceMapping.getMap()).getRefid();\r
+    } else {\r
+      sdmap = ((Sequence) sequenceMapping.getMap());\r
+    }\r
+    if (sdloc==null || sdmap == null)\r
+    {\r
+      jalview.bin.Cache.log.info("Ignoring non sequence-sequence mapping");\r
+      return;\r
+    }\r
+    mobj = this.getvObj2jv((Vobject) sdloc);\r
+    if (mobj instanceof SequenceI)\r
+    {\r
+      from = (SequenceI) mobj;\r
+    }\r
+    mobj = this.getvObj2jv((Vobject) sdmap);\r
+    if (mobj instanceof SequenceI)\r
+    {\r
+      to = (SequenceI) mobj;\r
+    }\r
+    if (from == null || to == null)\r
+    {\r
+\r
+      jalview.bin.Cache.log.error("Probable Vamsas implementation error : unbound dataset sequences involved in a mapping are being parsed!");\r
+      return;\r
+    } \r
+    if (sdloc.getDictionary()\r
+            .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))\r
+    {\r
+      if (sdmap.getDictionary()\r
+              .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_AA))\r
+      {\r
+        dnaToProt=true;\r
+        sense=true;\r
+      } \r
+      // else {\r
+\r
+      // }\r
+    } else {\r
+      if (sdmap.getDictionary()\r
+              .equals(uk.ac.vamsas.objects.utils.SymbolDictionary.STANDARD_NA))\r
+      {\r
+        dnaToProt=true;\r
+        sense=false;\r
+      } \r
+    }\r
+    // create mapping storage object and make each dataset alignment reference\r
+    // it.\r
+    jalview.datamodel.AlignmentI dsLoc = (jalview.datamodel.AlignmentI) getvObj2jv(sdloc.getV_parent());\r
+    jalview.datamodel.AlignmentI dsMap = (jalview.datamodel.AlignmentI) getvObj2jv(sdmap.getV_parent());\r
+    AlignedCodonFrame afc = new AlignedCodonFrame(0);\r
+\r
+    if (dsLoc!=null && dsLoc!=dsMap)\r
+    {\r
+      dsMap.addCodonFrame(afc);\r
+    }\r
+    if (dsMap!=null)\r
+    {\r
+      dsMap.addCodonFrame(afc);\r
+    }\r
+    // create and add the new mapping to (each) dataset's codonFrame\r
+\r
+    jalview.util.MapList mapping = null; \r
+    if (!sense)\r
+    {\r
+      mapping = this.parsemapType(sequenceMapping, 1, 3); // invert sense\r
+      mapping = new jalview.util.MapList(mapping.getToRanges(), mapping.getFromRanges(), mapping.getToRatio(), mapping.getFromRatio());\r
+      afc.addMap(to, from, mapping);\r
+    } else {\r
+      mapping = this.parsemapType(sequenceMapping, 3, 1); // correct sense\r
+      afc.addMap(from, to, mapping);\r
+    }\r
+    bindjvvobj(mapping, sequenceMapping);\r
+    jalview.structure.StructureSelectionManager.getStructureSelectionManager().addMappings(new AlignedCodonFrame[] { afc });\r
+  }\r
+}
\ No newline at end of file
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