/*
* GetAncestralSequenceFromSplitTrait.java
*
* Copyright (c) 2002-2015 Alexei Drummond, Andrew Rambaut and Marc Suchard
*
* This file is part of BEAST.
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership and licensing.
*
* BEAST is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* BEAST 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with BEAST; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
package dr.app.tools;
import dr.app.beast.BeastVersion;
import dr.app.util.Arguments;
import dr.app.util.Utils;
import dr.evolution.io.Importer;
import dr.evolution.io.NexusImporter;
import dr.evolution.io.TreeExporter;
import dr.evolution.io.TreeImporter;
import dr.evolution.tree.FlexibleTree;
import dr.inference.trace.TraceException;
import dr.util.Version;
import java.util.*;
import java.io.*;
public class GetAncestralSequenceFromSplitTrait {
private final static Version version = new BeastVersion();
public GetAncestralSequenceFromSplitTrait(String treeAnnotatorFileName, String outputFileName) throws IOException, TraceException {
File outInputFile = new File(treeAnnotatorFileName);
if (outInputFile.isFile()) {
System.out.println("Analysing *.tree file: " + treeAnnotatorFileName);
} else {
System.err.println(treeAnnotatorFileName + " does not exist!");
System.exit(0);
}
if (outputFileName != null) {
FileOutputStream outputStream = new FileOutputStream(outputFileName);
System.setOut(new PrintStream(outputStream));
}
analyze(outInputFile);
}
/**
* Recursively analyzes log files.
*
* @param treeAnnotatorInputFile the file to analyze (if this is a directory then the files within it are analyzed)
* @throws dr.inference.trace.TraceException
* if the trace file is in the wrong format or corrupted
*/
private void analyze(File treeAnnotatorInputFile) throws TraceException {
try {
FileReader fileReader = new FileReader(treeAnnotatorInputFile);
TreeImporter importer = new NexusImporter(fileReader);
FlexibleTree tree = (FlexibleTree) importer.importNextTree();
for(int i = 0; i<tree.getNodeCount(); i++) {
Hashtable<Integer, State> states = new Hashtable<Integer, State>();
for (Iterator<String> j = tree.getNodeAttributeNames(tree.getNode(i)); j.hasNext();) {
String name = j.next();
if(name.indexOf("states_")>=0) {
Integer d = Integer.parseInt(name.replaceFirst("states_", "").replaceFirst("\\..+", ""));
State s; //= new State(name.);
if(states.containsKey(d)) {
s = states.get(d);
}
else {
s = new State(d);
}
// if (tree.getNodeAttribute(tree.getNode(0), name) instanceof Object[]) {
// Object[] o = (Object[]) tree.getNodeAttribute(tree.getNode(0), name);
//
// if(name.matches("states_"+d+".prob")) {
// double[] probabilities = new double[o.length];
// for(int k=0; k<o.length; k++) {
// probabilities[k] = (Double) o[k];
// }
// s.setProbabilities(probabilities);
// }
// else if(name.matches("states_"+d)) {
// String[] set = new String[o.length];
// for(int k=0; k<o.length; k++) {
// set[k] = (String) o[k];
// }
// s.setSet(set);
// }
// }
// else {
if(name.matches("states_"+d+".prob")) {
Object o = tree.getNodeAttribute(tree.getNode(i), name);
double probability = (Double) o;
s.setProbability(probability);
}
else if(name.matches("states_"+d)) {
Object o = tree.getNodeAttribute(tree.getNode(i), name);
String value = (String) o;
s.setState(value.replaceAll("\"", ""));
}
else if(name.matches("states_"+d+".set.prob")) { /* Not necessary but lets parse it anyways */
Object[] o = (Object[]) tree.getNodeAttribute(tree.getNode(i), name);
double[] probabilities = new double[o.length];
for(int k=0; k<o.length; k++) {
probabilities[k] = (Double) o[k];
}
s.setProbabilities(probabilities);
}
else if(name.matches("states_"+d+".set")) { /* Not necessary but lets parse it anyways */
Object[] o = (Object[]) tree.getNodeAttribute(tree.getNode(i), name);
String[] set = new String[o.length];
for(int k=0; k<o.length; k++) {
set[k] = ((String) o[k]).replaceAll("\"", "");
}
s.setSet(set);
}
// }
states.put(d, s);
}
}
State[] statesArray = states.values().toArray(new State[states.size()]);
Arrays.sort(statesArray);
/* Set the default length to the number of characters that it would need */
StringBuffer sb = new StringBuffer(statesArray.length * statesArray[0].getState().length());
for(State s : statesArray) {
sb.append(s.getState());
}
tree.setNodeAttribute(tree.getNode(i), "seq", sb.toString());
}
/* Export the new tree with the new sequences */
TreeExporter exporter = new NexusExporter(System.out);
exporter.exportTree(tree);
System.out.println("Begin trees;");
System.out.println("\ttree max_tree = " + tree.toString());
System.out.println("End;");
} catch (IOException e) {
System.err.println("Error Parsing Input log: " + e.getMessage());
}
catch (Importer.ImportException e) {
System.err.println("Error Parsing Input Tree: " + e.getMessage());
}
}
public static void printTitle() {
System.out.println();
centreLine("GetAncestralSequenceFromSplitTrait " + version.getVersionString() + ", " + version.getDateString(), 60);
centreLine("BAli-Phy MCMC Output analysis", 60);
centreLine("by", 60);
centreLine("Wai Lok Sibon Li and Marc A. Suchard", 60);
System.out.println();
centreLine("David Geffen School of Medicine", 60);
centreLine("University of California, Los Angeles", 60);
centreLine("sibonli@ucla.edu", 60);
centreLine("and", 60);
centreLine("msuchard@ucla.edu",60);
System.out.println();
System.out.println();
}
public static void centreLine(String line, int pageWidth) {
int n = pageWidth - line.length();
int n1 = n / 2;
for (int i = 0; i < n1; i++) {
System.out.print(" ");
}
System.out.println(line);
}
public static void printUsage(Arguments arguments) {
arguments.printUsage("GetAncestralSequenceFromSplitTrait", "[<*.tree file-name> [<output-file-name>]]");
System.out.println();
System.out.println(" Example: ...");
System.out.println(" Example: ...");
System.out.println();
}
//Main method
public static void main(String[] args) throws IOException, TraceException {
printTitle();
Arguments arguments = new Arguments(
new Arguments.Option[]{
new Arguments.Option("help", "option to print this message")
});
try {
arguments.parseArguments(args);
} catch (Arguments.ArgumentException ae) {
System.out.println(ae);
printUsage(arguments);
System.exit(1);
}
if (arguments.hasOption("help")) {
printUsage(arguments);
System.exit(0);
}
String outInputFileName = null;
String outputFileName = null;
String[] args2 = arguments.getLeftoverArguments();
if (args2.length > 2) {
System.err.println("Unknown option: " + args2[2]);
System.err.println();
printUsage(arguments);
System.exit(1);
}
if (args2.length > 0) {
outInputFileName = args2[0];
}
if (args2.length > 1) {
outputFileName = args2[1];
}
if (outInputFileName == null) {
// No input file name was given so throw up a dialog box...
outInputFileName = Utils.getLoadFileName("GetAncestralSequenceFromSplitTrait " + version.getVersionString() + " - Select *.tree file to analyse");
}
new GetAncestralSequenceFromSplitTrait(outInputFileName, outputFileName);
System.exit(0);
}
private class State implements Comparable<State> {
private State(int stateIndex) {
this.stateIndex = stateIndex;
}
private int stateIndex;
private String[] set;
private double[] probabilities;
private String state;
private double probability;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public double getProbability() {
return probability;
}
public void setProbability(double probability) {
this.probability = probability;
}
public int getStateIndex() {
return stateIndex;
}
public void setStateIndex(int stateIndex) {
this.stateIndex = stateIndex;
}
public String[] getSet() {
return set;
}
public void setSet(String[] set) {
this.set = set;
}
public double[] getProbabilities() {
return probabilities;
}
public void setProbabilities(double[] probabilities) {
this.probabilities = probabilities;
}
public int compareTo(State o) {
return this.getStateIndex()-o.getStateIndex();
}
// public String getMaxProbState() {
// if(set.length != probabilities.length) {
// throw new RuntimeException("Set and probabilities arrays are not the same length: " + set.length +
// ", " + probabilities.length + ". State: " + getStateIndex());
// }
// if(set.length ==0 || probabilities.length ==0) {
// throw new RuntimeException("Array lengths are zero");
// }
// double max = 0;
// int maxIndex =0;
// for(int i=0; i<probabilities.length; i++) {
// if(probabilities[i]>max) {
// maxIndex=i;
// }
// }
// return set[maxIndex];
// }
}
}