/*
Copyright (C) 2009 Diego Darriba
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package es.uvigo.darwin.prottest.util.fileio;
import es.uvigo.darwin.prottest.tree.TreeUtils;
import es.uvigo.darwin.prottest.util.exception.ProtTestInternalException;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import pal.tree.Tree;
/**
*
* @author Diego Darriba
*/
public class NexusExporter {
private static final String HEADER = "#NEXUS";
private File outFile;
private PrintWriter outputWriter;
private enum NexusBlock {
TAXA {
public void beginSection(PrintWriter outputWriter) {
outputWriter.println("begin taxa;");
}
public void endSection(PrintWriter outputWriter) {
outputWriter.println("end taxa;");
}
public String getSectionName() {
return "taxa";
}
public void export(PrintWriter outputWriter, List taxa, Properties properties) {
}
},
TREES {
public void beginSection(PrintWriter outputWriter) {
outputWriter.println("begin trees;");
}
public void endSection(PrintWriter outputWriter) {
outputWriter.println("end trees;");
}
public String getSectionName() {
return "trees";
}
public void export(PrintWriter outputWriter, List trees, Properties properties) {
printBlankLine(outputWriter);
for (Object o : trees) {
if (!(o instanceof Tree)) {
throw new TypeMismatchException(Tree.class, o.getClass());
}
Tree tree = (Tree) o;
boolean printCladeSupport = properties.getProperty(PRINT_CLADE_SUPPORT, "false").equalsIgnoreCase("true");
String treeName = (String) tree.getAttribute(tree.getRoot(), TreeUtils.TREE_NAME_ATTRIBUTE);
String treeNewick = TreeUtils.toNewick(tree, true, true, printCladeSupport);
outputWriter.print(" " + treeName + " = ");
outputWriter.println(treeNewick);
}
printBlankLine(outputWriter);
}
},
CONSENSUS {
public void beginSection(PrintWriter outputWriter) {
TREES.beginSection(outputWriter);
}
public void endSection(PrintWriter outputWriter) {
TREES.endSection(outputWriter);
}
public void export(PrintWriter outputWriter, List trees, Properties properties) {
printBlankLine(outputWriter);
String fullTreeComment = "Note: This tree contains information on the topology," +
" branch lengths (if present), and the probability " +
" of the partition indicated by the branch.";
addComment(outputWriter, fullTreeComment, 0);
properties.setProperty(PRINT_CLADE_SUPPORT, "true");
TREES.export(outputWriter, trees, properties);
String simpleTreeComment = "Note: This tree contains information only on the topology" +
" and branch lengths (mean of the posterior probability density).";
addComment(outputWriter, simpleTreeComment, 0);
properties.setProperty(PRINT_CLADE_SUPPORT, "false");
TREES.export(outputWriter, trees, properties);
printBlankLine(outputWriter);
}
},
DEFAULT {
public void beginSection(PrintWriter outputWriter) {
throw new UndefinedBlockException();
}
public void endSection(PrintWriter outputWriter) {
throw new UndefinedBlockException();
}
public void export(PrintWriter outputWriter, List objects, Properties properties) {
throw new UndefinedBlockException();
}
};
public static final String PRINT_CLADE_SUPPORT = "pcs";
public void addComment(PrintWriter outputWriter, String comment, int lineWidth) {
comment = "[" + comment + "] ";
int commentLength = comment.length();
if (lineWidth <= 0) {
lineWidth = comment.length();
}
int column = 0;
while (column < commentLength) {
String toWrite;
if (column + lineWidth + 1 < comment.length()) {
toWrite = comment.substring(column, column + lineWidth + 1);
} else {
toWrite = comment.substring(column);
}
int toWriteLength = toWrite.lastIndexOf(" ");
if (toWriteLength > 0 && toWriteLength < toWrite.length()) {
outputWriter.println(toWrite.substring(0, toWriteLength));
} else {
toWriteLength = lineWidth;
outputWriter.println(toWrite);
}
column += toWriteLength;
}
}
public void printBlankLine(PrintWriter outputWriter) {
outputWriter.println(" ");
}
public abstract void beginSection(PrintWriter outputWriter);
public abstract void endSection(PrintWriter outputWriter);
public abstract void export(PrintWriter outputWriter, List objects, Properties properties);
private static class TypeMismatchException extends ProtTestInternalException {
public TypeMismatchException(Class classRequired, Class classObtained) {
super("Required class " + classRequired + " but obtained " + classObtained);
}
}
private static class UndefinedBlockException extends ProtTestInternalException {
public UndefinedBlockException() {
super("No Nexus block is defined");
}
}
}
public NexusExporter(File outFile) throws IOException {
this.outFile = outFile;
if (!outFile.exists()) {
outFile.createNewFile();
}
this.outputWriter = new PrintWriter(outFile);
initStructure(this.outputWriter);
}
public void printTreeBlock(List<Tree> trees) {
NexusBlock treeBlock = NexusBlock.TREES;
treeBlock.beginSection(outputWriter);
treeBlock.export(outputWriter, trees, new Properties());
treeBlock.endSection(outputWriter);
}
public void printConsensusBlock(Tree tree, String id) {
NexusBlock treeBlock = NexusBlock.CONSENSUS;
List<Tree> trees = new ArrayList<Tree>();
trees.add(tree);
if (id != null) {
treeBlock.addComment(outputWriter, id, 0);
}
treeBlock.beginSection(outputWriter);
treeBlock.export(outputWriter, trees, new Properties());
treeBlock.endSection(outputWriter);
}
public void printComment(String msg, int colWidth) {
NexusBlock.DEFAULT.addComment(outputWriter, msg, colWidth);
}
public void close() {
outputWriter.close();
}
private void initStructure(PrintWriter outputWriter) {
outputWriter.println(HEADER);
outputWriter.println(" ");
}
}