vamsas-client-1.2 schema (mappings and Treenodes) and begun refactoring object bindin...
[jalview.git] / src / jalview / io / vamsas / Tree.java
1 package jalview.io.vamsas;\r
2 \r
3 import java.util.Enumeration;\r
4 import java.util.Hashtable;\r
5 import java.util.Vector;\r
6 \r
7 import jalview.analysis.NJTree;\r
8 import jalview.datamodel.AlignmentI;\r
9 import jalview.datamodel.SeqCigar;\r
10 import jalview.datamodel.SequenceI;\r
11 import jalview.gui.TreePanel;\r
12 import jalview.io.VamsasAppDatastore;\r
13 import uk.ac.vamsas.client.Vobject;\r
14 import uk.ac.vamsas.objects.core.Entry;\r
15 import uk.ac.vamsas.objects.core.Input;\r
16 import uk.ac.vamsas.objects.core.Newick;\r
17 import uk.ac.vamsas.objects.core.Param;\r
18 import uk.ac.vamsas.objects.core.Provenance;\r
19 import uk.ac.vamsas.objects.core.Seg;\r
20 import uk.ac.vamsas.objects.core.Treenode;\r
21 import uk.ac.vamsas.objects.core.Vref;\r
22 \r
23 public class Tree extends DatastoreItem\r
24 {\r
25   AlignmentI jal;\r
26   TreePanel tp;\r
27   uk.ac.vamsas.objects.core.Tree tree;\r
28   uk.ac.vamsas.objects.core.Alignment alignment; // may be null => dataset or other kind of tree\r
29   public Tree(VamsasAppDatastore datastore, TreePanel tp2, AlignmentI jal2, uk.ac.vamsas.objects.core.Alignment alignment2)\r
30   {\r
31     super(datastore);\r
32 \r
33     jal = jal2;\r
34     tp = tp2;\r
35     alignment = alignment2;\r
36     \r
37     tree = (uk.ac.vamsas.objects.core.Tree) getjv2vObj(tp);\r
38     if (tree == null)\r
39     {\r
40       add();\r
41     }\r
42     else\r
43     {\r
44       if (isModifiable(tree.getModifiable()))\r
45       {\r
46         // synchronize(); // update();\r
47         // verify any changes.\r
48         System.out.println("Update tree in document.");\r
49       }\r
50       else\r
51       {\r
52         // handle conflict\r
53         System.out\r
54             .println("Add modified tree as new tree in document.");\r
55       }\r
56     }\r
57   }\r
58   /**\r
59    * correctly creates provenance for trees calculated on an alignment by\r
60    * jalview.\r
61    *\r
62    * @param jal\r
63    * @param tp\r
64    * @return\r
65    */\r
66   private Provenance makeTreeProvenance(AlignmentI jal, TreePanel tp)\r
67   {\r
68     Provenance prov = new Provenance();\r
69     prov.addEntry(new Entry());\r
70     prov.getEntry(0).setAction("imported " + tp.getTitle());\r
71     prov.getEntry(0).setUser(provEntry.getUser());\r
72     prov.getEntry(0).setApp(provEntry.getApp());\r
73     prov.getEntry(0).setDate(provEntry.getDate());\r
74     if (tp.getTree().hasOriginalSequenceData())\r
75     {\r
76       Input vInput = new Input();\r
77       // LATER: check to see if tree input data is contained in this alignment -\r
78       // or just correctly resolve the tree's seqData to the correct alignment in\r
79       // the document.\r
80       Vector alsqrefs = getjv2vObjs(findAlignmentSequences(jal, tp.getTree().seqData.getSequences()));\r
81       Object[] alsqs = new Object[alsqrefs.size()];\r
82       alsqrefs.copyInto(alsqs);\r
83       vInput.setObjRef(alsqs);\r
84       // now create main provenance data\r
85       prov.getEntry(0).setAction("created " + tp.getTitle());\r
86       prov.getEntry(0).addInput(vInput);\r
87       // jalview's special input parameter for distance matrix calculations\r
88       vInput.setName("jalview:seqdist");\r
89       prov.getEntry(0).addParam(new Param());\r
90       prov.getEntry(0).getParam(0).setName("treeType");\r
91       prov.getEntry(0).getParam(0).setType("utf8");\r
92       prov.getEntry(0).getParam(0).setContent("NJ");\r
93       int ranges[] = tp.getTree().seqData.getVisibleContigs();\r
94       // VisibleContigs are with respect to alignment coordinates. Still need offsets\r
95       int start = tp.getTree().seqData.getAlignmentOrigin();\r
96       for (int r = 0; r < ranges.length; r += 2)\r
97       {\r
98         Seg visSeg = new Seg();\r
99         visSeg.setStart(1 + start + ranges[r]);\r
100         visSeg.setEnd(start + ranges[r + 1]);\r
101         visSeg.setInclusive(true);\r
102         vInput.addSeg(visSeg);\r
103       }\r
104     }\r
105     return prov;\r
106   }\r
107   /**\r
108    * look up SeqCigars in an existing alignment.\r
109    * @param jal\r
110    * @param sequences\r
111    * @return vector of alignment sequences in order of SeqCigar array (but missing unfound seqcigars)\r
112    */\r
113   private Vector findAlignmentSequences(AlignmentI jal, SeqCigar[] sequences)\r
114   {\r
115     SeqCigar[] tseqs = new SeqCigar[sequences.length];\r
116     System.arraycopy(sequences, 0, tseqs, 0, sequences.length);\r
117     Vector alsq = new Vector();\r
118     Enumeration as = jal.getSequences().elements();\r
119     while (as.hasMoreElements())\r
120     {\r
121       SequenceI asq = (SequenceI) as.nextElement();\r
122       for (int t = 0; t<sequences.length; t++)\r
123       {\r
124         if (tseqs[t]!=null \r
125                 && (tseqs[t].getRefSeq()==asq || tseqs[t].getRefSeq() == asq.getDatasetSequence())\r
126                 && tseqs[t].getStart()>=asq.getStart() && tseqs[t].getEnd()<=asq.getEnd())\r
127         {\r
128           tseqs[t] = null;\r
129           alsq.add(asq);\r
130         }\r
131       }\r
132     }\r
133     return alsq;\r
134   }\r
135   public Treenode[] makeTreeNodes(NJTree ntree) {\r
136     Vector leaves = new Vector();\r
137     ntree.findLeaves(ntree.getTopNode(), leaves);\r
138     Vector tnv = new Vector();\r
139     Enumeration l = leaves.elements();\r
140     int i=0;\r
141     Hashtable nodespecs = new Hashtable();\r
142     while (l.hasMoreElements())\r
143     {\r
144       jalview.datamodel.BinaryNode tnode = (jalview.datamodel.BinaryNode) l.nextElement();\r
145       if (tnode instanceof jalview.datamodel.SequenceNode)\r
146       {\r
147         if (!((jalview.datamodel.SequenceNode) tnode).isPlaceholder())\r
148         {\r
149           Object assocseq = ((jalview.datamodel.SequenceNode) tnode).element();\r
150           if (assocseq instanceof SequenceI)\r
151           {\r
152             Vobject vobj = this.getjv2vObj(assocseq);\r
153             if (vobj!=null)\r
154             {\r
155               Treenode node = new Treenode();\r
156               node.setNodespec(makeNodeSpec(nodespecs, tnode));\r
157               node.setName(tnode.getName());\r
158               Vref vr = new Vref();\r
159               vr.addRefs(vobj);\r
160               node.addVref(vr);\r
161               tnv.addElement(node);\r
162             }\r
163             else\r
164             {\r
165               System.err.println("WARNING: Unassociated treeNode "+tnode.element().toString()+" "\r
166                       +((tnode.getName()!=null) ? " label "+tnode.getName() : ""));\r
167             }\r
168           }\r
169         }\r
170       }\r
171     }\r
172     if (tnv.size()>0)\r
173     {\r
174       Treenode[] tn = new Treenode[tnv.size()];\r
175       tnv.copyInto(tn);  \r
176       return tn;\r
177     }\r
178     return new Treenode[] {};\r
179   }\r
180   private String makeNodeSpec(Hashtable nodespecs, jalview.datamodel.BinaryNode tnode)\r
181   { \r
182     String nname = new String(tnode.getName());\r
183     Integer nindx = (Integer) nodespecs.get(nname);\r
184     if (nindx==null)\r
185     {\r
186       nindx = new Integer(1);\r
187     }\r
188     nname = nindx.toString()+" "+nname;\r
189     return nname;\r
190   }\r
191   /**\r
192    * call to match up Treenode specs to NJTree parsed from document object.\r
193    * @param nodespec\r
194    * @param leaves as returned from NJTree.findLeaves( .., ..) .. \r
195    * @return\r
196    */\r
197   private jalview.datamodel.BinaryNode findNodeSpec(String nodespec, Vector leaves)\r
198   {\r
199     int occurence=-1;\r
200     String nspec = nodespec.substring(nodespec.indexOf(' ')+1);\r
201     String oval = nodespec.substring(0, nodespec.indexOf(' '));\r
202     try {\r
203       occurence = new Integer(oval).intValue();\r
204     }\r
205     catch (Exception e)\r
206     {\r
207       System.err.println("Invalid nodespec '"+nodespec+"'");\r
208       return null;\r
209     }\r
210     jalview.datamodel.BinaryNode bn = null;\r
211     \r
212     int nocc = 0;\r
213     Enumeration en = leaves.elements();\r
214     while (en.hasMoreElements() && nocc<occurence)\r
215     {\r
216       bn = (jalview.datamodel.BinaryNode) en.nextElement();\r
217       if (bn instanceof jalview.datamodel.SequenceNode && bn.getName().equals(nspec))\r
218       {\r
219          --occurence;\r
220       } else \r
221         bn=null;\r
222     }\r
223     return bn;\r
224   }\r
225   \r
226   public void add() {\r
227     tree = new uk.ac.vamsas.objects.core.Tree();\r
228     bindjvvobj(tp, tree);\r
229     tree.setTitle(tp.getTitle());\r
230     Newick newick = new Newick();\r
231     newick.setContent(tp.getTree().toString());\r
232     newick.setTitle(tp.getTitle());\r
233     tree.addNewick(newick);\r
234     tree.setProvenance(makeTreeProvenance(jal, tp));\r
235     tree.setTreenode(makeTreeNodes(tp.getTree()));\r
236     \r
237     alignment.addTree(tree);\r
238   }\r
239 }\r