2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 // Contact: phylosoft @ gmail . com
24 // WWW: https://sites.google.com/site/cmzmasek/home/software/forester
26 package org.forester.io.writers;
28 import java.io.BufferedWriter;
30 import java.io.FileWriter;
31 import java.io.IOException;
32 import java.io.PrintWriter;
33 import java.io.StringWriter;
34 import java.io.Writer;
35 import java.util.ArrayList;
36 import java.util.Iterator;
37 import java.util.List;
38 import java.util.Stack;
40 import org.forester.io.parsers.nexus.NexusConstants;
41 import org.forester.io.parsers.phyloxml.PhyloXmlMapping;
42 import org.forester.phylogeny.Phylogeny;
43 import org.forester.phylogeny.PhylogenyNode;
44 import org.forester.phylogeny.PhylogenyNode.NH_CONVERSION_SUPPORT_VALUE_STYLE;
45 import org.forester.phylogeny.data.PhylogenyDataUtil;
46 import org.forester.phylogeny.iterators.PhylogenyNodeIterator;
47 import org.forester.phylogeny.iterators.PostOrderStackObject;
48 import org.forester.util.ForesterConstants;
49 import org.forester.util.ForesterUtil;
51 public final class PhylogenyWriter {
53 public final static boolean INDENT_PHYLOXML_DEAFULT = true;
54 public final static String PHYLO_XML_INTENDATION_BASE = " ";
55 public final static String PHYLO_XML_VERSION_ENCODING_LINE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
56 public final static String PHYLO_XML_NAMESPACE_LINE = "<phyloxml xmlns:xsi=\""
57 + ForesterConstants.XML_SCHEMA_INSTANCE
58 + "\" xsi:schemaLocation=\""
59 + ForesterConstants.PHYLO_XML_LOCATION
61 + ForesterConstants.PHYLO_XML_LOCATION
63 + ForesterConstants.PHYLO_XML_VERSION
64 + "/" + ForesterConstants.PHYLO_XML_XSD
66 + ForesterConstants.PHYLO_XML_LOCATION
68 public final static String PHYLO_XML_END = "</phyloxml>";
69 private boolean _saw_comma;
70 private StringBuffer _buffer;
71 private Writer _writer;
72 private PhylogenyNode _root;
73 private boolean _has_next;
74 private Stack<PostOrderStackObject> _stack;
75 private boolean _nh_write_distance_to_parent;
76 NH_CONVERSION_SUPPORT_VALUE_STYLE _nh_conversion_support_style;
77 private boolean _indent_phyloxml;
78 private int _node_level;
79 private int _phyloxml_level;
80 private FORMAT _format;
82 public PhylogenyWriter() {
83 setIndentPhyloxml( INDENT_PHYLOXML_DEAFULT );
84 setNhConversionSupportStyle( NH_CONVERSION_SUPPORT_VALUE_STYLE.NONE );
87 private void appendPhylogenyLevelPhyloXml( final Writer writer, final Phylogeny tree ) throws IOException {
88 final String indentation = new String();
89 if ( !ForesterUtil.isEmpty( tree.getName() ) ) {
90 PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.PHYLOGENY_NAME, tree.getName(), indentation );
92 if ( tree.getIdentifier() != null ) {
93 if ( ForesterUtil.isEmpty( tree.getIdentifier().getProvider() ) ) {
94 PhylogenyDataUtil.appendElement( writer,
95 PhyloXmlMapping.IDENTIFIER,
96 tree.getIdentifier().getValue(),
99 PhylogenyDataUtil.appendElement( writer,
100 PhyloXmlMapping.IDENTIFIER,
101 tree.getIdentifier().getValue(),
102 PhyloXmlMapping.IDENTIFIER_PROVIDER_ATTR,
103 tree.getIdentifier().getProvider(),
106 if ( !ForesterUtil.isEmpty( tree.getDescription() ) ) {
107 PhylogenyDataUtil.appendElement( writer,
108 PhyloXmlMapping.PHYLOGENY_DESCRIPTION,
109 tree.getDescription(),
112 if ( tree.getConfidence() != null ) {
113 if ( ForesterUtil.isEmpty( tree.getConfidence().getType() ) ) {
114 PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.CONFIDENCE, tree.getConfidence().getValue()
117 PhylogenyDataUtil.appendElement( writer,
118 PhyloXmlMapping.CONFIDENCE,
119 tree.getConfidence().getValue() + "",
120 PhyloXmlMapping.CONFIDENCE_TYPE_ATTR,
121 tree.getConfidence().getType(),
126 private StringBuffer createIndentation() {
127 if ( !isIndentPhyloxml() ) {
130 final StringBuffer sb = new StringBuffer( getNodeLevel() * 2 );
131 for( int i = 0; i < getNodeLevel(); ++i ) {
132 sb.append( PhylogenyWriter.PHYLO_XML_INTENDATION_BASE );
137 private void decreaseNodeLevel() {
141 private StringBuffer getBuffer() {
145 private int getNodeLevel() {
149 private StringBuffer getOutput( final Phylogeny tree ) throws IOException {
150 if ( getOutputFormt() == FORMAT.PHYLO_XML ) {
151 throw new RuntimeException( "method inappropriately called" );
153 if ( tree != null ) {
155 while ( isHasNext() ) {
158 if ( getOutputFormt() == FORMAT.NH ) {
159 getBuffer().append( ';' );
164 return new StringBuffer( 0 );
168 private FORMAT getOutputFormt() {
172 private int getPhyloXmlLevel() {
173 return _phyloxml_level;
176 private PhylogenyNode getRoot() {
180 private Stack<PostOrderStackObject> getStack() {
184 private Writer getWriter() {
188 private void increaseNodeLevel() {
192 private boolean isHasNext() {
196 private boolean isIndentPhyloxml() {
197 return _indent_phyloxml;
200 private boolean isSawComma() {
204 private boolean isWriteDistanceToParentInNH() {
205 return _nh_write_distance_to_parent;
208 private void next() throws IOException {
210 final PostOrderStackObject si = getStack().pop();
211 final PhylogenyNode node = si.getNode();
212 final int phase = si.getPhase();
213 if ( phase > node.getNumberOfDescendants() ) {
214 setHasNext( node != getRoot() );
215 if ( ( getOutputFormt() != FORMAT.PHYLO_XML ) || node.isExternal() ) {
216 if ( !node.isRoot() && node.isFirstChildNode() ) {
219 if ( getOutputFormt() == FORMAT.PHYLO_XML ) {
220 writeNode( node, createIndentation() );
223 writeNode( node, null );
226 if ( !node.isRoot() ) {
227 if ( !node.isLastChildNode() ) {
228 writeCladeSeparator();
237 getStack().push( new PostOrderStackObject( node, ( phase + 1 ) ) );
238 if ( node.isInternal() ) {
239 getStack().push( new PostOrderStackObject( node.getChildNode( phase - 1 ), 1 ) );
240 writeOpenClade( node );
241 if ( getOutputFormt() == FORMAT.PHYLO_XML ) {
243 writeNode( node, createIndentation() );
251 private void reset( final Phylogeny tree ) {
252 setBuffer( new StringBuffer() );
254 setSawComma( false );
256 setRoot( tree.getRoot() );
257 setStack( new Stack<PostOrderStackObject>() );
258 getStack().push( new PostOrderStackObject( tree.getRoot(), 1 ) );
262 private void reset( final Writer writer, final Phylogeny tree ) {
265 setSawComma( false );
267 setRoot( tree.getRoot() );
268 setStack( new Stack<PostOrderStackObject>() );
269 getStack().push( new PostOrderStackObject( tree.getRoot(), 1 ) );
273 private void setBuffer( final StringBuffer buffer ) {
277 private void setHasNext( final boolean has_next ) {
278 _has_next = has_next;
281 public void setIndentPhyloxml( final boolean indent_phyloxml ) {
282 _indent_phyloxml = indent_phyloxml;
285 private void setNodeLevel( final int level ) {
289 private void setOutputFormt( final FORMAT format ) {
293 private void setPhyloXmlLevel( final int phyloxml_level ) {
294 _phyloxml_level = phyloxml_level;
297 private void setRoot( final PhylogenyNode root ) {
301 private void setSawComma( final boolean saw_comma ) {
302 _saw_comma = saw_comma;
305 private void setStack( final Stack<PostOrderStackObject> stack ) {
309 private void setWriteDistanceToParentInNH( final boolean nh_write_distance_to_parent ) {
310 _nh_write_distance_to_parent = nh_write_distance_to_parent;
313 private void setWriter( final Writer writer ) {
317 public void toNewHampshire( final List<Phylogeny> trees,
318 final boolean write_distance_to_parent,
320 final String separator ) throws IOException {
321 final Iterator<Phylogeny> it = trees.iterator();
322 final StringBuffer sb = new StringBuffer();
323 while ( it.hasNext() ) {
324 sb.append( toNewHampshire( it.next(), write_distance_to_parent ) );
325 sb.append( separator );
327 writeToFile( sb, out_file );
330 public StringBuffer toNewHampshire( final Phylogeny tree,
331 final boolean nh_write_distance_to_parent,
332 final NH_CONVERSION_SUPPORT_VALUE_STYLE svs ) throws IOException {
333 setOutputFormt( FORMAT.NH );
334 setNhConversionSupportStyle( svs );
335 setWriteDistanceToParentInNH( nh_write_distance_to_parent );
336 return getOutput( tree );
339 public StringBuffer toNewHampshire( final Phylogeny tree, final boolean nh_write_distance_to_parent )
341 setOutputFormt( FORMAT.NH );
342 setWriteDistanceToParentInNH( nh_write_distance_to_parent );
343 return getOutput( tree );
346 public void toNewHampshire( final Phylogeny tree, final boolean write_distance_to_parent, final File out_file )
348 writeToFile( toNewHampshire( tree, write_distance_to_parent ), out_file );
351 public void toNewHampshire( final Phylogeny tree,
352 final boolean write_distance_to_parent,
353 final NH_CONVERSION_SUPPORT_VALUE_STYLE svs,
354 final File out_file ) throws IOException {
355 writeToFile( toNewHampshire( tree, write_distance_to_parent, svs ), out_file );
358 public void toNewHampshire( final Phylogeny[] trees,
359 final boolean write_distance_to_parent,
361 final String separator ) throws IOException {
362 final StringBuffer sb = new StringBuffer();
363 for( final Phylogeny element : trees ) {
364 sb.append( toNewHampshire( element, write_distance_to_parent ) );
365 sb.append( separator );
367 writeToFile( sb, out_file );
370 public void toNewHampshireX( final List<Phylogeny> trees, final File out_file, final String separator )
372 final Iterator<Phylogeny> it = trees.iterator();
373 final StringBuffer sb = new StringBuffer();
374 while ( it.hasNext() ) {
375 sb.append( toNewHampshireX( it.next() ) );
376 sb.append( separator );
378 writeToFile( sb, out_file );
381 public StringBuffer toNewHampshireX( final Phylogeny tree ) throws IOException {
382 setOutputFormt( FORMAT.NHX );
383 return getOutput( tree );
386 public void toNewHampshireX( final Phylogeny tree, final File out_file ) throws IOException {
387 writeToFile( toNewHampshireX( tree ), out_file );
390 public void toNewHampshireX( final Phylogeny[] trees, final File out_file, final String separator )
392 final StringBuffer sb = new StringBuffer();
393 for( final Phylogeny element : trees ) {
394 sb.append( toNewHampshireX( element ) );
395 sb.append( separator );
397 writeToFile( sb, out_file );
400 public void toNexus( final File out_file, final Phylogeny tree, final NH_CONVERSION_SUPPORT_VALUE_STYLE svs )
402 final Writer writer = new BufferedWriter( new PrintWriter( out_file ) );
403 final List<Phylogeny> trees = new ArrayList<Phylogeny>( 1 );
405 writeNexusStart( writer );
406 writeNexusTaxaBlock( writer, tree );
407 writeNexusTreesBlock( writer, trees, svs );
412 public StringBuffer toNexus( final Phylogeny tree, final NH_CONVERSION_SUPPORT_VALUE_STYLE svs ) throws IOException {
413 final StringWriter string_writer = new StringWriter();
414 final Writer writer = new BufferedWriter( string_writer );
415 final List<Phylogeny> trees = new ArrayList<Phylogeny>( 1 );
417 writeNexusStart( writer );
418 writeNexusTaxaBlock( writer, tree );
419 writeNexusTreesBlock( writer, trees, svs );
422 return string_writer.getBuffer();
425 public void toPhyloXML( final File out_file,
426 final List<Phylogeny> trees,
427 final int phyloxml_level,
428 final String separator ) throws IOException {
429 final Writer writer = new BufferedWriter( new PrintWriter( out_file ) );
430 toPhyloXML( writer, trees, phyloxml_level, separator );
435 public void toPhyloXML( final File out_file, final Phylogeny tree, final int phyloxml_level ) throws IOException {
436 final Writer writer = new BufferedWriter( new PrintWriter( out_file ) );
437 writePhyloXmlStart( writer );
438 toPhyloXMLNoPhyloXmlSource( writer, tree, phyloxml_level );
439 writePhyloXmlEnd( writer );
444 public StringBuffer toPhyloXML( final Phylogeny tree, final int phyloxml_level ) throws IOException {
445 final StringWriter string_writer = new StringWriter();
446 final Writer writer = new BufferedWriter( string_writer );
447 setPhyloXmlLevel( phyloxml_level );
448 setOutputFormt( FORMAT.PHYLO_XML );
449 writePhyloXmlStart( writer );
450 writeOutput( writer, tree );
451 writePhyloXmlEnd( writer );
454 return string_writer.getBuffer();
457 public void toPhyloXML( final Phylogeny[] trees,
458 final int phyloxml_level,
460 final String separator ) throws IOException {
461 final Writer writer = new BufferedWriter( new PrintWriter( out_file ) );
462 toPhyloXML( writer, trees, phyloxml_level, separator );
467 public void toPhyloXML( final Phylogeny phy, final int phyloxml_level, final File out_file ) throws IOException {
468 final Writer writer = new BufferedWriter( new PrintWriter( out_file ) );
469 toPhyloXML( writer, phy, phyloxml_level );
474 public void toPhyloXML( final Writer writer,
475 final List<Phylogeny> trees,
476 final int phyloxml_level,
477 final String separator ) throws IOException {
478 writePhyloXmlStart( writer );
479 final Iterator<Phylogeny> it = trees.iterator();
480 while ( it.hasNext() ) {
481 toPhyloXMLNoPhyloXmlSource( writer, it.next(), phyloxml_level );
482 writer.write( separator );
484 writePhyloXmlEnd( writer );
487 public void toPhyloXML( final Writer writer, final Phylogeny tree, final int phyloxml_level ) throws IOException {
488 setPhyloXmlLevel( phyloxml_level );
489 setOutputFormt( FORMAT.PHYLO_XML );
490 writePhyloXmlStart( writer );
491 writeOutput( writer, tree );
492 writePhyloXmlEnd( writer );
495 public void toPhyloXML( final Writer writer,
496 final Phylogeny[] trees,
497 final int phyloxml_level,
498 final String separator ) throws IOException {
499 writePhyloXmlStart( writer );
500 for( final Phylogeny phylogeny : trees ) {
501 toPhyloXMLNoPhyloXmlSource( writer, phylogeny, phyloxml_level );
502 writer.write( separator );
504 writePhyloXmlEnd( writer );
507 private void toPhyloXMLNoPhyloXmlSource( final Writer writer, final Phylogeny tree, final int phyloxml_level )
509 setPhyloXmlLevel( phyloxml_level );
510 setOutputFormt( FORMAT.PHYLO_XML );
511 writeOutput( writer, tree );
514 private void writeCladeSeparator() {
516 if ( ( getOutputFormt() == FORMAT.NHX ) || ( getOutputFormt() == FORMAT.NH ) ) {
517 getBuffer().append( "," );
521 private void writeCloseClade() throws IOException {
523 if ( getOutputFormt() == FORMAT.PHYLO_XML ) {
524 getWriter().write( ForesterUtil.LINE_SEPARATOR );
525 if ( isIndentPhyloxml() ) {
526 getWriter().write( createIndentation().toString() );
528 PhylogenyDataUtil.appendClose( getWriter(), PhyloXmlMapping.CLADE );
530 else if ( ( getOutputFormt() == FORMAT.NHX ) || ( getOutputFormt() == FORMAT.NH ) ) {
531 getBuffer().append( ")" );
535 private void writeNode( final PhylogenyNode node, final StringBuffer indentation ) throws IOException {
536 if ( getOutputFormt() == FORMAT.PHYLO_XML ) {
537 if ( node.isExternal() ) {
538 getWriter().write( ForesterUtil.LINE_SEPARATOR );
539 if ( indentation != null ) {
540 getWriter().write( indentation.toString() );
542 PhylogenyDataUtil.appendOpen( getWriter(), PhyloXmlMapping.CLADE );
544 PhyloXmlNodeWriter.toPhyloXml( getWriter(),
547 indentation != null ? indentation.toString() : "" );
548 if ( node.isExternal() ) {
549 getWriter().write( ForesterUtil.LINE_SEPARATOR );
550 if ( indentation != null ) {
551 getWriter().write( indentation.toString() );
553 PhylogenyDataUtil.appendClose( getWriter(), PhyloXmlMapping.CLADE );
556 else if ( getOutputFormt() == FORMAT.NHX ) {
557 getBuffer().append( node.toNewHampshireX() );
559 else if ( getOutputFormt() == FORMAT.NH ) {
560 getBuffer().append( node.toNewHampshire( isWriteDistanceToParentInNH(), getNhConversionSupportStyle() ) );
564 private NH_CONVERSION_SUPPORT_VALUE_STYLE getNhConversionSupportStyle() {
565 return _nh_conversion_support_style;
568 private void setNhConversionSupportStyle( final NH_CONVERSION_SUPPORT_VALUE_STYLE nh_conversion_support_style ) {
569 _nh_conversion_support_style = nh_conversion_support_style;
572 private void writeOpenClade( final PhylogenyNode node ) throws IOException {
573 if ( !isSawComma() ) {
574 if ( !node.isRoot() && node.isFirstChildNode() ) {
577 if ( getOutputFormt() == FORMAT.PHYLO_XML ) {
578 getWriter().write( ForesterUtil.LINE_SEPARATOR );
579 if ( isIndentPhyloxml() ) {
580 getWriter().write( createIndentation().toString() );
582 if ( node.isCollapse() ) {
583 PhylogenyDataUtil.appendOpen( getWriter(),
584 PhyloXmlMapping.CLADE,
585 PhyloXmlMapping.NODE_COLLAPSE,
589 PhylogenyDataUtil.appendOpen( getWriter(), PhyloXmlMapping.CLADE );
592 else if ( ( getOutputFormt() == FORMAT.NHX ) || ( getOutputFormt() == FORMAT.NH ) ) {
593 getBuffer().append( "(" );
596 setSawComma( false );
599 private void writeOutput( final Writer writer, final Phylogeny tree ) throws IOException {
600 if ( getOutputFormt() != FORMAT.PHYLO_XML ) {
601 throw new RuntimeException( "method inappropriately called" );
603 if ( tree != null ) {
604 reset( writer, tree );
607 if ( !ForesterUtil.isEmpty( tree.getDistanceUnit() ) ) {
608 unit = tree.getDistanceUnit();
610 if ( !ForesterUtil.isEmpty( tree.getType() ) ) {
611 type = tree.getType();
613 PhylogenyDataUtil.appendOpen( writer,
614 PhyloXmlMapping.PHYLOGENY,
615 PhyloXmlMapping.PHYLOGENY_IS_ROOTED_ATTR,
616 tree.isRooted() + "",
617 PhyloXmlMapping.PHYLOGENY_BRANCHLENGTH_UNIT_ATTR,
619 PhyloXmlMapping.PHYLOGENY_TYPE_ATTR,
621 PhyloXmlMapping.PHYLOGENY_IS_REROOTABLE_ATTR,
622 tree.isRerootable() + "" );
623 appendPhylogenyLevelPhyloXml( writer, tree );
624 while ( isHasNext() ) {
627 writer.write( ForesterUtil.LINE_SEPARATOR );
628 PhylogenyDataUtil.appendClose( writer, PhyloXmlMapping.PHYLOGENY );
632 private void writeToFile( final StringBuffer sb, final File out_file ) throws IOException {
633 if ( out_file.exists() ) {
634 throw new IOException( "attempt to overwrite existing file \"" + out_file.getAbsolutePath() + "\"" );
636 final PrintWriter out = new PrintWriter( new FileWriter( out_file ), true );
637 if ( getOutputFormt() == FORMAT.PHYLO_XML ) {
638 out.print( PHYLO_XML_VERSION_ENCODING_LINE );
639 out.print( ForesterUtil.LINE_SEPARATOR );
640 out.print( PHYLO_XML_NAMESPACE_LINE );
641 out.print( ForesterUtil.LINE_SEPARATOR );
644 if ( getOutputFormt() == FORMAT.PHYLO_XML ) {
645 out.print( ForesterUtil.LINE_SEPARATOR );
646 out.print( PHYLO_XML_END );
652 public static PhylogenyWriter createPhylogenyWriter() {
653 return new PhylogenyWriter();
656 private static void writeNexusStart( final Writer writer ) throws IOException {
657 writer.write( NexusConstants.NEXUS );
658 writer.write( ForesterUtil.LINE_SEPARATOR );
661 public static void writeNexusTaxaBlock( final Writer writer, final Phylogeny tree ) throws IOException {
662 writer.write( NexusConstants.BEGIN_TAXA );
663 writer.write( ForesterUtil.LINE_SEPARATOR );
665 writer.write( NexusConstants.DIMENSIONS );
667 writer.write( NexusConstants.NTAX );
669 writer.write( String.valueOf( tree.getNumberOfExternalNodes() ) );
671 writer.write( ForesterUtil.LINE_SEPARATOR );
673 writer.write( NexusConstants.TAXLABELS );
674 for( final PhylogenyNodeIterator it = tree.iteratorExternalForward(); it.hasNext(); ) {
675 final PhylogenyNode node = it.next();
678 if ( !ForesterUtil.isEmpty( node.getName() ) ) {
679 data = node.getName();
681 else if ( node.getNodeData().isHasTaxonomy() ) {
682 if ( !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getTaxonomyCode() ) ) {
683 data = node.getNodeData().getTaxonomy().getTaxonomyCode();
685 else if ( !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getScientificName() ) ) {
686 data = node.getNodeData().getTaxonomy().getScientificName();
688 else if ( !ForesterUtil.isEmpty( node.getNodeData().getTaxonomy().getCommonName() ) ) {
689 data = node.getNodeData().getTaxonomy().getCommonName();
691 else if ( node.getNodeData().getTaxonomy().getTaxonomyCode() != null ) {
692 data = node.getNodeData().getTaxonomy().getTaxonomyCode();
695 else if ( node.getNodeData().isHasSequence() ) {
696 if ( !ForesterUtil.isEmpty( node.getNodeData().getSequence().getName() ) ) {
697 data = node.getNodeData().getSequence().getName();
700 if ( data.length() > 0 ) {
701 data = data.replaceAll( " ", "_" );
703 writer.write( data );
706 writer.write( ForesterUtil.LINE_SEPARATOR );
707 writer.write( NexusConstants.END );
708 writer.write( ForesterUtil.LINE_SEPARATOR );
711 public static void writeNexusTreesBlock( final Writer writer,
712 final List<Phylogeny> trees,
713 final NH_CONVERSION_SUPPORT_VALUE_STYLE svs ) throws IOException {
714 writer.write( NexusConstants.BEGIN_TREES );
715 writer.write( ForesterUtil.LINE_SEPARATOR );
717 for( final Phylogeny phylogeny : trees ) {
719 writer.write( NexusConstants.TREE );
721 if ( !ForesterUtil.isEmpty( phylogeny.getName() ) ) {
722 writer.write( "\'" );
723 writer.write( phylogeny.getName() );
724 writer.write( "\'" );
727 writer.write( "tree" );
728 writer.write( String.valueOf( i ) );
731 if ( phylogeny.isRooted() ) {
732 writer.write( "[&R]" );
735 writer.write( "[&U]" );
737 writer.write( phylogeny.toNewHampshire( svs ) );
738 writer.write( ForesterUtil.LINE_SEPARATOR );
741 writer.write( NexusConstants.END );
742 writer.write( ForesterUtil.LINE_SEPARATOR );
745 private static void writePhyloXmlEnd( final Writer writer ) throws IOException {
746 writer.write( ForesterUtil.LINE_SEPARATOR );
747 writer.write( PhylogenyWriter.PHYLO_XML_END );
750 private static void writePhyloXmlStart( final Writer writer ) throws IOException {
751 writer.write( PhylogenyWriter.PHYLO_XML_VERSION_ENCODING_LINE );
752 writer.write( ForesterUtil.LINE_SEPARATOR );
753 writer.write( PhylogenyWriter.PHYLO_XML_NAMESPACE_LINE );
754 writer.write( ForesterUtil.LINE_SEPARATOR );
757 public static enum FORMAT {
758 NH, NHX, PHYLO_XML, NEXUS;