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