X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fio%2Fvamsas%2FTree.java;h=a3781a7d09e8b2809ed8fdf7dd81fc40044a6ed8;hb=37de9310bec3501cbc6381e0c3dcb282fcaad812;hp=de8230c93bf8e39edfdb5de6e4f023fb27a062c7;hpb=38c8b5a114ce8f0c57aa73a022e6ce83b7cf97ff;p=jalview.git diff --git a/src/jalview/io/vamsas/Tree.java b/src/jalview/io/vamsas/Tree.java index de8230c..a3781a7 100644 --- a/src/jalview/io/vamsas/Tree.java +++ b/src/jalview/io/vamsas/Tree.java @@ -1,494 +1,657 @@ -package jalview.io.vamsas; - -import java.io.IOException; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import jalview.analysis.NJTree; -import jalview.analysis.SequenceIdMatcher; -import jalview.bin.Cache; -import jalview.datamodel.AlignmentI; -import jalview.datamodel.AlignmentView; -import jalview.datamodel.BinaryNode; -import jalview.datamodel.SeqCigar; -import jalview.datamodel.Sequence; -import jalview.datamodel.SequenceI; -import jalview.datamodel.SequenceNode; -import jalview.gui.AlignViewport; -import jalview.gui.TreePanel; -import jalview.io.NewickFile; -import jalview.io.VamsasAppDatastore; -import uk.ac.vamsas.client.Vobject; -import uk.ac.vamsas.objects.core.AlignmentSequence; -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 - private NewickFile ntree; - private String title; - private AlignmentView inputData = null; - public static void updateFrom(VamsasAppDatastore datastore, jalview.gui.AlignFrame alignFrame, uk.ac.vamsas.objects.core.Tree vtree) { - Tree toTree = new Tree(datastore, alignFrame, vtree); - - } - public Tree(VamsasAppDatastore datastore, jalview.gui.AlignFrame alignFrame, uk.ac.vamsas.objects.core.Tree vtree) - { - super(datastore); - tree = vtree; - TreePanel tp = (TreePanel) getvObj2jv(tree); - if (tp != null) { - if (tree.isUpdated()) - { - Cache.log.info( - "Update from vamsas document to alignment associated tree not implemented yet."); - } - } - else - { - // make a new tree - Object[] idata = this.recoverInputData(tree.getProvenance()); - try - { - if (idata != null && idata[0] != null) - { - inputData = (AlignmentView) idata[0]; - } - ntree = getNtree(); - title = tree.getNewick(0).getTitle(); - if (title==null || title.length()==0) - { - title = tree.getTitle(); // hack!!!! - } - } - catch (Exception e) - { - Cache.log.warn("Problems parsing treefile '" + - tree.getNewick(0).getContent() + "'", e); - } - } - } - private NewickFile getNtree() throws IOException - { - return new jalview.io.NewickFile(tree.getNewick(0).getContent()); - } - 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) - { - Cache.log.debug("Making Tree provenance for "+tp.getTitle()); - 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"); // TODO: settle on appropriate name. - 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"); // TODO: type of tree is a general parameter - 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); - } - } - Cache.log.debug("Finished Tree provenance for "+tp.getTitle()); - 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); - } - } - } - if (alsq.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 0) - { - if (tp.getEntry(pe).getInputCount() > 1) - { - Cache.log.warn("Ignoring additional input spec in provenance entry " - + tp.getEntry(pe).toString()); - } - // LATER: deal sensibly with multiple inputs - Input vInput = tp.getEntry(pe).getInput(0); - // is this the whole alignment or a specific set of sequences ? - if (vInput.getObjRefCount()==0) - continue; - if (vInput.getObjRefCount()==1 && vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.Alignment) - { - // recover an AlignmentView for the input data - javport = (AlignViewport) getvObj2jv( (uk.ac.vamsas. - client.Vobject) vInput - .getObjRef(0)); - jal = javport.getAlignment(); - view = javport.getAlignment(). - getCompactAlignment(); - } else - if (vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.AlignmentSequence) { - // recover an AlignmentView for the input data - javport = getViewport(((Vobject)vInput.getObjRef(0)).getV_parent()); - jal = javport.getAlignment(); - jalview.datamodel.SequenceI[] seqs = new jalview.datamodel.SequenceI[vInput.getObjRefCount()]; - for (int i=0,iSize=vInput.getObjRefCount(); i from) - { - view.deleteRange(offset + from - 1, offset + se[0] - 2); - offset -= se[0] - from; - } - from = se[1] + 1; - } - } - if (from < to) - { - view.deleteRange(offset + from - 1, offset + to - 1); // final - // deletion - - // TODO: check - // off by - // one for to - } - return new Object[]{new AlignmentView(view), jal}; - } - } - Cache.log.debug("Returning null for input data recovery from provenance."); - return null; - } - - private AlignViewport getViewport(Vobject v_parent) - { - if (v_parent instanceof uk.ac.vamsas.objects.core.Alignment) - { - return datastore.findViewport((uk.ac.vamsas.objects.core.Alignment) v_parent); - } - return null; - } - - public NewickFile getNewickTree() - { - return ntree; - } - public String getTitle() - { - return title; - } - public AlignmentView getInputData() - { - return inputData; - } - public boolean isValidTree() - { - try { - ntree.parse(); - if (ntree.getTree()!=null) - { - ntree = getNtree(); - } - return true; - } - catch (Exception e) - { - Cache.log.debug("Failed to parse newick tree string",e); - } - return false; - } -} +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ +package jalview.io.vamsas; + +import jalview.analysis.NJTree; +import jalview.bin.Cache; +import jalview.datamodel.AlignmentI; +import jalview.datamodel.AlignmentView; +import jalview.datamodel.BinaryNode; +import jalview.datamodel.SeqCigar; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceI; +import jalview.datamodel.SequenceNode; +import jalview.gui.TreePanel; +import jalview.io.NewickFile; +import jalview.io.VamsasAppDatastore; +import jalview.viewmodel.AlignmentViewport; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.List; +import java.util.Vector; + +import uk.ac.vamsas.client.Vobject; +import uk.ac.vamsas.objects.core.AlignmentSequence; +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 + private NewickFile ntree; + + private String title; + + private AlignmentView inputData = null; + + public static void updateFrom(VamsasAppDatastore datastore, + jalview.gui.AlignFrame alignFrame, + uk.ac.vamsas.objects.core.Tree vtree) + { + Tree toTree = new Tree(datastore, alignFrame, vtree); + } + + public Tree(VamsasAppDatastore datastore, + jalview.gui.AlignFrame alignFrame, + uk.ac.vamsas.objects.core.Tree vtree) + { + super(datastore, vtree, TreePanel.class); + doJvUpdate(); + } + + private NewickFile getNtree() throws IOException + { + return new jalview.io.NewickFile(tree.getNewick(0).getContent()); + } + + public Tree(VamsasAppDatastore datastore, TreePanel tp2, AlignmentI jal2, + uk.ac.vamsas.objects.core.Alignment alignment2) + { + super(datastore, tp2, uk.ac.vamsas.objects.core.Tree.class); + + jal = jal2; + tp = (TreePanel) jvobj; + alignment = alignment2; + + tree = (uk.ac.vamsas.objects.core.Tree) vobj; + doSync(); + } + + /* + * (non-Javadoc) + * + * @see jalview.io.vamsas.DatastoreItem#addFromDocument() + */ + @Override + public void addFromDocument() + { + tree = (uk.ac.vamsas.objects.core.Tree) vobj; // vtree; + TreePanel tp = (TreePanel) jvobj; // getvObj2jv(tree); + // make a new tree + Object[] idata = recoverInputData(tree.getProvenance()); + try + { + if (idata != null && idata[0] != null) + { + inputData = (AlignmentView) idata[0]; + } + ntree = getNtree(); + title = tree.getNewick(0).getTitle(); + if (title == null || title.length() == 0) + { + title = tree.getTitle(); // hack!!!! + } + } catch (Exception e) + { + Cache.log.warn("Problems parsing treefile '" + + tree.getNewick(0).getContent() + "'", e); + } + } + + /* + * (non-Javadoc) + * + * @see jalview.io.vamsas.DatastoreItem#conflict() + */ + @Override + public void conflict() + { + Cache.log + .info("Update (with conflict) from vamsas document to alignment associated tree not implemented yet."); + } + + /* + * (non-Javadoc) + * + * @see jalview.io.vamsas.DatastoreItem#update() + */ + @Override + public void updateToDoc() + { + if (isModifiable(tree.getModifiable())) + { + // synchronize(); // update(); + // verify any changes. + log.info("TODO: Update tree in document from jalview."); + } + else + { + // handle conflict + log.info("TODO: Add the locally modified tree in Jalview as a new tree in document, leaving locked tree unchanged."); + } + } + + /* + * (non-Javadoc) + * + * @see jalview.io.vamsas.DatastoreItem#updateFromDoc() + */ + @Override + public void updateFromDoc() + { + // should probably just open a new tree panel in the same place as the old + // one + // TODO: Tree.updateFromDoc + /* + * TreePanel tp = (TreePanel) jvobj; // getvObj2jv(tree); + * + * // make a new tree Object[] idata = + * recoverInputData(tree.getProvenance()); try { if (idata != null && + * idata[0] != null) { inputData = (AlignmentView) idata[0]; } ntree = + * getNtree(); title = tree.getNewick(0).getTitle(); if (title == null || + * title.length() == 0) { title = tree.getTitle(); // hack!!!! } } catch + * (Exception e) { Cache.log.warn("Problems parsing treefile '" + + * tree.getNewick(0).getContent() + "'", e); } + */ + log.debug("Update the local tree in jalview from the document."); + + if (isModifiable(tree.getModifiable())) + { + // synchronize(); // update(); + // verify any changes. + log.debug("Update tree in document from jalview."); + } + else + { + // handle conflict + log.debug("Add modified jalview 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) + { + Cache.log.debug("Making Tree provenance for " + tp.getTitle()); + 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"); // TODO: settle on appropriate name. + 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"); // TODO: type of tree is a + // general parameter + 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); + } + } + Cache.log.debug("Finished Tree provenance for " + tp.getTitle()); + 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(); + List jalsqs; + synchronized (jalsqs = jal.getSequences()) + { + for (SequenceI asq : jalsqs) + { + for (int t = 0; t < sequences.length; t++) + { + if (tseqs[t] != null + && (tseqs[t].getRefSeq() == asq || tseqs[t].getRefSeq() == asq + .getDatasetSequence())) + // && tseqs[t].getStart()>=asq.getStart() && + // tseqs[t].getEnd()<=asq.getEnd()) + { + tseqs[t] = null; + alsq.add(asq); + } + } + } + } + if (alsq.size() < sequences.length) + { + Cache.log + .warn("Not recovered all alignment sequences for given set of input sequence CIGARS"); + } + return alsq; + } + + /** + * + * Update jalview newick representation with TreeNode map + * + * @param tp + * the treepanel that this tree is bound to. + */ + public void UpdateSequenceTreeMap(TreePanel tp) + { + if (tp == null || tree == null) + { + return; + } + + if (tp.getTree() == null) + { + Cache.log.warn("Not updating SequenceTreeMap for " + + tree.getVorbaId()); + return; + } + Vector leaves = tp.getTree().findLeaves( + tp.getTree().getTopNode()); + Treenode[] tn = tree.getTreenode(); // todo: select nodes for this + // particular tree + int sz = tn.length; + int i = 0; + + while (i < sz) + { + Treenode node = tn[i++]; + BinaryNode mappednode = findNodeSpec(node.getNodespec(), leaves); + if (mappednode != null && mappednode instanceof SequenceNode) + { + SequenceNode leaf = (SequenceNode) mappednode; + // check if we can make the specified association + Object jvseq = null; + int vrf = 0, refv = 0; + while (jvseq == null && vrf < node.getVrefCount()) + { + if (refv < node.getVref(vrf).getRefsCount()) + { + Object noderef = node.getVref(vrf).getRefs(refv++); + if (noderef instanceof AlignmentSequence) + { + // we only make these kind of associations + jvseq = getvObj2jv((Vobject) noderef); + } + } + else + { + refv = 0; + vrf++; + } + } + if (jvseq instanceof SequenceI) + { + leaf.setElement(jvseq); + leaf.setPlaceholder(false); + } + else + { + leaf.setPlaceholder(true); + leaf.setElement(new Sequence(leaf.getName(), "THISISAPLACEHLDER")); + } + } + } + } + + // / TODO: refactor to vamsas :start + /** + * construct treenode mappings for mapped sequences + * + * @param ntree + * @param newick + * @return + */ + public Treenode[] makeTreeNodes(NJTree ntree, Newick newick) + { + Vector leaves = ntree.findLeaves(ntree.getTopNode()); + Vector tnv = new Vector(); + Enumeration l = leaves.elements(); + 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(); + if (newick.isRegisterable()) + { + this.cdoc.registerObject(newick); + node.addTreeId(newick); + } + 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 < occurence) + { + bn = (jalview.datamodel.BinaryNode) en.nextElement(); + if (bn instanceof jalview.datamodel.SequenceNode + && bn.getName().equals(nspec)) + { + --occurence; + } + else + { + bn = null; + } + } + return bn; + } + + // todo: end refactor to vamsas library + /** + * add jalview object to vamsas document + * + */ + @Override + public void addToDocument() + { + tree = new uk.ac.vamsas.objects.core.Tree(); + bindjvvobj(tp, tree); + tree.setTitle(tp.getTitle()); + Newick newick = new Newick(); + newick.setContent(tp.getTree().toString()); + newick.setTitle(tp.getTitle()); + tree.addNewick(newick); + tree.setProvenance(makeTreeProvenance(jal, tp)); + tree.setTreenode(makeTreeNodes(tp.getTree(), newick)); + + alignment.addTree(tree); + } + + /** + * note: this function assumes that all sequence and alignment objects + * referenced in input data has already been associated with jalview objects. + * + * @param tp + * @param alignFrame + * @return Object[] { AlignmentView, AlignmentI - reference alignment for + * input } + */ + public Object[] recoverInputData(Provenance tp) + { + AlignmentViewport javport = null; + jalview.datamodel.AlignmentI jal = null; + jalview.datamodel.CigarArray view = null; + for (int pe = 0; pe < tp.getEntryCount(); pe++) + { + if (tp.getEntry(pe).getInputCount() > 0) + { + if (tp.getEntry(pe).getInputCount() > 1) + { + Cache.log + .warn("Ignoring additional input spec in provenance entry " + + tp.getEntry(pe).toString()); + } + // LATER: deal sensibly with multiple inputs + Input vInput = tp.getEntry(pe).getInput(0); + // is this the whole alignment or a specific set of sequences ? + if (vInput.getObjRefCount() == 0) + { + if (tree.getV_parent() != null + && tree.getV_parent() instanceof uk.ac.vamsas.objects.core.Alignment) + { + javport = getViewport(tree.getV_parent()); + jal = javport.getAlignment(); + view = javport.getAlignment().getCompactAlignment(); + } + } + else + { + // Explicit reference - to alignment, sequences or what. + if (vInput.getObjRefCount() == 1 + && vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.Alignment) + { + // recover an AlignmentView for the input data + javport = getViewport((Vobject) vInput.getObjRef(0)); + jal = javport.getAlignment(); + view = javport.getAlignment().getCompactAlignment(); + } + else if (vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.AlignmentSequence) + { + // recover an AlignmentView for the input data + javport = getViewport(((Vobject) vInput.getObjRef(0)) + .getV_parent()); + jal = javport.getAlignment(); + jalview.datamodel.SequenceI[] seqs = new jalview.datamodel.SequenceI[vInput + .getObjRefCount()]; + for (int i = 0, iSize = vInput.getObjRefCount(); i < iSize; i++) + { + SequenceI seq = (SequenceI) getvObj2jv((Vobject) vInput + .getObjRef(i)); + seqs[i] = seq; + } + view = new jalview.datamodel.Alignment(seqs) + .getCompactAlignment(); + + } + } + int from = 1, to = jal.getWidth(); + int offset = 0; // deleteRange modifies its frame of reference + for (int r = 0, s = vInput.getSegCount(); r < s; r++) + { + Seg visSeg = vInput.getSeg(r); + int se[] = getSegRange(visSeg, true); // jalview doesn't do + // bidirection alignments yet. + if (to < se[1]) + { + Cache.log.warn("Ignoring invalid segment in InputData spec."); + } + else + { + if (se[0] > from) + { + view.deleteRange(offset + from - 1, offset + se[0] - 2); + offset -= se[0] - from; + } + from = se[1] + 1; + } + } + if (from < to) + { + view.deleteRange(offset + from - 1, offset + to - 1); // final + // deletion - + // TODO: check + // off by + // one for to + } + return new Object[] { new AlignmentView(view), jal }; + } + } + Cache.log + .debug("Returning null for input data recovery from provenance."); + return null; + } + + private AlignmentViewport getViewport(Vobject v_parent) + { + if (v_parent instanceof uk.ac.vamsas.objects.core.Alignment) + { + return datastore + .findViewport((uk.ac.vamsas.objects.core.Alignment) v_parent); + } + return null; + } + + public NewickFile getNewickTree() + { + return ntree; + } + + public String getTitle() + { + return title; + } + + public AlignmentView getInputData() + { + return inputData; + } + + public boolean isValidTree() + { + try + { + if (ntree == null) + { + return false; + } + ntree.parse(); + if (ntree.getTree() != null) + { + ntree = getNtree(); + } + return true; + } catch (Exception e) + { + Cache.log.debug("Failed to parse newick tree string", e); + } + return false; + } +}