1 package jalview.io.vamsas;
\r
3 import java.util.Enumeration;
\r
4 import java.util.Hashtable;
\r
5 import java.util.Vector;
\r
7 import jalview.analysis.NJTree;
\r
8 import jalview.bin.Cache;
\r
9 import jalview.datamodel.AlignmentI;
\r
10 import jalview.datamodel.AlignmentView;
\r
11 import jalview.datamodel.SeqCigar;
\r
12 import jalview.datamodel.SequenceI;
\r
13 import jalview.gui.AlignViewport;
\r
14 import jalview.gui.TreePanel;
\r
15 import jalview.io.NewickFile;
\r
16 import jalview.io.VamsasAppDatastore;
\r
17 import uk.ac.vamsas.client.Vobject;
\r
18 import uk.ac.vamsas.objects.core.Entry;
\r
19 import uk.ac.vamsas.objects.core.Input;
\r
20 import uk.ac.vamsas.objects.core.Newick;
\r
21 import uk.ac.vamsas.objects.core.Param;
\r
22 import uk.ac.vamsas.objects.core.Provenance;
\r
23 import uk.ac.vamsas.objects.core.Seg;
\r
24 import uk.ac.vamsas.objects.core.Treenode;
\r
25 import uk.ac.vamsas.objects.core.Vref;
\r
27 public class Tree extends DatastoreItem
\r
31 uk.ac.vamsas.objects.core.Tree tree;
\r
32 uk.ac.vamsas.objects.core.Alignment alignment; // may be null => dataset or
\r
33 // other kind of tree
\r
34 private NewickFile ntree;
\r
35 private String title;
\r
36 private AlignmentView inputData = null;
\r
37 public static void updateFrom(VamsasAppDatastore datastore, jalview.gui.AlignFrame alignFrame, uk.ac.vamsas.objects.core.Tree vtree) {
\r
38 Tree toTree = new Tree(datastore, alignFrame, vtree);
\r
41 public Tree(VamsasAppDatastore datastore, jalview.gui.AlignFrame alignFrame, uk.ac.vamsas.objects.core.Tree vtree)
\r
45 TreePanel tp = (TreePanel) getvObj2jv(tree);
\r
47 if (tree.isUpdated())
\r
50 "Update from vamsas document to alignment associated tree not implemented yet.");
\r
56 Object[] idata = this.recoverInputData(tree.getProvenance());
\r
59 if (idata != null && idata[0] != null)
\r
61 inputData = (AlignmentView) idata[0];
\r
63 ntree = new jalview.io.NewickFile(tree.getNewick(0).getContent());
\r
64 title = tree.getNewick(0).getTitle();
\r
65 if (title==null || title.length()==0)
\r
67 title = tree.getTitle(); // hack!!!!
\r
72 Cache.log.warn("Problems parsing treefile '" +
\r
73 tree.getNewick(0).getContent() + "'", e);
\r
77 public Tree(VamsasAppDatastore datastore, TreePanel tp2, AlignmentI jal2, uk.ac.vamsas.objects.core.Alignment alignment2)
\r
83 alignment = alignment2;
\r
85 tree = (uk.ac.vamsas.objects.core.Tree) getjv2vObj(tp);
\r
92 if (isModifiable(tree.getModifiable()))
\r
94 // synchronize(); // update();
\r
95 // verify any changes.
\r
96 System.out.println("Update tree in document.");
\r
102 .println("Add modified tree as new tree in document.");
\r
107 * correctly creates provenance for trees calculated on an alignment by
\r
114 private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp)
\r
116 Cache.log.debug("Making Tree provenance for "+tp.getTitle());
\r
117 Provenance prov = new Provenance();
\r
118 prov.addEntry(new Entry());
\r
119 prov.getEntry(0).setAction("imported " + tp.getTitle());
\r
120 prov.getEntry(0).setUser(provEntry.getUser());
\r
121 prov.getEntry(0).setApp(provEntry.getApp());
\r
122 prov.getEntry(0).setDate(provEntry.getDate());
\r
123 if (tp.getTree().hasOriginalSequenceData())
\r
125 Input vInput = new Input();
\r
126 // LATER: check to see if tree input data is contained in this alignment -
\r
127 // or just correctly resolve the tree's seqData to the correct alignment
\r
130 Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal, tp.getTree().seqData.getSequences()));
\r
131 Object[] alsqs = new Object[alsqrefs.size()];
\r
132 alsqrefs.copyInto(alsqs);
\r
133 vInput.setObjRef(alsqs);
\r
134 // now create main provenance data
\r
135 prov.getEntry(0).setAction("created " + tp.getTitle());
\r
136 prov.getEntry(0).addInput(vInput);
\r
137 // jalview's special input parameter for distance matrix calculations
\r
138 vInput.setName("jalview:seqdist");
\r
139 prov.getEntry(0).addParam(new Param());
\r
140 prov.getEntry(0).getParam(0).setName("treeType");
\r
141 prov.getEntry(0).getParam(0).setType("utf8");
\r
142 prov.getEntry(0).getParam(0).setContent("NJ");
\r
143 int ranges[] = tp.getTree().seqData.getVisibleContigs();
\r
144 // VisibleContigs are with respect to alignment coordinates. Still need
\r
146 int start = tp.getTree().seqData.getAlignmentOrigin();
\r
147 for (int r = 0; r < ranges.length; r += 2)
\r
149 Seg visSeg = new Seg();
\r
150 visSeg.setStart(1 + start + ranges[r]);
\r
151 visSeg.setEnd(start + ranges[r + 1]);
\r
152 visSeg.setInclusive(true);
\r
153 vInput.addSeg(visSeg);
\r
156 Cache.log.debug("Finished Tree provenance for "+tp.getTitle());
\r
160 * look up SeqCigars in an existing alignment.
\r
164 * @return vector of alignment sequences in order of SeqCigar array (but
\r
165 * missing unfound seqcigars)
\r
167 private Vector findAlignmentSequences(AlignmentI jal, SeqCigar[] sequences)
\r
169 SeqCigar[] tseqs = new SeqCigar[sequences.length];
\r
170 System.arraycopy(sequences, 0, tseqs, 0, sequences.length);
\r
171 Vector alsq = new Vector();
\r
172 Enumeration as = jal.getSequences().elements();
\r
173 while (as.hasMoreElements())
\r
175 SequenceI asq = (SequenceI) as.nextElement();
\r
176 for (int t = 0; t<sequences.length; t++)
\r
178 if (tseqs[t]!=null
\r
179 && (tseqs[t].getRefSeq()==asq || tseqs[t].getRefSeq() == asq.getDatasetSequence()))
\r
180 // && tseqs[t].getStart()>=asq.getStart() && tseqs[t].getEnd()<=asq.getEnd())
\r
187 if (alsq.size()<sequences.length)
\r
188 Cache.log.warn("Not recovered all alignment sequences for given set of input sequence CIGARS");
\r
192 * construct treenode mappings for mapped sequences
\r
197 public Treenode[] makeTreeNodes(NJTree ntree) {
\r
198 Vector leaves = new Vector();
\r
199 ntree.findLeaves(ntree.getTopNode(), leaves);
\r
200 Vector tnv = new Vector();
\r
201 Enumeration l = leaves.elements();
\r
203 Hashtable nodespecs = new Hashtable();
\r
204 while (l.hasMoreElements())
\r
206 jalview.datamodel.BinaryNode tnode = (jalview.datamodel.BinaryNode) l.nextElement();
\r
207 if (tnode instanceof jalview.datamodel.SequenceNode)
\r
209 if (!((jalview.datamodel.SequenceNode) tnode).isPlaceholder())
\r
211 Object assocseq = ((jalview.datamodel.SequenceNode) tnode).element();
\r
212 if (assocseq instanceof SequenceI)
\r
214 Vobject vobj = this.getjv2vObj(assocseq);
\r
217 Treenode node = new Treenode();
\r
218 node.setNodespec(makeNodeSpec(nodespecs, tnode));
\r
219 node.setName(tnode.getName());
\r
220 Vref vr = new Vref();
\r
223 tnv.addElement(node);
\r
227 System.err.println("WARNING: Unassociated treeNode "+tnode.element().toString()+" "
\r
228 +((tnode.getName()!=null) ? " label "+tnode.getName() : ""));
\r
236 Treenode[] tn = new Treenode[tnv.size()];
\r
240 return new Treenode[] {};
\r
242 private String makeNodeSpec(Hashtable nodespecs, jalview.datamodel.BinaryNode tnode)
\r
244 String nname = new String(tnode.getName());
\r
245 Integer nindx = (Integer) nodespecs.get(nname);
\r
248 nindx = new Integer(1);
\r
250 nname = nindx.toString()+" "+nname;
\r
254 * call to match up Treenode specs to NJTree parsed from document object.
\r
258 * as returned from NJTree.findLeaves( .., ..) ..
\r
261 private jalview.datamodel.BinaryNode findNodeSpec(String nodespec, Vector leaves)
\r
264 String nspec = nodespec.substring(nodespec.indexOf(' ')+1);
\r
265 String oval = nodespec.substring(0, nodespec.indexOf(' '));
\r
267 occurence = new Integer(oval).intValue();
\r
269 catch (Exception e)
\r
271 System.err.println("Invalid nodespec '"+nodespec+"'");
\r
274 jalview.datamodel.BinaryNode bn = null;
\r
277 Enumeration en = leaves.elements();
\r
278 while (en.hasMoreElements() && nocc<occurence)
\r
280 bn = (jalview.datamodel.BinaryNode) en.nextElement();
\r
281 if (bn instanceof jalview.datamodel.SequenceNode && bn.getName().equals(nspec))
\r
290 * add jalview object to vamsas document
\r
293 public void add() {
\r
294 tree = new uk.ac.vamsas.objects.core.Tree();
\r
295 bindjvvobj(tp, tree);
\r
296 tree.setTitle(tp.getTitle());
\r
297 Newick newick = new Newick();
\r
298 newick.setContent(tp.getTree().toString());
\r
299 newick.setTitle(tp.getTitle());
\r
300 tree.addNewick(newick);
\r
301 tree.setProvenance(makeTreeProvenance(jal, tp));
\r
302 tree.setTreenode(makeTreeNodes(tp.getTree()));
\r
304 alignment.addTree(tree);
\r
308 * note: this function assumes that all sequence and alignment objects
\r
309 * referenced in input data has already been associated with jalview objects.
\r
312 * @return Object[] { AlignmentView, AlignmentI - reference alignment for
\r
315 public Object[] recoverInputData(Provenance tp)
\r
317 AlignViewport javport=null;
\r
318 jalview.datamodel.AlignmentI jal=null;
\r
319 jalview.datamodel.CigarArray view=null;
\r
320 for (int pe = 0; pe < tp.getEntryCount(); pe++)
\r
322 if (tp.getEntry(pe).getInputCount() > 0)
\r
324 if (tp.getEntry(pe).getInputCount() > 1)
\r
326 Cache.log.warn("Ignoring additional input spec in provenance entry "
\r
327 + tp.getEntry(pe).toString());
\r
329 // LATER: deal sensibly with multiple inputs
\r
330 Input vInput = tp.getEntry(pe).getInput(0);
\r
331 // is this the whole alignment or a specific set of sequences ?
\r
332 if (vInput.getObjRefCount()==0)
\r
334 if (vInput.getObjRefCount()==1 && vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.Alignment)
\r
336 // recover an AlignmentView for the input data
\r
337 javport = (AlignViewport) getvObj2jv( (uk.ac.vamsas.
\r
338 client.Vobject) vInput
\r
340 jal = javport.getAlignment();
\r
341 view = javport.getAlignment().
\r
342 getCompactAlignment();
\r
344 if (vInput.getObjRef(0) instanceof uk.ac.vamsas.objects.core.AlignmentSequence) {
\r
345 // recover an AlignmentView for the input data
\r
346 javport = (AlignViewport) getvObj2jv(((Vobject)vInput.getObjRef(0)).getV_parent());
\r
347 jal = javport.getAlignment();
\r
348 jalview.datamodel.SequenceI[] seqs = new jalview.datamodel.SequenceI[vInput.getObjRefCount()];
\r
349 for (int i=0,iSize=vInput.getObjRefCount(); i<iSize; i++)
\r
351 SequenceI seq = (SequenceI) getvObj2jv((Vobject) vInput.getObjRef(i));
\r
354 view = new jalview.datamodel.Alignment(seqs).getCompactAlignment();
\r
358 int from = 1, to = jal.getWidth();
\r
359 int offset = 0; // deleteRange modifies its frame of reference
\r
360 for (int r = 0, s = vInput.getSegCount(); r < s; r++)
\r
362 Seg visSeg = vInput.getSeg(r);
\r
363 int se[] = getSegRange(visSeg, true); // jalview doesn't do
\r
364 // bidirection alignments yet.
\r
367 Cache.log.warn("Ignoring invalid segment in InputData spec.");
\r
373 view.deleteRange(offset + from - 1, offset + se[0] - 2);
\r
374 offset -= se[0] - from;
\r
381 view.deleteRange(offset + from - 1, offset + to - 1); // final
\r
387 return new Object[]{new AlignmentView(view), jal};
\r
390 Cache.log.debug("Returning null for input data recovery from provenance.");
\r
393 public NewickFile getNewickTree()
\r
397 public String getTitle()
\r
401 public AlignmentView getInputData()
\r