JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / bin / jalview / io / NewickFile.js
1 Clazz.declarePackage ("jalview.io");\r
2 Clazz.load (["jalview.io.FileParse", "jalview.jsdev.RegExp"], "jalview.io.NewickFile", ["jalview.datamodel.SequenceNode", "jalview.util.MessageManager", "java.io.BufferedReader", "$.IOException", "java.lang.Float", "$.StringBuffer", "java.util.StringTokenizer"], function () {\r
3 c$ = Clazz.decorateAsClass (function () {\r
4 this.root = null;\r
5 this.$HasBootstrap = false;\r
6 this.$HasDistances = false;\r
7 this.RootHasDistance = false;\r
8 this.ReplaceUnderscores = false;\r
9 this.printRootInfo = true;\r
10 this.NodeSafeName = null;\r
11 this.QuoteChar = '\'';\r
12 Clazz.instantialize (this, arguments);\r
13 }, jalview.io, "NewickFile", jalview.io.FileParse);\r
14 Clazz.prepareFields (c$, function () {\r
15 this.NodeSafeName =  Clazz.newArray (-1, [jalview.jsdev.RegExp.perlCode ("m/[\\[,:'()]/"), jalview.jsdev.RegExp.perlCode ("s/'/''/"), jalview.jsdev.RegExp.perlCode ("s/\\/w/_/")]);\r
16 });\r
17 Clazz.makeConstructor (c$, \r
18 function (inStr) {\r
19 Clazz.superConstructor (this, jalview.io.NewickFile, [inStr, "Paste"]);\r
20 }, "~S");\r
21 Clazz.makeConstructor (c$, \r
22 function (newtree) {\r
23 Clazz.superConstructor (this, jalview.io.NewickFile, []);\r
24 this.root = newtree;\r
25 }, "jalview.datamodel.SequenceNode");\r
26 Clazz.makeConstructor (c$, \r
27 function (newtree, bootstrap) {\r
28 Clazz.superConstructor (this, jalview.io.NewickFile, []);\r
29 this.$HasBootstrap = bootstrap;\r
30 this.root = newtree;\r
31 }, "jalview.datamodel.SequenceNode,~B");\r
32 Clazz.makeConstructor (c$, \r
33 function (newtree, bootstrap, distances) {\r
34 Clazz.superConstructor (this, jalview.io.NewickFile, []);\r
35 this.root = newtree;\r
36 this.$HasBootstrap = bootstrap;\r
37 this.$HasDistances = distances;\r
38 }, "jalview.datamodel.SequenceNode,~B,~B");\r
39 Clazz.makeConstructor (c$, \r
40 function (newtree, bootstrap, distances, rootdistance) {\r
41 Clazz.superConstructor (this, jalview.io.NewickFile, []);\r
42 this.root = newtree;\r
43 this.$HasBootstrap = bootstrap;\r
44 this.$HasDistances = distances;\r
45 this.RootHasDistance = rootdistance;\r
46 }, "jalview.datamodel.SequenceNode,~B,~B,~B");\r
47 Clazz.defineMethod (c$, "ErrorStringrange", \r
48 ($fz = function (Error, Er, r, p, s) {\r
49 return ((Error == null) ? "" : Error) + Er + " at position " + p + " ( " + s.substring (((p - r) < 0) ? 0 : (p - r), ((p + r) > s.length) ? s.length : (p + r)) + " )\n";\r
50 }, $fz.isPrivate = true, $fz), "~S,~S,~N,~N,~S");\r
51 Clazz.defineMethod (c$, "HasBootstrap", \r
52 function () {\r
53 return this.$HasBootstrap;\r
54 });\r
55 Clazz.defineMethod (c$, "HasDistances", \r
56 function () {\r
57 return this.$HasDistances;\r
58 });\r
59 Clazz.defineMethod (c$, "HasRootDistance", \r
60 function () {\r
61 return this.RootHasDistance;\r
62 });\r
63 Clazz.defineMethod (c$, "parse", \r
64 function () {\r
65 var nf;\r
66 {\r
67 var file =  new StringBuffer ();\r
68 while ((nf = this.nextLine ()) != null) {\r
69 file.append (nf);\r
70 }\r
71 nf = file.toString ();\r
72 }this.root =  new jalview.datamodel.SequenceNode ();\r
73 var realroot = null;\r
74 var c = this.root;\r
75 var d = -1;\r
76 var cp = 0;\r
77 var Error = null;\r
78 var nodename = null;\r
79 var commentString2 = null;\r
80 var DefDistance = 0.001;\r
81 var DefBootstrap = -1;\r
82 var distance = DefDistance;\r
83 var bootstrap = DefBootstrap;\r
84 var ascending = false;\r
85 var majorsyms = jalview.jsdev.RegExp.newRegex (["[(\\['),;]"]);\r
86 var nextcp = 0;\r
87 var ncp = cp;\r
88 var parsednodename = false;\r
89 while (majorsyms.searchFrom (nf, cp) && (Error == null)) {\r
90 var fcp = majorsyms.matchedFrom ();\r
91 var schar;\r
92 switch (schar = nf.charAt (fcp)) {\r
93 case '(':\r
94 if (ascending) {\r
95 Error = this.ErrorStringrange (Error, "Unexpected '('", 7, fcp, nf);\r
96 continue;\r
97 };d++;\r
98 if (c.right () == null) {\r
99 c.setRight ( new jalview.datamodel.SequenceNode (null, c, null, DefDistance, DefBootstrap, false));\r
100 c = c.right ();\r
101 } else {\r
102 if (c.left () != null) {\r
103 var tmpn =  new jalview.datamodel.SequenceNode (null, c, null, 0, 0, true);\r
104 tmpn.SetChildren (c.left (), c.right ());\r
105 c.setRight (tmpn);\r
106 }c.setLeft ( new jalview.datamodel.SequenceNode (null, c, null, DefDistance, DefBootstrap, false));\r
107 c = c.left ();\r
108 }if (realroot == null) {\r
109 realroot = c;\r
110 }nodename = null;\r
111 distance = DefDistance;\r
112 bootstrap = DefBootstrap;\r
113 cp = fcp + 1;\r
114 break;\r
115 case '\'':\r
116 var qnodename = jalview.jsdev.RegExp.newRegex (["'([^']|'')+'"]);\r
117 if (qnodename.searchFrom (nf, fcp)) {\r
118 var nl = qnodename.stringMatched ().length;\r
119 nodename =  String.instantialize (qnodename.stringMatched ().substring (1, nl - 1));\r
120 var xpandquotes = jalview.jsdev.RegExp.perlCode ("s/''/'/");\r
121 var widernodename = xpandquotes.replaceAll (nodename);\r
122 nodename = widernodename;\r
123 nextcp = fcp + nl + 1;\r
124 parsednodename = true;\r
125 } else {\r
126 Error = this.ErrorStringrange (Error, "Unterminated quotes for nodename", 7, fcp, nf);\r
127 }break;\r
128 default:\r
129 if (schar == ';') {\r
130 if (d != -1) {\r
131 Error = this.ErrorStringrange (Error, "Wayward semicolon (depth=" + d + ")", 7, fcp, nf);\r
132 }}if (schar == '[') {\r
133 var comment = jalview.jsdev.RegExp.newRegex (["]"]);\r
134 if (comment.searchFrom (nf, fcp)) {\r
135 nextcp = comment.matchedFrom () + 1;\r
136 this.warningMessage = "Tree file contained comments which may confuse input algorithm.";\r
137 break;\r
138 } else {\r
139 Error = this.ErrorStringrange (Error, "Unterminated comment", 3, fcp, nf);\r
140 };}var fstring = nf.substring (ncp, fcp);\r
141 while (fstring.indexOf (']') > -1) {\r
142 var cstart = fstring.indexOf ('[');\r
143 var cend = fstring.indexOf (']');\r
144 commentString2 = fstring.substring (cstart + 1, cend);\r
145 fstring = fstring.substring (0, cstart) + fstring.substring (cend + 1);\r
146 }\r
147 var uqnodename = jalview.jsdev.RegExp.newRegex (["\\b([^' :;\\](),]+)"]);\r
148 var nbootstrap = jalview.jsdev.RegExp.newRegex (["\\s*([0-9+]+)\\s*:"]);\r
149 var ndist = jalview.jsdev.RegExp.newRegex ([":([-0-9Ee.+]+)"]);\r
150 if (!parsednodename && uqnodename.search (fstring) && ((uqnodename.matchedFromI (1) == 0) || (fstring.charAt (uqnodename.matchedFromI (1) - 1) != ':'))) {\r
151 if (nodename == null) {\r
152 if (this.ReplaceUnderscores) {\r
153 nodename = uqnodename.stringMatchedI (1).$replace ('_', ' ');\r
154 } else {\r
155 nodename = uqnodename.stringMatchedI (1);\r
156 }} else {\r
157 Error = this.ErrorStringrange (Error, "File has broken algorithm - overwritten nodename", 10, fcp, nf);\r
158 }}if (nbootstrap.search (fstring)) {\r
159 if (nbootstrap.stringMatchedI (1).equals (uqnodename.stringMatchedI (1))) {\r
160 nodename = null;\r
161 }if (nodename == null || nodename.length == 0 || nbootstrap.matchedFromI (1) > (uqnodename.matchedFromI (1) + uqnodename.stringMatched ().length)) {\r
162 try {\r
163 bootstrap = ( new Integer (nbootstrap.stringMatchedI (1))).intValue ();\r
164 this.$HasBootstrap = true;\r
165 } catch (e) {\r
166 if (Clazz.exceptionOf (e, Exception)) {\r
167 Error = this.ErrorStringrange (Error, "Can't parse bootstrap value", 4, ncp + nbootstrap.matchedFrom (), nf);\r
168 } else {\r
169 throw e;\r
170 }\r
171 }\r
172 }}var nodehasdistance = false;\r
173 if (ndist.search (fstring)) {\r
174 try {\r
175 distance = ( new Float (ndist.stringMatchedI (1))).floatValue ();\r
176 this.$HasDistances = true;\r
177 nodehasdistance = true;\r
178 } catch (e) {\r
179 if (Clazz.exceptionOf (e, Exception)) {\r
180 Error = this.ErrorStringrange (Error, "Can't parse node distance value", 7, ncp + ndist.matchedFrom (), nf);\r
181 } else {\r
182 throw e;\r
183 }\r
184 }\r
185 }if (ascending) {\r
186 c.setName (nodename);\r
187 c.dist = (this.$HasDistances) ? distance : DefDistance;\r
188 c.setBootstrap ((this.$HasBootstrap) ? bootstrap : DefBootstrap);\r
189 if (c === realroot) {\r
190 this.RootHasDistance = nodehasdistance;\r
191 }this.parseNHXNodeProps (c, commentString2);\r
192 commentString2 = null;\r
193 } else {\r
194 var newnode =  new jalview.datamodel.SequenceNode (null, c, nodename, (this.$HasDistances) ? distance : DefDistance, (this.$HasBootstrap) ? bootstrap : DefBootstrap, false);\r
195 this.parseNHXNodeProps (c, commentString2);\r
196 commentString2 = null;\r
197 if (c.right () == null) {\r
198 c.setRight (newnode);\r
199 } else {\r
200 if (c.left () == null) {\r
201 c.setLeft (newnode);\r
202 } else {\r
203 var newdummy =  new jalview.datamodel.SequenceNode (null, c, null, (this.$HasDistances ? 0 : DefDistance), 0, true);\r
204 newdummy.SetChildren (c.left (), newnode);\r
205 c.setLeft (newdummy);\r
206 }}}if (ascending) {\r
207 c = c.AscendTree ();\r
208 if ((d > -1) && (c == null)) {\r
209 Error = this.ErrorStringrange (Error, "File broke algorithm: Lost place in tree (is there an extra ')' ?)", 7, fcp, nf);\r
210 }}if (nf.charAt (fcp) == ')') {\r
211 d--;\r
212 ascending = true;\r
213 } else {\r
214 if (nf.charAt (fcp) == ',') {\r
215 if (ascending) {\r
216 ascending = false;\r
217 } else {\r
218 if ((c.left () != null) && (!c.left ().isLeaf ())) {\r
219 c = c.left ();\r
220 }}}}nodename = null;\r
221 distance = DefDistance;\r
222 bootstrap = DefBootstrap;\r
223 commentString2 = null;\r
224 parsednodename = false;\r
225 }\r
226 if (nextcp == 0) {\r
227 ncp = cp = fcp + 1;\r
228 } else {\r
229 cp = nextcp;\r
230 nextcp = 0;\r
231 }}\r
232 if (Error != null) {\r
233 throw ( new java.io.IOException (jalview.util.MessageManager.formatMessage ("exception.newfile",  Clazz.newArray (-1, [Error.toString ()]))));\r
234 }if (this.root == null) {\r
235 throw ( new java.io.IOException (jalview.util.MessageManager.formatMessage ("exception.newfile",  Clazz.newArray (-1, [jalview.util.MessageManager.getString ("label.no_tree_read_in")]))));\r
236 }this.root = this.root.right ().detach ();\r
237 if (!this.RootHasDistance) {\r
238 this.root.dist = (this.$HasDistances) ? 0 : DefDistance;\r
239 }});\r
240 Clazz.defineMethod (c$, "parseNHXNodeProps", \r
241 ($fz = function (c, commentString) {\r
242 if (commentString != null && commentString.startsWith ("&&NHX")) {\r
243 var st =  new java.util.StringTokenizer (commentString.substring (5), ":");\r
244 while (st.hasMoreTokens ()) {\r
245 var tok = st.nextToken ();\r
246 var colpos = tok.indexOf ("=");\r
247 if (colpos > -1) {\r
248 var code = tok.substring (0, colpos);\r
249 var value = tok.substring (colpos + 1);\r
250 try {\r
251 if (code.toLowerCase ().equals ("b")) {\r
252 var v = -1;\r
253 var iv =  new Float (value);\r
254 v = iv.intValue ();\r
255 c.setBootstrap (v);\r
256 this.$HasBootstrap = true;\r
257 }} catch (e) {\r
258 if (Clazz.exceptionOf (e, Exception)) {\r
259 System.err.println ("Couldn't parse code '" + code + "' = '" + value + "'");\r
260 e.printStackTrace (System.err);\r
261 } else {\r
262 throw e;\r
263 }\r
264 }\r
265 }}\r
266 }}, $fz.isPrivate = true, $fz), "jalview.datamodel.SequenceNode,~S");\r
267 Clazz.defineMethod (c$, "getTree", \r
268 function () {\r
269 return this.root;\r
270 });\r
271 Clazz.defineMethod (c$, "print", \r
272 function () {\r
273 {\r
274 var tf =  new StringBuffer ();\r
275 this.print (tf, this.root);\r
276 return (tf.append (";").toString ());\r
277 }});\r
278 Clazz.defineMethod (c$, "print", \r
279 function (withbootstraps) {\r
280 {\r
281 var boots = this.$HasBootstrap;\r
282 this.$HasBootstrap = withbootstraps;\r
283 var rv = this.print ();\r
284 this.$HasBootstrap = boots;\r
285 return rv;\r
286 }}, "~B");\r
287 Clazz.defineMethod (c$, "print", \r
288 function (withbootstraps, withdists) {\r
289 {\r
290 var dists = this.$HasDistances;\r
291 this.$HasDistances = withdists;\r
292 var rv = this.print (withbootstraps);\r
293 this.$HasDistances = dists;\r
294 return rv;\r
295 }}, "~B,~B");\r
296 Clazz.defineMethod (c$, "print", \r
297 function (withbootstraps, withdists, printRootInfo) {\r
298 {\r
299 var rootinfo = printRootInfo;\r
300 this.printRootInfo = printRootInfo;\r
301 var rv = this.print (withbootstraps, withdists);\r
302 this.printRootInfo = rootinfo;\r
303 return rv;\r
304 }}, "~B,~B,~B");\r
305 Clazz.defineMethod (c$, "getQuoteChar", \r
306 function () {\r
307 return this.QuoteChar;\r
308 });\r
309 Clazz.defineMethod (c$, "setQuoteChar", \r
310 function (c) {\r
311 var old = this.QuoteChar;\r
312 this.QuoteChar = c;\r
313 return old;\r
314 }, "~S");\r
315 Clazz.defineMethod (c$, "nodeName", \r
316 ($fz = function (name) {\r
317 if (this.NodeSafeName[0].search (name)) {\r
318 return this.QuoteChar + this.NodeSafeName[1].replaceAll (name) + this.QuoteChar;\r
319 } else {\r
320 return this.NodeSafeName[2].replaceAll (name);\r
321 }}, $fz.isPrivate = true, $fz), "~S");\r
322 Clazz.defineMethod (c$, "printNodeField", \r
323 ($fz = function (c) {\r
324 return ((c.getName () == null) ? "" : this.nodeName (c.getName ())) + ((this.$HasBootstrap) ? ((c.getBootstrap () > -1) ? ((c.getName () != null ? " " : "") + c.getBootstrap ()) : "") : "") + ((this.$HasDistances) ? (":" + c.dist) : "");\r
325 }, $fz.isPrivate = true, $fz), "jalview.datamodel.SequenceNode");\r
326 Clazz.defineMethod (c$, "printRootField", \r
327 ($fz = function (root) {\r
328 return (this.printRootInfo) ? (((root.getName () == null) ? "" : this.nodeName (root.getName ())) + ((this.$HasBootstrap) ? ((root.getBootstrap () > -1) ? ((root.getName () != null ? " " : "") + +root.getBootstrap ()) : "") : "") + ((this.RootHasDistance) ? (":" + root.dist) : "")) : "";\r
329 }, $fz.isPrivate = true, $fz), "jalview.datamodel.SequenceNode");\r
330 Clazz.defineMethod (c$, "print", \r
331 function (tf, root) {\r
332 if (root != null) {\r
333 if (root.isLeaf () && this.printRootInfo) {\r
334 tf.append (this.printRootField (root));\r
335 } else {\r
336 if (root.isDummy ()) {\r
337 this._print (tf, root.right ());\r
338 this._print (tf, root.left ());\r
339 } else {\r
340 tf.append ("(");\r
341 this._print (tf, root.right ());\r
342 if (root.left () != null) {\r
343 tf.append (",");\r
344 }this._print (tf, root.left ());\r
345 tf.append (")" + this.printRootField (root));\r
346 }}}}, "StringBuffer,jalview.datamodel.SequenceNode");\r
347 Clazz.defineMethod (c$, "_print", \r
348 function (tf, c) {\r
349 if (c != null) {\r
350 if (c.isLeaf ()) {\r
351 tf.append (this.printNodeField (c));\r
352 } else {\r
353 if (c.isDummy ()) {\r
354 this._print (tf, c.left ());\r
355 if (c.left () != null) {\r
356 tf.append (",");\r
357 }this._print (tf, c.right ());\r
358 } else {\r
359 tf.append ("(");\r
360 this._print (tf, c.right ());\r
361 if (c.left () != null) {\r
362 tf.append (",");\r
363 }this._print (tf, c.left ());\r
364 tf.append (")" + this.printNodeField (c));\r
365 }}}}, "StringBuffer,jalview.datamodel.SequenceNode");\r
366 c$.main = Clazz.defineMethod (c$, "main", \r
367 function (args) {\r
368 try {\r
369 if (args == null || args.length != 1) {\r
370 System.err.println ("Takes one argument - file name of a newick tree file.");\r
371 System.exit (0);\r
372 }var fn =  new java.io.File (args[0]);\r
373 var newickfile =  new StringBuffer ();\r
374 var treefile =  new java.io.BufferedReader ( new java.io.FileReader (fn));\r
375 var l;\r
376 while ((l = treefile.readLine ()) != null) {\r
377 newickfile.append (l);\r
378 }\r
379 treefile.close ();\r
380 System.out.println ("Read file :\n");\r
381 var trf =  new jalview.io.NewickFile (args[0], "File");\r
382 trf.parse ();\r
383 System.out.println ("Original file :\n");\r
384 var nonl = jalview.jsdev.RegExp.newRegex (["\n+", ""]);\r
385 System.out.println (nonl.replaceAll (newickfile.toString ()) + "\n");\r
386 System.out.println ("Parsed file.\n");\r
387 System.out.println ("Default output type for original input.\n");\r
388 System.out.println (trf.print ());\r
389 System.out.println ("Without bootstraps.\n");\r
390 System.out.println (trf.print (false));\r
391 System.out.println ("Without distances.\n");\r
392 System.out.println (trf.print (true, false));\r
393 System.out.println ("Without bootstraps but with distanecs.\n");\r
394 System.out.println (trf.print (false, true));\r
395 System.out.println ("Without bootstraps or distanecs.\n");\r
396 System.out.println (trf.print (false, false));\r
397 System.out.println ("With bootstraps and with distances.\n");\r
398 System.out.println (trf.print (true, true));\r
399 } catch (e) {\r
400 if (Clazz.exceptionOf (e, java.io.IOException)) {\r
401 System.err.println ("Exception\n" + e);\r
402 e.printStackTrace ();\r
403 } else {\r
404 throw e;\r
405 }\r
406 }\r
407 }, "~A");\r
408 });\r