From 9602211f8efae2e67f836bbacb2cc07a5dde3625 Mon Sep 17 00:00:00 2001 From: jprocter Date: Sun, 17 Jun 2007 13:11:18 +0000 Subject: [PATCH] vamsas-client-1.2 schema (mappings and Treenodes) and begun refactoring object binding code --- src/jalview/io/VamsasAppDatastore.java | 437 ++++++++++++++++-------------- src/jalview/io/vamsas/DatastoreItem.java | 146 ++++++++++ src/jalview/io/vamsas/Tree.java | 239 ++++++++++++++++ 3 files changed, 614 insertions(+), 208 deletions(-) create mode 100644 src/jalview/io/vamsas/DatastoreItem.java create mode 100644 src/jalview/io/vamsas/Tree.java diff --git a/src/jalview/io/VamsasAppDatastore.java b/src/jalview/io/VamsasAppDatastore.java index d799a6c..427f5b5 100644 --- a/src/jalview/io/VamsasAppDatastore.java +++ b/src/jalview/io/VamsasAppDatastore.java @@ -30,7 +30,9 @@ import jalview.gui.AlignFrame; import jalview.gui.AlignViewport; import jalview.gui.Desktop; import jalview.gui.TreePanel; +import jalview.io.vamsas.DatastoreItem; +import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.IdentityHashMap; @@ -49,12 +51,11 @@ import uk.ac.vamsas.objects.core.*; public class VamsasAppDatastore { - Entry provEntry = null; + public static final String JALVIEW_ANNOTATION_ROW = "jalview:AnnotationRow"; - // AlignViewport av; + public static final String JALVIEW_GRAPH_TYPE = "jalview:graphType"; - org.exolab.castor.types.Date date = new org.exolab.castor.types.Date( - new java.util.Date()); + Entry provEntry = null; IClientDocument cdoc; @@ -70,23 +71,6 @@ public class VamsasAppDatastore this.jv2vobj = jv2vobj; this.provEntry = provEntry; } - - /* - * public void storeJalview(String file, AlignFrame af) { try { // 1. Load the - * mapping information from the file Mapping map = new - * Mapping(getClass().getClassLoader()); java.net.URL url = - * getClass().getResource("/jalview_mapping.xml"); map.loadMapping(url); // 2. - * Unmarshal the data // Unmarshaller unmar = new Unmarshaller(); - * //unmar.setIgnoreExtraElements(true); //unmar.setMapping(map); // uni = - * (UniprotFile) unmar.unmarshal(new FileReader(file)); // 3. marshal the data - * with the total price back and print the XML in the console Marshaller - * marshaller = new Marshaller( new FileWriter(file) ); - * - * marshaller.setMapping(map); marshaller.marshal(af); } catch (Exception e) { - * e.printStackTrace(); } } - * - * - */ /** * @return the Vobject bound to Jalview datamodel object */ @@ -441,116 +425,26 @@ public class VamsasAppDatastore } if (aa[i].sequenceRef != null) { - uk.ac.vamsas.objects.core.AlignmentSequence alsref = (uk.ac.vamsas. - objects.core.AlignmentSequence) getjv2vObj(aa[i].sequenceRef); - uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation an = (uk.ac. - vamsas.objects.core.AlignmentSequenceAnnotation) getjv2vObj(aa[ - i]); - int[] gapMap = null; - if (AlSeqMaps.containsKey(aa[i].sequenceRef)) - { - gapMap = (int[]) AlSeqMaps.get(aa[i].sequenceRef); - } - else + // Deal with sequence associated annotation + Vobject sref = getjv2vObj(aa[i].sequenceRef); + if (sref instanceof uk.ac.vamsas.objects.core.AlignmentSequence) { - gapMap = new int[aa[i].sequenceRef.getLength()]; - // map from alignment position to sequence position. - int[] sgapMap = aa[i].sequenceRef.gapMap(); - for (int a = 0; a < sgapMap.length; a++) - { - gapMap[sgapMap[a]] = a; - } - } - if (an == null) + saveAlignmentSequenceAnnotation(AlSeqMaps, (AlignmentSequence) sref, aa[i]); + } else { - an = new uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation(); - Seg vSeg = new Seg(); - vSeg.setStart(1); - vSeg.setInclusive(true); - vSeg.setEnd(gapMap.length); - an.addSeg(vSeg); - an.setType("jalview:SecondaryStructurePrediction"); // TODO: better fix this rough guess ;) - alsref.addAlignmentSequenceAnnotation(an); - bindjvvobj(aa[i], an); - // LATER: much of this is verbatim from the alignmentAnnotation - // method below. suggests refactoring to make rangeAnnotation the - // base class - an.setDescription(aa[i].description); - if (aa[i].graph > 0) + // first find the alignment sequence to associate this with. + SequenceI jvalsq=null; + Enumeration jval = av.getAlignment().getSequences().elements(); + while (jval.hasMoreElements()) { - an.setGraph(true); // aa[i].graph); - } - else - { - an.setGraph(false); - } - an.setLabel(aa[i].label); - an.setProvenance(dummyProvenance()); // get provenance as user - // created, or jnet, or - // something else. - an.setGroup(Integer.toString(aa[i].graphGroup)); // // JBPNote - - // originally we - // were going to - // store - // graphGroup in - // the Jalview - // specific - // bits. - AnnotationElement ae; - for (int a = 0; a < aa[i].annotations.length; a++) - { - if (aa[i].annotations[a] == null) - { - continue; - } - - ae = new AnnotationElement(); - ae.setDescription(aa[i].annotations[a].description); - ae.addGlyph(new Glyph()); - ae.getGlyph(0) - .setContent(aa[i].annotations[a].displayCharacter); // assume - // jax-b - // takes - // care - // of - // utf8 - // translation - if (aa[i].graph != - jalview.datamodel.AlignmentAnnotation.NO_GRAPH) + jvalsq = (SequenceI) jval.nextElement(); + //saveDatasetSequenceAnnotation(AlSeqMaps,(uk.ac.vamsas.objects.core.Sequence) sref, aa[i]); + if (jvalsq.getDatasetSequence() == aa[i].sequenceRef) { - ae.addValue(aa[i].annotations[a].value); - } - ae.setPosition(gapMap[a] + 1); // position w.r.t. AlignmentSequence - // symbols - if (aa[i].annotations[a].secondaryStructure != ' ') - { - // we only write an annotation where it really exists. - Glyph ss = new Glyph(); - ss - .setDict(uk.ac.vamsas.objects.utils.GlyphDictionary. - PROTEIN_SS_3STATE); - ss.setContent(String - .valueOf(aa[i].annotations[a]. - secondaryStructure)); - ae.addGlyph(ss); - } - an.addAnnotationElement(ae); - } - } - else - { - // update reference sequence Annotation - if (an.getModifiable()==null) // TODO: USE VAMSAS LIBRARY OBJECT LOCK METHODS) - { - // verify existing alignment sequence annotation is up to date - System.out.println("update alignment sequence annotation."); - } - else - { - // verify existing alignment sequence annotation is up to date - System.out - .println( - "make new alignment sequence annotation if modification has happened."); + Vobject alsref = getjv2vObj(jvalsq); + saveAlignmentSequenceAnnotation(AlSeqMaps, (AlignmentSequence) alsref, aa[i]); + break; + }; } } } @@ -562,10 +456,10 @@ public class VamsasAppDatastore if (an == null) { an = new uk.ac.vamsas.objects.core.AlignmentAnnotation(); - an.setType("jalview:AnnotationRow"); + an.setType(JALVIEW_ANNOTATION_ROW); an.setDescription(aa[i].description); alignment.addAlignmentAnnotation(an); - Seg vSeg = new Seg(); + Seg vSeg = new Seg(); // TODO: refactor to have a default rangeAnnotationType initer/updater that takes a set of int ranges. vSeg.setStart(1); vSeg.setInclusive(true); vSeg.setEnd(jal.getWidth()); @@ -576,7 +470,7 @@ public class VamsasAppDatastore } an.setLabel(aa[i].label); an.setProvenance(dummyProvenance()); - if (aa[i].graph != aa[i].NO_GRAPH) + if (aa[i].graph != AlignmentAnnotation.NO_GRAPH) { an.setGroup(Integer.toString(aa[i].graphGroup)); // // JBPNote - // originally we @@ -636,7 +530,7 @@ public class VamsasAppDatastore { an.setGraph(true); an.setGroup(Integer.toString(aa[i].graphGroup)); - an.addProperty(newProperty("jalview:graphType", null, + an.addProperty(newProperty(JALVIEW_GRAPH_TYPE, null, ( (aa[i].graph == jalview.datamodel.AlignmentAnnotation. BAR_GRAPH) ? "BAR_GRAPH" : @@ -685,34 +579,7 @@ public class VamsasAppDatastore if (tp.getAlignment() == jal) { - Tree tree = (Tree) getjv2vObj(tp); - if (tree == null) - { - tree = new Tree(); - bindjvvobj(tp, tree); - tree.setTitle(tp.getTitle()); - Newick newick = new Newick(); - // TODO: translate sequenceI to leaf mappings to vamsas - // references - see tree specification in schema. - newick.setContent(tp.getTree().toString()); - newick.setTitle(tp.getTitle()); - tree.addNewick(newick); - tree.setProvenance(makeTreeProvenance(jal, tp)); - alignment.addTree(tree); - } - else - { - if (tree.getModifiable()==null) // TODO: USE VAMSAS LIBRARY OBJECT LOCK METHODS) - { - // verify any changes. - System.out.println("Update tree in document."); - } - else - { - System.out - .println("Add modified tree as new tree in document."); - } - } + DatastoreItem vtree = new jalview.io.vamsas.Tree(this, tp, jal, alignment); } } } @@ -727,7 +594,191 @@ public class VamsasAppDatastore } } + private void initRangeAnnotationType(RangeAnnotation an, AlignmentAnnotation alan, int[] gapMap) + { + Seg vSeg = new Seg(); + vSeg.setStart(1); + vSeg.setInclusive(true); + vSeg.setEnd(gapMap.length); + an.addSeg(vSeg); + + // LATER: much of this is verbatim from the alignmentAnnotation + // method below. suggests refactoring to make rangeAnnotation the + // base class + an.setDescription(alan.description); + an.setLabel(alan.label); + an.setGroup(Integer.toString(alan.graphGroup)); + // // JBPNote - + // originally we + // were going to + // store + // graphGroup in + // the Jalview + // specific + // bits. + AnnotationElement ae; + for (int a = 0; a < alan.annotations.length; a++) + { + if (alan.annotations[a] == null) + { + continue; + } + + ae = new AnnotationElement(); + ae.setDescription(alan.annotations[a].description); + ae.addGlyph(new Glyph()); + ae.getGlyph(0) + .setContent(alan.annotations[a].displayCharacter); // assume + // jax-b + // takes + // care + // of + // utf8 + // translation + if (alan.graph != + jalview.datamodel.AlignmentAnnotation.NO_GRAPH) + { + ae.addValue(alan.annotations[a].value); + } + ae.setPosition(gapMap[a] + 1); // position w.r.t. AlignmentSequence + // symbols + if (alan.annotations[a].secondaryStructure != ' ') + { + // we only write an annotation where it really exists. + Glyph ss = new Glyph(); + ss + .setDict(uk.ac.vamsas.objects.utils.GlyphDictionary. + PROTEIN_SS_3STATE); + ss.setContent(String + .valueOf(alan.annotations[a]. + secondaryStructure)); + ae.addGlyph(ss); + } + an.addAnnotationElement(ae); + } + } + private void saveDatasetSequenceAnnotation(HashMap AlSeqMaps, uk.ac.vamsas.objects.core.Sequence sref, AlignmentAnnotation alan) + { + //{ + // uk.ac.vamsas. + // objects.core.AlignmentSequence alsref = (uk.ac.vamsas. + // objects.core.AlignmentSequence) sref; + uk.ac.vamsas.objects.core.DataSetAnnotations an = (uk.ac. + vamsas.objects.core.DataSetAnnotations) getjv2vObj(alan); + int[] gapMap = getGapMap(AlSeqMaps, alan); + if (an == null) + { + an = new uk.ac.vamsas.objects.core.DataSetAnnotations(); + initRangeAnnotationType(an, alan, gapMap); + an.setProvenance(dummyProvenance()); // get provenance as user + // created, or jnet, or + // something else. + an.setType("jalview:SecondaryStructurePrediction"); // TODO: better fix this rough guess ;) + // The properties below don't fit into the DataSet Sequence Annotation as it currently is defined. + if (alan.graph > 0) + { + an.addProperty(newProperty("jalview:displayAsGraph", "boolean", "true")); + } + an.setGroup(Integer.toString(alan.graphGroup)); // // JBPNote - + // originally we + // were going to + // store + // graphGroup in + // the Jalview + // specific + // bits. + ((DataSet) sref.getV_parent()).addDataSetAnnotations(an); + bindjvvobj(alan, an); + } + else + { + // update reference sequence Annotation + if (an.getModifiable()==null) // TODO: USE VAMSAS LIBRARY OBJECT LOCK METHODS) + { + // verify existing alignment sequence annotation is up to date + System.out.println("update dataset sequence annotation."); + } + else + { + // verify existing alignment sequence annotation is up to date + System.out + .println( + "make new alignment dataset sequence annotation if modification has happened."); + } + } + + } + private int[] getGapMap(HashMap AlSeqMaps, AlignmentAnnotation alan) + { + int[] gapMap; + if (AlSeqMaps.containsKey(alan.sequenceRef)) + { + gapMap = (int[]) AlSeqMaps.get(alan.sequenceRef); + } + else + { + gapMap = new int[alan.sequenceRef.getLength()]; + // map from alignment position to sequence position. + int[] sgapMap = alan.sequenceRef.gapMap(); + for (int a = 0; a < sgapMap.length; a++) + { + gapMap[sgapMap[a]] = a; + } + } + return gapMap; + } + + private void saveAlignmentSequenceAnnotation(HashMap AlSeqMaps, AlignmentSequence alsref, AlignmentAnnotation alan) + { + //{ + // uk.ac.vamsas. + // objects.core.AlignmentSequence alsref = (uk.ac.vamsas. + // objects.core.AlignmentSequence) sref; + uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation an = (uk.ac. + vamsas.objects.core.AlignmentSequenceAnnotation) getjv2vObj(alan); + int[] gapMap = getGapMap(AlSeqMaps, alan); + if (an == null) + { + an = new uk.ac.vamsas.objects.core.AlignmentSequenceAnnotation(); + initRangeAnnotationType(an, alan, gapMap); + /** + * I mean here that we don't actually have a semantic 'type' for the annotation (this might be - score, intrinsic property, measurement, something extracted from another program, etc) + */ + an.setType("jalview:SecondaryStructurePrediction"); // TODO: better fix this rough guess ;) + alsref.addAlignmentSequenceAnnotation(an); + bindjvvobj(alan, an); + // These properties are directly supported by the AlignmentSequenceAnnotation type. + if (alan.graph != AlignmentAnnotation.NO_GRAPH) + { + an.setGraph(true); + an.addProperty(newProperty(JALVIEW_GRAPH_TYPE, "integer", ""+alan.graph)); + } + else + { + an.setGraph(false); + } + an.setProvenance(dummyProvenance()); // get provenance as user + // created, or jnet, or + // something else. + } + else + { + // update reference sequence Annotation + if (an.getModifiable()==null) // TODO: USE VAMSAS LIBRARY OBJECT LOCK METHODS) + { + // verify existing alignment sequence annotation is up to date + System.out.println("update alignment sequence annotation."); + } + else + { + // verify existing alignment sequence annotation is up to date + System.out + .println( + "make new alignment sequence annotation if modification has happened."); + } + } + } private Property newProperty(String name, String type, String content) { Property vProperty = new Property(); @@ -791,53 +842,6 @@ public class VamsasAppDatastore } /** - * correctly creates provenance for trees calculated on an alignment by - * jalview. - * - * @param jal - * @param tp - * @return - */ - private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp) - { - Provenance prov = new Provenance(); - prov.addEntry(new Entry()); - prov.getEntry(0).setAction("imported " + tp.getTitle()); - prov.getEntry(0).setUser(provEntry.getUser()); - prov.getEntry(0).setApp(provEntry.getApp()); - prov.getEntry(0).setDate(provEntry.getDate()); - if (tp.getTree().hasOriginalSequenceData()) - { - Input vInput = new Input(); - // LATER: check to see if tree input data is contained in this alignment - - // or just correctly resolve the tree's seqData to the correct alignment in - // the document. - // vInput.setObjRef(getjv2vObj(jal)); - vInput.setObjRef(new Object[] { getjv2vObj(tp.getViewPort())}); - prov.getEntry(0).setAction("created " + tp.getTitle()); - prov.getEntry(0).addInput(vInput); - vInput.setName("jalview:seqdist"); - prov.getEntry(0).addParam(new Param()); - prov.getEntry(0).getParam(0).setName("treeType"); - prov.getEntry(0).getParam(0).setType("utf8"); - prov.getEntry(0).getParam(0).setContent("NJ"); - - int ranges[] = tp.getTree().seqData.getVisibleContigs(); - // VisibleContigs are with respect to alignment coordinates. Still need offsets - int start = tp.getTree().seqData.getAlignmentOrigin(); - for (int r = 0; r < ranges.length; r += 2) - { - Seg visSeg = new Seg(); - visSeg.setStart(1 + start + ranges[r]); - visSeg.setEnd(start + ranges[r + 1]); - visSeg.setInclusive(true); - vInput.addSeg(visSeg); - } - } - return prov; - } - - /** * * @param tp * @return Object[] { AlignmentView, AlignmentI - reference alignment for @@ -1559,7 +1563,6 @@ public class VamsasAppDatastore { Cache.log.debug( "Inserting empty annotation row elements for a whole-alignment annotation."); - } else { @@ -1659,7 +1662,7 @@ public class VamsasAppDatastore uk.ac.vamsas.objects.core.Property[] props = annotation.getProperty(); for (int p = 0; p < props.length; p++) { - if (props[p].getName().equalsIgnoreCase("jalview:graphType")) + if (props[p].getName().equalsIgnoreCase(JALVIEW_GRAPH_TYPE)) { try { @@ -1916,4 +1919,22 @@ public class VamsasAppDatastore p.addEntry(dummyPEntry(action)); } + public Entry getProvEntry() + { + return provEntry; + } + + public IClientDocument getClientDocument() + { + return cdoc; + } + + public IdentityHashMap getJvObjectBinding() + { + return jv2vobj; + } + public Hashtable getVamsasObjectBinding() { + return vobj2jv; + } + } diff --git a/src/jalview/io/vamsas/DatastoreItem.java b/src/jalview/io/vamsas/DatastoreItem.java new file mode 100644 index 0000000..b77cc8c --- /dev/null +++ b/src/jalview/io/vamsas/DatastoreItem.java @@ -0,0 +1,146 @@ +package jalview.io.vamsas; + +import jalview.bin.Cache; +import jalview.gui.TreePanel; +import jalview.io.VamsasAppDatastore; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.IdentityHashMap; +import java.util.Vector; + +import uk.ac.vamsas.client.IClientDocument; +import uk.ac.vamsas.client.Vobject; +import uk.ac.vamsas.client.VorbaId; +import uk.ac.vamsas.objects.core.Entry; + +/** + * Holds all the common machinery for binding objects to vamsas objects + * @author JimP + * + */ +public class DatastoreItem +{ + /** + * + */ + Entry provEntry = null; + + IClientDocument cdoc; + + Hashtable vobj2jv; + + IdentityHashMap jv2vobj; + /** + * @return the Vobject bound to Jalview datamodel object + */ + protected Vobject getjv2vObj(Object jvobj) + { + if (jv2vobj.containsKey(jvobj)) + { + return cdoc.getObject( (VorbaId) jv2vobj.get(jvobj)); + } + if (Cache.log.isDebugEnabled()) + { + Cache.log.debug("Returning null VorbaID binding for jalview object "+jvobj); + } + return null; + } + + /** + * + * @param vobj + * @return Jalview datamodel object bound to the vamsas document object + */ + protected Object getvObj2jv(uk.ac.vamsas.client.Vobject vobj) + { + VorbaId id = vobj.getVorbaId(); + if (id == null) + { + id = cdoc.registerObject(vobj); + Cache.log + .debug("Registering new object and returning null for getvObj2jv"); + return null; + } + if (vobj2jv.containsKey(vobj.getVorbaId())) + { + return vobj2jv.get(vobj.getVorbaId()); + } + return null; + } + + protected void bindjvvobj(Object jvobj, uk.ac.vamsas.client.Vobject vobj) + { + VorbaId id = vobj.getVorbaId(); + if (id == null) + { + id = cdoc.registerObject(vobj); + if (id == null || vobj.getVorbaId() == null || cdoc.getObject(id)!=vobj) + { + Cache.log.error("Failed to get id for " + + (vobj.isRegisterable() ? "registerable" : + "unregisterable") + " object " + vobj); + } + } + + if (vobj2jv.containsKey(vobj.getVorbaId()) && + ! ( (VorbaId) vobj2jv.get(vobj.getVorbaId())).equals(jvobj)) + { + Cache.log.debug("Warning? Overwriting existing vamsas id binding for " + + vobj.getVorbaId(), + new Exception("Overwriting vamsas id binding.")); + } + else if (jv2vobj.containsKey(jvobj) && + ! ( (VorbaId) jv2vobj.get(jvobj)).equals(vobj.getVorbaId())) + { + Cache.log.debug( + "Warning? Overwriting existing jalview object binding for " + jvobj, + new Exception("Overwriting jalview object binding.")); + } + /* Cache.log.error("Attempt to make conflicting object binding! "+vobj+" id " +vobj.getVorbaId()+" already bound to "+getvObj2jv(vobj)+" and "+jvobj+" already bound to "+getjv2vObj(jvobj),new Exception("Excessive call to bindjvvobj")); + }*/ + // we just update the hash's regardless! + Cache.log.debug("Binding "+vobj.getVorbaId()+" to "+jvobj); + vobj2jv.put(vobj.getVorbaId(), jvobj); + // JBPNote - better implementing a hybrid invertible hash. + jv2vobj.put(jvobj, vobj.getVorbaId()); + } + + public DatastoreItem() { + super(); + } + public DatastoreItem(VamsasAppDatastore datastore) + { + this(); + initDatastoreItem(datastore); + // TODO Auto-generated constructor stub + } + + public void initDatastoreItem(VamsasAppDatastore ds) + { + initDatastoreItem(ds.getProvEntry(), ds.getClientDocument(), ds.getVamsasObjectBinding(), ds.getJvObjectBinding()); + } + public void initDatastoreItem(Entry provEntry, IClientDocument cdoc, Hashtable vobj2jv, IdentityHashMap jv2vobj) + { + this.provEntry = provEntry; + this.cdoc = cdoc; + this.vobj2jv = vobj2jv; + this.jv2vobj = jv2vobj; + } + + protected boolean isModifiable(String modifiable) + { + return modifiable==null; // TODO: USE VAMSAS LIBRARY OBJECT LOCK METHODS) + } + + protected Vector getjv2vObjs(Vector alsq) + { + Vector vObjs = new Vector(); + Enumeration elm = alsq.elements(); + while (elm.hasMoreElements()) + { + vObjs.addElement(getjv2vObj(elm.nextElement())); + } + return vObjs; + } +} diff --git a/src/jalview/io/vamsas/Tree.java b/src/jalview/io/vamsas/Tree.java new file mode 100644 index 0000000..3946a98 --- /dev/null +++ b/src/jalview/io/vamsas/Tree.java @@ -0,0 +1,239 @@ +package jalview.io.vamsas; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import jalview.analysis.NJTree; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.SeqCigar; +import jalview.datamodel.SequenceI; +import jalview.gui.TreePanel; +import jalview.io.VamsasAppDatastore; +import uk.ac.vamsas.client.Vobject; +import uk.ac.vamsas.objects.core.Entry; +import uk.ac.vamsas.objects.core.Input; +import uk.ac.vamsas.objects.core.Newick; +import uk.ac.vamsas.objects.core.Param; +import uk.ac.vamsas.objects.core.Provenance; +import uk.ac.vamsas.objects.core.Seg; +import uk.ac.vamsas.objects.core.Treenode; +import uk.ac.vamsas.objects.core.Vref; + +public class Tree extends DatastoreItem +{ + AlignmentI jal; + TreePanel tp; + uk.ac.vamsas.objects.core.Tree tree; + uk.ac.vamsas.objects.core.Alignment alignment; // may be null => dataset or other kind of tree + public Tree(VamsasAppDatastore datastore, TreePanel tp2, AlignmentI jal2, uk.ac.vamsas.objects.core.Alignment alignment2) + { + super(datastore); + + jal = jal2; + tp = tp2; + alignment = alignment2; + + tree = (uk.ac.vamsas.objects.core.Tree) getjv2vObj(tp); + if (tree == null) + { + add(); + } + else + { + if (isModifiable(tree.getModifiable())) + { + // synchronize(); // update(); + // verify any changes. + System.out.println("Update tree in document."); + } + else + { + // handle conflict + System.out + .println("Add modified tree as new tree in document."); + } + } + } + /** + * correctly creates provenance for trees calculated on an alignment by + * jalview. + * + * @param jal + * @param tp + * @return + */ + private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp) + { + Provenance prov = new Provenance(); + prov.addEntry(new Entry()); + prov.getEntry(0).setAction("imported " + tp.getTitle()); + prov.getEntry(0).setUser(provEntry.getUser()); + prov.getEntry(0).setApp(provEntry.getApp()); + prov.getEntry(0).setDate(provEntry.getDate()); + if (tp.getTree().hasOriginalSequenceData()) + { + Input vInput = new Input(); + // LATER: check to see if tree input data is contained in this alignment - + // or just correctly resolve the tree's seqData to the correct alignment in + // the document. + Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal, tp.getTree().seqData.getSequences())); + Object[] alsqs = new Object[alsqrefs.size()]; + alsqrefs.copyInto(alsqs); + vInput.setObjRef(alsqs); + // now create main provenance data + prov.getEntry(0).setAction("created " + tp.getTitle()); + prov.getEntry(0).addInput(vInput); + // jalview's special input parameter for distance matrix calculations + vInput.setName("jalview:seqdist"); + prov.getEntry(0).addParam(new Param()); + prov.getEntry(0).getParam(0).setName("treeType"); + prov.getEntry(0).getParam(0).setType("utf8"); + prov.getEntry(0).getParam(0).setContent("NJ"); + int ranges[] = tp.getTree().seqData.getVisibleContigs(); + // VisibleContigs are with respect to alignment coordinates. Still need offsets + int start = tp.getTree().seqData.getAlignmentOrigin(); + for (int r = 0; r < ranges.length; r += 2) + { + Seg visSeg = new Seg(); + visSeg.setStart(1 + start + ranges[r]); + visSeg.setEnd(start + ranges[r + 1]); + visSeg.setInclusive(true); + vInput.addSeg(visSeg); + } + } + return prov; + } + /** + * look up SeqCigars in an existing alignment. + * @param jal + * @param sequences + * @return vector of alignment sequences in order of SeqCigar array (but missing unfound seqcigars) + */ + private Vector findAlignmentSequences(AlignmentI jal, SeqCigar[] sequences) + { + SeqCigar[] tseqs = new SeqCigar[sequences.length]; + System.arraycopy(sequences, 0, tseqs, 0, sequences.length); + Vector alsq = new Vector(); + Enumeration as = jal.getSequences().elements(); + while (as.hasMoreElements()) + { + SequenceI asq = (SequenceI) as.nextElement(); + for (int t = 0; t=asq.getStart() && tseqs[t].getEnd()<=asq.getEnd()) + { + tseqs[t] = null; + alsq.add(asq); + } + } + } + return alsq; + } + public Treenode[] makeTreeNodes(NJTree ntree) { + Vector leaves = new Vector(); + ntree.findLeaves(ntree.getTopNode(), leaves); + Vector tnv = new Vector(); + Enumeration l = leaves.elements(); + int i=0; + Hashtable nodespecs = new Hashtable(); + while (l.hasMoreElements()) + { + jalview.datamodel.BinaryNode tnode = (jalview.datamodel.BinaryNode) l.nextElement(); + if (tnode instanceof jalview.datamodel.SequenceNode) + { + if (!((jalview.datamodel.SequenceNode) tnode).isPlaceholder()) + { + Object assocseq = ((jalview.datamodel.SequenceNode) tnode).element(); + if (assocseq instanceof SequenceI) + { + Vobject vobj = this.getjv2vObj(assocseq); + if (vobj!=null) + { + Treenode node = new Treenode(); + node.setNodespec(makeNodeSpec(nodespecs, tnode)); + node.setName(tnode.getName()); + Vref vr = new Vref(); + vr.addRefs(vobj); + node.addVref(vr); + tnv.addElement(node); + } + else + { + System.err.println("WARNING: Unassociated treeNode "+tnode.element().toString()+" " + +((tnode.getName()!=null) ? " label "+tnode.getName() : "")); + } + } + } + } + } + if (tnv.size()>0) + { + Treenode[] tn = new Treenode[tnv.size()]; + tnv.copyInto(tn); + return tn; + } + return new Treenode[] {}; + } + private String makeNodeSpec(Hashtable nodespecs, jalview.datamodel.BinaryNode tnode) + { + String nname = new String(tnode.getName()); + Integer nindx = (Integer) nodespecs.get(nname); + if (nindx==null) + { + nindx = new Integer(1); + } + nname = nindx.toString()+" "+nname; + return nname; + } + /** + * call to match up Treenode specs to NJTree parsed from document object. + * @param nodespec + * @param leaves as returned from NJTree.findLeaves( .., ..) .. + * @return + */ + private jalview.datamodel.BinaryNode findNodeSpec(String nodespec, Vector leaves) + { + int occurence=-1; + String nspec = nodespec.substring(nodespec.indexOf(' ')+1); + String oval = nodespec.substring(0, nodespec.indexOf(' ')); + try { + occurence = new Integer(oval).intValue(); + } + catch (Exception e) + { + System.err.println("Invalid nodespec '"+nodespec+"'"); + return null; + } + jalview.datamodel.BinaryNode bn = null; + + int nocc = 0; + Enumeration en = leaves.elements(); + while (en.hasMoreElements() && nocc