1 package jalview.io.vamsas;
3 import java.io.IOException;
4 import java.util.Enumeration;
5 import java.util.Hashtable;
6 import java.util.Vector;
8 import jalview.analysis.NJTree;
9 import jalview.analysis.SequenceIdMatcher;
10 import jalview.bin.Cache;
11 import jalview.datamodel.AlignmentI;
12 import jalview.datamodel.AlignmentView;
13 import jalview.datamodel.BinaryNode;
14 import jalview.datamodel.SeqCigar;
15 import jalview.datamodel.Sequence;
16 import jalview.datamodel.SequenceI;
17 import jalview.datamodel.SequenceNode;
18 import jalview.gui.AlignFrame;
19 import jalview.gui.AlignViewport;
20 import jalview.gui.TreePanel;
21 import jalview.io.NewickFile;
22 import jalview.io.VamsasAppDatastore;
23 import uk.ac.vamsas.client.Vobject;
24 import uk.ac.vamsas.objects.core.AlignmentSequence;
25 import uk.ac.vamsas.objects.core.Entry;
26 import uk.ac.vamsas.objects.core.Input;
27 import uk.ac.vamsas.objects.core.Newick;
28 import uk.ac.vamsas.objects.core.Param;
29 import uk.ac.vamsas.objects.core.Provenance;
30 import uk.ac.vamsas.objects.core.Seg;
31 import uk.ac.vamsas.objects.core.Treenode;
32 import uk.ac.vamsas.objects.core.Vref;
34 public class Tree extends DatastoreItem
40 uk.ac.vamsas.objects.core.Tree tree;
42 uk.ac.vamsas.objects.core.Alignment alignment; // may be null => dataset or
45 private NewickFile ntree;
49 private AlignmentView inputData = null;
51 public static void updateFrom(VamsasAppDatastore datastore,
52 jalview.gui.AlignFrame alignFrame,
53 uk.ac.vamsas.objects.core.Tree vtree)
55 Tree toTree = new Tree(datastore, alignFrame, vtree);
59 public Tree(VamsasAppDatastore datastore,
60 jalview.gui.AlignFrame alignFrame,
61 uk.ac.vamsas.objects.core.Tree vtree)
65 TreePanel tp = (TreePanel) getvObj2jv(tree);
71 .info("Update from vamsas document to alignment associated tree not implemented yet.");
77 Object[] idata = recoverInputData(tree.getProvenance());
80 if (idata != null && idata[0] != null)
82 inputData = (AlignmentView) idata[0];
85 title = tree.getNewick(0).getTitle();
86 if (title == null || title.length() == 0)
88 title = tree.getTitle(); // hack!!!!
92 Cache.log.warn("Problems parsing treefile '"
93 + tree.getNewick(0).getContent() + "'", e);
98 private NewickFile getNtree() throws IOException
100 return new jalview.io.NewickFile(tree.getNewick(0).getContent());
103 public Tree(VamsasAppDatastore datastore, TreePanel tp2, AlignmentI jal2,
104 uk.ac.vamsas.objects.core.Alignment alignment2)
110 alignment = alignment2;
112 tree = (uk.ac.vamsas.objects.core.Tree) getjv2vObj(tp);
119 if (isModifiable(tree.getModifiable()))
121 // synchronize(); // update();
122 // verify any changes.
123 System.out.println("Update tree in document.");
128 System.out.println("Add modified tree as new tree in document.");
134 * correctly creates provenance for trees calculated on an alignment by
141 private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp)
143 Cache.log.debug("Making Tree provenance for " + tp.getTitle());
144 Provenance prov = new Provenance();
145 prov.addEntry(new Entry());
146 prov.getEntry(0).setAction("imported " + tp.getTitle());
147 prov.getEntry(0).setUser(provEntry.getUser());
148 prov.getEntry(0).setApp(provEntry.getApp());
149 prov.getEntry(0).setDate(provEntry.getDate());
150 if (tp.getTree().hasOriginalSequenceData())
152 Input vInput = new Input();
153 // LATER: check to see if tree input data is contained in this alignment -
154 // or just correctly resolve the tree's seqData to the correct alignment
157 Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal, tp
158 .getTree().seqData.getSequences()));
159 Object[] alsqs = new Object[alsqrefs.size()];
160 alsqrefs.copyInto(alsqs);
161 vInput.setObjRef(alsqs);
162 // now create main provenance data
163 prov.getEntry(0).setAction("created " + tp.getTitle());
164 prov.getEntry(0).addInput(vInput);
165 // jalview's special input parameter for distance matrix calculations
166 vInput.setName("jalview:seqdist"); // TODO: settle on appropriate name.
167 prov.getEntry(0).addParam(new Param());
168 prov.getEntry(0).getParam(0).setName("treeType");
169 prov.getEntry(0).getParam(0).setType("utf8");
170 prov.getEntry(0).getParam(0).setContent("NJ"); // TODO: type of tree is a
172 int ranges[] = tp.getTree().seqData.getVisibleContigs();
173 // VisibleContigs are with respect to alignment coordinates. Still need
175 int start = tp.getTree().seqData.getAlignmentOrigin();
176 for (int r = 0; r < ranges.length; r += 2)
178 Seg visSeg = new Seg();
179 visSeg.setStart(1 + start + ranges[r]);
180 visSeg.setEnd(start + ranges[r + 1]);
181 visSeg.setInclusive(true);
182 vInput.addSeg(visSeg);
185 Cache.log.debug("Finished Tree provenance for " + tp.getTitle());
190 * look up SeqCigars in an existing alignment.
194 * @return vector of alignment sequences in order of SeqCigar array (but
195 * missing unfound seqcigars)
197 private Vector findAlignmentSequences(AlignmentI jal, SeqCigar[] sequences)
199 SeqCigar[] tseqs = new SeqCigar[sequences.length];
200 System.arraycopy(sequences, 0, tseqs, 0, sequences.length);
201 Vector alsq = new Vector();
202 Enumeration as = jal.getSequences().elements();
203 while (as.hasMoreElements())
205 SequenceI asq = (SequenceI) as.nextElement();
206 for (int t = 0; t < sequences.length; t++)
209 && (tseqs[t].getRefSeq() == asq || tseqs[t].getRefSeq() == asq
210 .getDatasetSequence()))
211 // && tseqs[t].getStart()>=asq.getStart() &&
212 // tseqs[t].getEnd()<=asq.getEnd())
219 if (alsq.size() < sequences.length)
221 .warn("Not recovered all alignment sequences for given set of input sequence CIGARS");
227 * Update jalview newick representation with TreeNode map
229 * @param tp the treepanel that this tree is bound to.
231 public void UpdateSequenceTreeMap(TreePanel tp)
233 if (tp == null || tree == null)
235 Vector leaves = new Vector();
236 if (tp.getTree()==null)
238 Cache.log.warn("Not updating SequenceTreeMap for "+tree.getVorbaId());
241 tp.getTree().findLeaves(tp.getTree().getTopNode(), leaves);
242 Treenode[] tn = tree.getTreenode(); // todo: select nodes for this
249 Treenode node = tn[i++];
250 BinaryNode mappednode = findNodeSpec(node.getNodespec(), leaves);
251 if (mappednode != null && mappednode instanceof SequenceNode)
253 SequenceNode leaf = (SequenceNode) mappednode;
254 // check if we can make the specified association
256 int vrf = 0, refv = 0;
257 while (jvseq == null && vrf < node.getVrefCount())
259 if (refv < node.getVref(vrf).getRefsCount())
261 Object noderef = node.getVref(vrf).getRefs(refv++);
262 if (noderef instanceof AlignmentSequence)
264 // we only make these kind of associations
265 jvseq = getvObj2jv((Vobject) noderef);
274 if (jvseq instanceof SequenceI)
276 leaf.setElement(jvseq);
277 leaf.setPlaceholder(false);
281 leaf.setPlaceholder(true);
283 .setElement(new Sequence(leaf.getName(),
284 "THISISAPLACEHLDER"));
290 // / TODO: refactor to vamsas :start
292 * construct treenode mappings for mapped sequences
298 public Treenode[] makeTreeNodes(NJTree ntree, Newick newick)
300 Vector leaves = new Vector();
301 ntree.findLeaves(ntree.getTopNode(), leaves);
302 Vector tnv = new Vector();
303 Enumeration l = leaves.elements();
304 Hashtable nodespecs = new Hashtable();
305 while (l.hasMoreElements())
307 jalview.datamodel.BinaryNode tnode = (jalview.datamodel.BinaryNode) l
309 if (tnode instanceof jalview.datamodel.SequenceNode)
311 if (!((jalview.datamodel.SequenceNode) tnode).isPlaceholder())
313 Object assocseq = ((jalview.datamodel.SequenceNode) tnode)
315 if (assocseq instanceof SequenceI)
317 Vobject vobj = this.getjv2vObj(assocseq);
320 Treenode node = new Treenode();
321 if (newick.isRegisterable())
323 this.cdoc.registerObject(newick);
324 node.addTreeId(newick);
326 node.setNodespec(makeNodeSpec(nodespecs, tnode));
327 node.setName(tnode.getName());
328 Vref vr = new Vref();
331 tnv.addElement(node);
335 System.err.println("WARNING: Unassociated treeNode "
336 + tnode.element().toString()
338 + ((tnode.getName() != null) ? " label "
339 + tnode.getName() : ""));
347 Treenode[] tn = new Treenode[tnv.size()];
351 return new Treenode[]
355 private String makeNodeSpec(Hashtable nodespecs,
356 jalview.datamodel.BinaryNode tnode)
358 String nname = new String(tnode.getName());
359 Integer nindx = (Integer) nodespecs.get(nname);
362 nindx = new Integer(1);
364 nname = nindx.toString() + " " + nname;
369 * call to match up Treenode specs to NJTree parsed from document object.
373 * as returned from NJTree.findLeaves( .., ..) ..
376 private jalview.datamodel.BinaryNode findNodeSpec(String nodespec,
380 String nspec = nodespec.substring(nodespec.indexOf(' ') + 1);
381 String oval = nodespec.substring(0, nodespec.indexOf(' '));
384 occurence = new Integer(oval).intValue();
385 } catch (Exception e)
387 System.err.println("Invalid nodespec '" + nodespec + "'");
390 jalview.datamodel.BinaryNode bn = null;
393 Enumeration en = leaves.elements();
394 while (en.hasMoreElements() && nocc < occurence)
396 bn = (jalview.datamodel.BinaryNode) en.nextElement();
397 if (bn instanceof jalview.datamodel.SequenceNode
398 && bn.getName().equals(nspec))
408 // todo: end refactor to vamsas library
410 * add jalview object to vamsas document
415 tree = new uk.ac.vamsas.objects.core.Tree();
416 bindjvvobj(tp, tree);
417 tree.setTitle(tp.getTitle());
418 Newick newick = new Newick();
419 newick.setContent(tp.getTree().toString());
420 newick.setTitle(tp.getTitle());
421 tree.addNewick(newick);
422 tree.setProvenance(makeTreeProvenance(jal, tp));
423 tree.setTreenode(makeTreeNodes(tp.getTree(), newick));
425 alignment.addTree(tree);
429 * note: this function assumes that all sequence and alignment objects
430 * referenced in input data has already been associated with jalview objects.
434 * @return Object[] { AlignmentView, AlignmentI - reference alignment for
437 public Object[] recoverInputData(Provenance tp)
439 AlignViewport javport = null;
440 jalview.datamodel.AlignmentI jal = null;
441 jalview.datamodel.CigarArray view = null;
442 for (int pe = 0; pe < tp.getEntryCount(); pe++)
444 if (tp.getEntry(pe).getInputCount() > 0)
446 if (tp.getEntry(pe).getInputCount() > 1)
449 .warn("Ignoring additional input spec in provenance entry "
450 + tp.getEntry(pe).toString());
452 // LATER: deal sensibly with multiple inputs
453 Input vInput = tp.getEntry(pe).getInput(0);
454 // is this the whole alignment or a specific set of sequences ?
455 if (vInput.getObjRefCount() == 0)
457 if (tree.getV_parent()!=null && tree.getV_parent() instanceof uk.ac.vamsas.objects.core.Alignment)
459 javport = getViewport(tree.getV_parent());
460 jal = javport.getAlignment();
461 view = javport.getAlignment().getCompactAlignment();
466 // Explicit reference - to alignment, sequences or what.
467 if (vInput.getObjRefCount() == 1
468 && vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.Alignment)
470 // recover an AlignmentView for the input data
471 javport = getViewport((Vobject) vInput.getObjRef(0));
472 jal = javport.getAlignment();
473 view = javport.getAlignment().getCompactAlignment();
475 else if (vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.AlignmentSequence)
477 // recover an AlignmentView for the input data
478 javport = getViewport(((Vobject) vInput.getObjRef(0)).getV_parent());
479 jal = javport.getAlignment();
480 jalview.datamodel.SequenceI[] seqs = new jalview.datamodel.SequenceI[vInput
482 for (int i = 0, iSize = vInput.getObjRefCount(); i < iSize; i++)
484 SequenceI seq = (SequenceI) getvObj2jv((Vobject) vInput
488 view = new jalview.datamodel.Alignment(seqs)
489 .getCompactAlignment();
493 int from = 1, to = jal.getWidth();
494 int offset = 0; // deleteRange modifies its frame of reference
495 for (int r = 0, s = vInput.getSegCount(); r < s; r++)
497 Seg visSeg = vInput.getSeg(r);
498 int se[] = getSegRange(visSeg, true); // jalview doesn't do
499 // bidirection alignments yet.
502 Cache.log.warn("Ignoring invalid segment in InputData spec.");
508 view.deleteRange(offset + from - 1, offset + se[0] - 2);
509 offset -= se[0] - from;
516 view.deleteRange(offset + from - 1, offset + to - 1); // final
523 { new AlignmentView(view), jal };
527 .debug("Returning null for input data recovery from provenance.");
531 private AlignViewport getViewport(Vobject v_parent)
533 if (v_parent instanceof uk.ac.vamsas.objects.core.Alignment)
536 .findViewport((uk.ac.vamsas.objects.core.Alignment) v_parent);
541 public NewickFile getNewickTree()
546 public String getTitle()
551 public AlignmentView getInputData()
556 public boolean isValidTree()
565 if (ntree.getTree() != null)
570 } catch (Exception e)
572 Cache.log.debug("Failed to parse newick tree string", e);