Fixed bug http://dragonfly.compbio.dundee.ac.uk/mantis/view.php?id=9326 for viewing...
[jalview.git] / src / jalview / io / NewickFile.java
1 /*\r
2 * Jalview - A Sequence Alignment Editor and Viewer\r
3 * Copyright (C) 2005 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle\r
4 *\r
5 * This program is free software; you can redistribute it and/or\r
6 * modify it under the terms of the GNU General Public License\r
7 * as published by the Free Software Foundation; either version 2\r
8 * of the License, or (at your option) any later version.\r
9 *\r
10 * This program is distributed in the hope that it will be useful,\r
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 * GNU General Public License for more details.\r
14 *\r
15 * You should have received a copy of the GNU General Public License\r
16 * along with this program; if not, write to the Free Software\r
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA\r
18 */\r
19 \r
20 // NewickFile.java\r
21 // Tree I/O\r
22 // http://evolution.genetics.washington.edu/phylip/newick_doc.html\r
23 package jalview.io;\r
24 \r
25 import jalview.datamodel.*;\r
26 \r
27 import java.io.*;\r
28 \r
29 \r
30 /**\r
31  * DOCUMENT ME!\r
32  *\r
33  * @author $author$\r
34  * @version $Revision$\r
35  */\r
36 public class NewickFile extends FileParse\r
37 {\r
38     SequenceNode root;\r
39     private boolean HasBootstrap = false;\r
40     private boolean HasDistances = false;\r
41     private boolean RootHasDistance = false;\r
42 \r
43     // File IO Flags\r
44     boolean ReplaceUnderscores = false;\r
45     boolean printRootInfo = false;\r
46     private com.stevesoft.pat.Regex[] NodeSafeName = new com.stevesoft.pat.Regex[]\r
47         {\r
48             new com.stevesoft.pat.Regex().perlCode("m/[\\[,:'()]/"), // test for requiring quotes\r
49             new com.stevesoft.pat.Regex().perlCode("s/'/''/"), // escaping quote characters\r
50             new com.stevesoft.pat.Regex().perlCode("s/\\/w/_/") // unqoted whitespace transformation\r
51         };\r
52     char QuoteChar = '\'';\r
53 \r
54     /**\r
55      * Creates a new NewickFile object.\r
56      *\r
57      * @param inStr DOCUMENT ME!\r
58      *\r
59      * @throws IOException DOCUMENT ME!\r
60      */\r
61     public NewickFile(String inStr) throws IOException\r
62     {\r
63         super(inStr, "Paste");\r
64     }\r
65 \r
66     /**\r
67      * Creates a new NewickFile object.\r
68      *\r
69      * @param inFile DOCUMENT ME!\r
70      * @param type DOCUMENT ME!\r
71      *\r
72      * @throws IOException DOCUMENT ME!\r
73      */\r
74     public NewickFile(String inFile, String type) throws IOException\r
75     {\r
76         super(inFile, type);\r
77     }\r
78 \r
79     /**\r
80      * Creates a new NewickFile object.\r
81      *\r
82      * @param newtree DOCUMENT ME!\r
83      */\r
84     public NewickFile(SequenceNode newtree)\r
85     {\r
86         root = newtree;\r
87     }\r
88 \r
89     /**\r
90      * Creates a new NewickFile object.\r
91      *\r
92      * @param newtree DOCUMENT ME!\r
93      * @param bootstrap DOCUMENT ME!\r
94      */\r
95     public NewickFile(SequenceNode newtree, boolean bootstrap)\r
96     {\r
97         HasBootstrap = bootstrap;\r
98         root = newtree;\r
99     }\r
100 \r
101     /**\r
102      * Creates a new NewickFile object.\r
103      *\r
104      * @param newtree DOCUMENT ME!\r
105      * @param bootstrap DOCUMENT ME!\r
106      * @param distances DOCUMENT ME!\r
107      */\r
108     public NewickFile(SequenceNode newtree, boolean bootstrap, boolean distances)\r
109     {\r
110         root = newtree;\r
111         HasBootstrap = bootstrap;\r
112         HasDistances = distances;\r
113     }\r
114 \r
115     /**\r
116      * Creates a new NewickFile object.\r
117      *\r
118      * @param newtree DOCUMENT ME!\r
119      * @param bootstrap DOCUMENT ME!\r
120      * @param distances DOCUMENT ME!\r
121      * @param rootdistance DOCUMENT ME!\r
122      */\r
123     public NewickFile(SequenceNode newtree, boolean bootstrap,\r
124         boolean distances, boolean rootdistance)\r
125     {\r
126         root = newtree;\r
127         HasBootstrap = bootstrap;\r
128         HasDistances = distances;\r
129         RootHasDistance = rootdistance;\r
130     }\r
131 \r
132     /**\r
133      * DOCUMENT ME!\r
134      *\r
135      * @param Error DOCUMENT ME!\r
136      * @param Er DOCUMENT ME!\r
137      * @param r DOCUMENT ME!\r
138      * @param p DOCUMENT ME!\r
139      * @param s DOCUMENT ME!\r
140      *\r
141      * @return DOCUMENT ME!\r
142      */\r
143     private String ErrorStringrange(String Error, String Er, int r, int p,\r
144         String s)\r
145     {\r
146         return ((Error == null) ? "" : Error) + Er + " at position " + p +\r
147         " ( " +\r
148         s.substring(((p - r) < 0) ? 0 : (p - r),\r
149             ((p + r) > s.length()) ? s.length() : (p + r)) + " )\n";\r
150     }\r
151 \r
152     // @tree annotations\r
153     // These are set automatically by the reader\r
154     public boolean HasBootstrap()\r
155     {\r
156         return HasBootstrap;\r
157     }\r
158 \r
159     /**\r
160      * DOCUMENT ME!\r
161      *\r
162      * @return DOCUMENT ME!\r
163      */\r
164     public boolean HasDistances()\r
165     {\r
166         return HasDistances;\r
167     }\r
168 \r
169     public boolean HasRootDistance()\r
170     {\r
171         return RootHasDistance;\r
172     }\r
173     /**\r
174      * DOCUMENT ME!\r
175      *\r
176      * @throws IOException DOCUMENT ME!\r
177      */\r
178     public void parse() throws IOException\r
179     {\r
180         String nf;\r
181 \r
182         { // fill nf with complete tree file\r
183 \r
184             StringBuffer file = new StringBuffer();\r
185 \r
186             while ((nf = nextLine()) != null)\r
187             {\r
188                 file.append(nf);\r
189             }\r
190 \r
191             nf = file.toString();\r
192         }\r
193 \r
194         root = new SequenceNode();\r
195 \r
196         SequenceNode realroot = null;\r
197         SequenceNode c = root;\r
198 \r
199         int d = -1;\r
200         int cp = 0;\r
201         //int flen = nf.length();\r
202 \r
203         String Error = null;\r
204         String nodename = null;\r
205 \r
206         float DefDistance = (float) 0.001; // @param Default distance for a node - very very small\r
207         int DefBootstrap = 0; // @param Default bootstrap for a node\r
208 \r
209         float distance = DefDistance;\r
210         int bootstrap = DefBootstrap;\r
211 \r
212         boolean ascending = false; // flag indicating that we are leaving the current node\r
213 \r
214         com.stevesoft.pat.Regex majorsyms = new com.stevesoft.pat.Regex(\r
215                 "[(\\['),;]");\r
216 \r
217         while (majorsyms.searchFrom(nf, cp) && (Error == null))\r
218         {\r
219             int fcp = majorsyms.matchedFrom();\r
220 \r
221             switch (nf.charAt(fcp))\r
222             {\r
223             case '[': // Comment or structured/extended NH format info\r
224 \r
225                 com.stevesoft.pat.Regex comment = new com.stevesoft.pat.Regex(\r
226                         "]");\r
227 \r
228                 if (comment.searchFrom(nf, fcp))\r
229                 {\r
230                     // Skip the comment field\r
231                     cp = 1 + comment.matchedFrom();\r
232                 }\r
233                 else\r
234                 {\r
235                     Error = ErrorStringrange(Error, "Unterminated comment", 3,\r
236                             fcp, nf);\r
237                 }\r
238 \r
239                 ;\r
240 \r
241                 break;\r
242 \r
243             case '(':\r
244 \r
245                 // ascending should not be set\r
246                 // New Internal node\r
247                 if (ascending)\r
248                 {\r
249                     Error = ErrorStringrange(Error, "Unexpected '('", 7, fcp, nf);\r
250 \r
251                     continue;\r
252                 }\r
253 \r
254                 ;\r
255                 d++;\r
256 \r
257                 if (c.right() == null)\r
258                 {\r
259                     c.setRight(new SequenceNode(null, c, null, DefDistance,\r
260                             DefBootstrap, false));\r
261                     c = (SequenceNode) c.right();\r
262                 }\r
263                 else\r
264                 {\r
265                     if (c.left() != null)\r
266                     {\r
267                         // Dummy node for polytomy - keeps c.left free for new node\r
268                         SequenceNode tmpn = new SequenceNode(null, c, null, 0,\r
269                                 0, true);\r
270                         tmpn.SetChildren(c.left(), c.right());\r
271                         c.setRight(tmpn);\r
272                     }\r
273 \r
274                     c.setLeft(new SequenceNode(null, c, null, DefDistance,\r
275                             DefBootstrap, false));\r
276                     c = (SequenceNode) c.left();\r
277                 }\r
278 \r
279                 if (realroot == null)\r
280                 {\r
281                     realroot = c;\r
282                 }\r
283 \r
284                 nodename = null;\r
285                 distance = DefDistance;\r
286                 bootstrap = DefBootstrap;\r
287                 cp = fcp + 1;\r
288 \r
289                 break;\r
290 \r
291             // Deal with quoted fields\r
292             case '\'':\r
293 \r
294                 com.stevesoft.pat.Regex qnodename = new com.stevesoft.pat.Regex(\r
295                         "([^']|'')+'");\r
296 \r
297                 if (qnodename.searchFrom(nf, fcp))\r
298                 {\r
299                     int nl = qnodename.stringMatched().length();\r
300                     nodename = new String(qnodename.stringMatched().substring(0,\r
301                                 nl - 1));\r
302                     cp = fcp + nl + 1;\r
303                 }\r
304                 else\r
305                 {\r
306                     Error = ErrorStringrange(Error,\r
307                             "Unterminated quotes for nodename", 7, fcp, nf);\r
308                 }\r
309 \r
310                 break;\r
311 \r
312             case ';':\r
313 \r
314                 if (d != -1)\r
315                 {\r
316                     Error = ErrorStringrange(Error,\r
317                             "Wayward semicolon (depth=" + d + ")", 7, fcp, nf);\r
318                 }\r
319 \r
320             // cp advanced at the end of default\r
321             default:\r
322 \r
323                 // Parse simpler field strings\r
324                 String fstring = nf.substring(cp, fcp);\r
325                 com.stevesoft.pat.Regex uqnodename = new com.stevesoft.pat.Regex(\r
326                         "\\b([^' :;\\](),]+)");\r
327                 com.stevesoft.pat.Regex nbootstrap = new com.stevesoft.pat.Regex(\r
328                         "\\S+([0-9+]+)\\S*:");\r
329                 com.stevesoft.pat.Regex ndist = new com.stevesoft.pat.Regex(\r
330                         ":([-0-9Ee.+]+)");\r
331 \r
332                 if (uqnodename.search(fstring) &&\r
333                         ((uqnodename.matchedFrom(1) == 0) ||\r
334                         (fstring.charAt(uqnodename.matchedFrom(1) - 1) != ':'))) // JBPNote HACK!\r
335                 {\r
336                     if (nodename == null)\r
337                     {\r
338                         if (ReplaceUnderscores)\r
339                         {\r
340                             nodename = uqnodename.stringMatched(1).replace('_',\r
341                                     ' ');\r
342                         }\r
343                         else\r
344                         {\r
345                             nodename = uqnodename.stringMatched(1);\r
346                         }\r
347                     }\r
348                     else\r
349                     {\r
350                         Error = ErrorStringrange(Error,\r
351                                 "File has broken algorithm - overwritten nodename",\r
352                                 10, fcp, nf);\r
353                     }\r
354                 }\r
355 \r
356                 if (nbootstrap.search(fstring) &&\r
357                         (nbootstrap.matchedFrom(1) > (uqnodename.matchedFrom(1) +\r
358                         uqnodename.stringMatched().length())))\r
359                 {\r
360                     try\r
361                     {\r
362                         bootstrap = (new Integer(nbootstrap.stringMatched(1))).intValue();\r
363                         HasBootstrap = true;\r
364                     }\r
365                     catch (Exception e)\r
366                     {\r
367                         Error = ErrorStringrange(Error,\r
368                                 "Can't parse bootstrap value", 4,\r
369                                 cp + nbootstrap.matchedFrom(), nf);\r
370                     }\r
371                 }\r
372 \r
373                 boolean nodehasdistance = false;\r
374 \r
375                 if (ndist.search(fstring))\r
376                 {\r
377                     try\r
378                     {\r
379                         distance = (new Float(ndist.stringMatched(1))).floatValue();\r
380                         HasDistances = true;\r
381                         nodehasdistance = true;\r
382                     }\r
383                     catch (Exception e)\r
384                     {\r
385                         Error = ErrorStringrange(Error,\r
386                                 "Can't parse node distance value", 7,\r
387                                 cp + ndist.matchedFrom(), nf);\r
388                     }\r
389                 }\r
390 \r
391                 if (ascending)\r
392                 {\r
393                     // Write node info here\r
394                     c.setName(nodename);\r
395                     // Trees without distances still need a render distance\r
396                     c.dist = (HasDistances) ? distance : DefDistance;\r
397                     // be consistent for internal bootstrap defaults too\r
398                     c.setBootstrap((HasBootstrap) ? bootstrap : DefBootstrap);\r
399                     if (c == realroot)\r
400                     {\r
401                         RootHasDistance = nodehasdistance; // JBPNote This is really UGLY!!! Ensure root node gets its given distance\r
402                     }\r
403                 }\r
404                 else\r
405                 {\r
406                     // Find a place to put the leaf\r
407                     SequenceNode newnode = new SequenceNode(null, c, nodename,\r
408                             (HasDistances) ? distance : DefDistance,\r
409                             (HasBootstrap) ? bootstrap : DefBootstrap, false);\r
410 \r
411                     if (c.right() == null)\r
412                     {\r
413                         c.setRight(newnode);\r
414                     }\r
415                     else\r
416                     {\r
417                         if (c.left() == null)\r
418                         {\r
419                             c.setLeft(newnode);\r
420                         }\r
421                         else\r
422                         {\r
423                             // Insert a dummy node for polytomy\r
424                             // dummy nodes have distances\r
425                             SequenceNode newdummy = new SequenceNode(null, c,\r
426                                     null, (HasDistances ? 0 : DefDistance), 0, true);\r
427                             newdummy.SetChildren(c.left(), newnode);\r
428                             c.setLeft(newdummy);\r
429                         }\r
430                     }\r
431                 }\r
432 \r
433                 if (ascending)\r
434                 {\r
435                     // move back up the tree from preceding closure\r
436                     c = c.AscendTree();\r
437 \r
438                     if ((d > -1) && (c == null))\r
439                     {\r
440                         Error = ErrorStringrange(Error,\r
441                                 "File broke algorithm: Lost place in tree (is there an extra ')' ?)",\r
442                                 7, fcp, nf);\r
443                     }\r
444                 }\r
445 \r
446                 if (nf.charAt(fcp) == ')')\r
447                 {\r
448                     d--;\r
449                     ascending = true;\r
450                 }\r
451                 else\r
452                 {\r
453                     if (nf.charAt(fcp) == ',')\r
454                     {\r
455                         if (ascending)\r
456                         {\r
457                             ascending = false;\r
458                         }\r
459                         else\r
460                         {\r
461                             // Just advance focus, if we need to\r
462                             if ((c.left() != null) && (!c.left().isLeaf()))\r
463                             {\r
464                                 c = (SequenceNode) c.left();\r
465                             }\r
466                         }\r
467                     }\r
468 \r
469                     // else : We do nothing if ';' is encountered.\r
470                 }\r
471 \r
472                 // Reset new node properties to obvious fakes\r
473                 nodename = null;\r
474                 distance = DefDistance;\r
475                 bootstrap = DefBootstrap;\r
476 \r
477                 cp = fcp + 1;\r
478             }\r
479         }\r
480 \r
481         if (Error != null)\r
482         {\r
483             throw (new IOException("NewickFile: " + Error + "\n"));\r
484         }\r
485 \r
486         root = (SequenceNode) root.right().detach(); // remove the imaginary root.\r
487 \r
488         if (!RootHasDistance)\r
489         {\r
490             root.dist = (HasDistances) ? 0 : DefDistance;\r
491         }\r
492     }\r
493 \r
494     /**\r
495      * DOCUMENT ME!\r
496      *\r
497      * @return DOCUMENT ME!\r
498      */\r
499     public SequenceNode getTree()\r
500     {\r
501         return root;\r
502     }\r
503 \r
504     /**\r
505      * Generate a newick format tree according to internal flags\r
506      * for bootstraps, distances and root distances.\r
507      *\r
508      * @return new hampshire tree in a single line\r
509      */\r
510     public String print()\r
511     {\r
512         synchronized (this)\r
513         {\r
514             StringBuffer tf = new StringBuffer();\r
515             print(tf, root);\r
516 \r
517             return (tf.append(";").toString());\r
518         }\r
519     }\r
520 \r
521     /**\r
522      *\r
523      *\r
524      * Generate a newick format tree according to internal flags\r
525      * for distances and root distances and user specificied writing of\r
526      * bootstraps.\r
527      * @param withbootstraps controls if bootstrap values are explicitly written.\r
528      *\r
529      * @return new hampshire tree in a single line\r
530      */\r
531     public String print(boolean withbootstraps)\r
532     {\r
533         synchronized (this)\r
534         {\r
535             boolean boots = this.HasBootstrap;\r
536             this.HasBootstrap = withbootstraps;\r
537 \r
538             String rv = print();\r
539             this.HasBootstrap = boots;\r
540 \r
541             return rv;\r
542         }\r
543     }\r
544 \r
545     /**\r
546      *\r
547      * Generate newick format tree according to internal flags\r
548      * for writing root node distances.\r
549      *\r
550      * @param withbootstraps explicitly write bootstrap values\r
551      * @param withdists explicitly write distances\r
552      *\r
553      * @return new hampshire tree in a single line\r
554      */\r
555     public String print(boolean withbootstraps, boolean withdists)\r
556     {\r
557         synchronized (this)\r
558         {\r
559             boolean dists = this.HasDistances;\r
560             this.HasDistances = withdists;\r
561 \r
562             String rv = print(withbootstraps);\r
563             this.HasDistances = dists;\r
564 \r
565             return rv;\r
566         }\r
567     }\r
568 \r
569     /**\r
570      * Generate newick format tree according to user specified flags\r
571      *\r
572      * @param withbootstraps explicitly write bootstrap values\r
573      * @param withdists explicitly write distances\r
574      * @param printRootInfo explicitly write root distance\r
575      *\r
576      * @return new hampshire tree in a single line\r
577      */\r
578     public String print(boolean withbootstraps, boolean withdists,\r
579         boolean printRootInfo)\r
580     {\r
581         synchronized (this)\r
582         {\r
583             boolean rootinfo = printRootInfo;\r
584             this.printRootInfo = printRootInfo;\r
585 \r
586             String rv = print(withbootstraps, withdists);\r
587             this.printRootInfo = rootinfo;\r
588 \r
589             return rv;\r
590         }\r
591     }\r
592 \r
593     /**\r
594      * DOCUMENT ME!\r
595      *\r
596      * @return DOCUMENT ME!\r
597      */\r
598     char getQuoteChar()\r
599     {\r
600         return QuoteChar;\r
601     }\r
602 \r
603     /**\r
604      * DOCUMENT ME!\r
605      *\r
606      * @param c DOCUMENT ME!\r
607      *\r
608      * @return DOCUMENT ME!\r
609      */\r
610     char setQuoteChar(char c)\r
611     {\r
612         char old = QuoteChar;\r
613         QuoteChar = c;\r
614 \r
615         return old;\r
616     }\r
617 \r
618     /**\r
619      * DOCUMENT ME!\r
620      *\r
621      * @param name DOCUMENT ME!\r
622      *\r
623      * @return DOCUMENT ME!\r
624      */\r
625     private String nodeName(String name)\r
626     {\r
627         if (NodeSafeName[0].search(name))\r
628         {\r
629             return QuoteChar + NodeSafeName[1].replaceAll(name) + QuoteChar;\r
630         }\r
631         else\r
632         {\r
633             return NodeSafeName[2].replaceAll(name);\r
634         }\r
635     }\r
636 \r
637     /**\r
638      * DOCUMENT ME!\r
639      *\r
640      * @param c DOCUMENT ME!\r
641      *\r
642      * @return DOCUMENT ME!\r
643      */\r
644     private String printNodeField(SequenceNode c)\r
645     {\r
646         return ((c.getName() == null) ? "" : nodeName(c.getName())) +\r
647         ((HasBootstrap)\r
648         ? ((c.getBootstrap() > -1) ? (" " + c.getBootstrap()) : "") : "") +\r
649         ((HasDistances) ? (":" + c.dist) : "");\r
650     }\r
651 \r
652     /**\r
653      * DOCUMENT ME!\r
654      *\r
655      * @param root DOCUMENT ME!\r
656      *\r
657      * @return DOCUMENT ME!\r
658      */\r
659     private String printRootField(SequenceNode root)\r
660     {\r
661         return (printRootInfo)\r
662         ? (((root.getName() == null) ? "" : nodeName(root.getName())) +\r
663         ((HasBootstrap)\r
664         ? ((root.getBootstrap() > -1) ? (" " + root.getBootstrap()) : "") : "") +\r
665         ((RootHasDistance) ? (":" + root.dist) : "")) : "";\r
666     }\r
667 \r
668     // Non recursive call deals with root node properties\r
669     public void print(StringBuffer tf, SequenceNode root)\r
670     {\r
671         if (root != null)\r
672         {\r
673             if (root.isLeaf() && printRootInfo)\r
674             {\r
675                 tf.append(printRootField(root));\r
676             }\r
677             else\r
678             {\r
679                 if (root.isDummy())\r
680                 {\r
681                     _print(tf, (SequenceNode) root.right());\r
682                     _print(tf, (SequenceNode) root.left());\r
683                 }\r
684                 else\r
685                 {\r
686                     tf.append("(");\r
687                     _print(tf, (SequenceNode) root.right());\r
688 \r
689                     if (root.left() != null)\r
690                     {\r
691                         tf.append(",");\r
692                     }\r
693 \r
694                     _print(tf, (SequenceNode) root.left());\r
695                     tf.append(")" + printRootField(root));\r
696                 }\r
697             }\r
698         }\r
699     }\r
700 \r
701     // Recursive call for non-root nodes\r
702     public void _print(StringBuffer tf, SequenceNode c)\r
703     {\r
704         if (c != null)\r
705         {\r
706             if (c.isLeaf())\r
707             {\r
708                 tf.append(printNodeField(c));\r
709             }\r
710             else\r
711             {\r
712                 if (c.isDummy())\r
713                 {\r
714                     _print(tf, (SequenceNode) c.left());\r
715                     if (c.left() != null)\r
716                     {\r
717                       tf.append(",");\r
718                     }\r
719                     _print(tf, (SequenceNode) c.right());\r
720                 }\r
721                 else\r
722                 {\r
723                     tf.append("(");\r
724                     _print(tf, (SequenceNode) c.right());\r
725 \r
726                     if (c.left() != null)\r
727                     {\r
728                         tf.append(",");\r
729                     }\r
730 \r
731                     _print(tf, (SequenceNode) c.left());\r
732                     tf.append(")" + printNodeField(c));\r
733                 }\r
734             }\r
735         }\r
736     }\r
737 \r
738     // Test\r
739     public static void main(String[] args)\r
740     {\r
741         try\r
742         {\r
743             if (args==null || args.length!=1) {\r
744               System.err.println("Takes one argument - file name of a newick tree file.");\r
745               System.exit(0);\r
746             }\r
747 \r
748             File fn = new File(args[0]);\r
749 \r
750             StringBuffer newickfile = new StringBuffer();\r
751             BufferedReader treefile = new BufferedReader(new FileReader(fn));\r
752             String l;\r
753 \r
754             while ((l = treefile.readLine()) != null)\r
755             {\r
756                 newickfile.append(l);\r
757             }\r
758 \r
759             treefile.close();\r
760             System.out.println("Read file :\n");\r
761 \r
762             NewickFile trf = new NewickFile(args[0], "File");\r
763             trf.parse();\r
764             System.out.println("Original file :\n");\r
765 \r
766             com.stevesoft.pat.Regex nonl = new com.stevesoft.pat.Regex("\n+", "");\r
767             System.out.println(nonl.replaceAll(newickfile.toString()) + "\n");\r
768 \r
769             System.out.println("Parsed file.\n");\r
770             System.out.println("Default output type for original input.\n");\r
771             System.out.println(trf.print());\r
772             System.out.println("Without bootstraps.\n");\r
773             System.out.println(trf.print(false));\r
774             System.out.println("Without distances.\n");\r
775             System.out.println(trf.print(true, false));\r
776             System.out.println("Without bootstraps but with distanecs.\n");\r
777             System.out.println(trf.print(false, true));\r
778             System.out.println("Without bootstraps or distanecs.\n");\r
779             System.out.println(trf.print(false, false));\r
780             System.out.println("With bootstraps and with distances.\n");\r
781             System.out.println(trf.print(true, true));\r
782         }\r
783         catch (java.io.IOException e)\r
784         {\r
785             System.err.println("Exception\n" + e);\r
786             e.printStackTrace();\r
787         }\r
788     }\r
789 }\r