/* * CoalGenApp.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.coalgen; import dr.evolution.io.Importer; import dr.inference.trace.LogFileTraces; import dr.inference.trace.TraceException; import jam.framework.SingleDocApplication; import jebl.evolution.coalescent.EmpiricalDemographicFunction; import jebl.evolution.graphs.Node; import jebl.evolution.io.ImportException; import jebl.evolution.io.NewickExporter; import jebl.evolution.io.NexusImporter; import jebl.evolution.io.TreeImporter; import jebl.evolution.taxa.Taxon; import jebl.evolution.trees.RootedTree; import jebl.evolution.treesimulation.CoalescentIntervalGenerator; import jebl.evolution.treesimulation.IntervalGenerator; import jebl.evolution.treesimulation.TreeSimulator; import javax.swing.*; import java.io.*; import java.util.Arrays; /** * @author Andrew Rambaut * @author Alexei Drummond * @version $Id$ */ public class CoalGenApp { public CoalGenApp() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); java.net.URL url = CoalGenApp.class.getResource("/images/CoalGen.png"); Icon icon = null; if (url != null) { icon = new ImageIcon(url); } String nameString = "CoalGen"; String aboutString = "Coalescent Tree Simulator\nVersion 2.0\n \nCopyright 2004-2009 Andrew Rambaut and Alexei Drummond\nAll Rights Reserved."; SingleDocApplication app = new SingleDocApplication(new CoalGenMenuFactory(), nameString, aboutString, icon); CoalGenFrame frame = new CoalGenFrame(nameString); app.setDocumentFrame(frame); } catch (Exception e) { e.printStackTrace(); } } public static void simulate(String inputFileName, String treesFileName, String outputFileName) throws IOException, TraceException, Importer.ImportException { File logFile = new File(inputFileName); System.out.println("Loading trace file: " + inputFileName); LogFileTraces traces = new LogFileTraces(inputFileName, logFile); traces.loadTraces(); traces.setBurnIn(0); System.out.println(traces.getStateCount() + " states loaded"); System.out.println(); System.out.println("Opening trees file: " + treesFileName); // BufferedReader reader = new BufferedReader(new FileReader(treesFileName)); System.out.println("Simulating..."); System.out.println("0 25 50 75 100"); System.out.println("|--------------|--------------|--------------|--------------|"); int stepSize = traces.getStateCount() / 60; if (stepSize < 1) stepSize = 1; PrintWriter writer = new PrintWriter(new FileWriter(outputFileName)); FileReader fileReader = new FileReader(treesFileName); TreeImporter importer = new NexusImporter(fileReader); EmpiricalDemographicFunction demo = null; IntervalGenerator intervals = null; TreeSimulator sim = null; CoalGenData data = new CoalGenData(); data.traces = traces; data.setDemographicModel(7); // const stepwise bsp data.setupSkyline(); double[] popSizes = new double[data.popSizeCount]; double[] groupSizes = new double[data.groupSizeCount]; NewickExporter exporter = new NewickExporter(writer); int count = 0; try { while (importer.hasTree()) { RootedTree inTree = (RootedTree)importer.importNextTree(); if (sim == null) { setSamplingTimes(inTree); sim = new TreeSimulator(inTree.getTaxa(), "date"); } data.getNextSkyline(popSizes, groupSizes); double[] times = getTimes(inTree, groupSizes); demo = new EmpiricalDemographicFunction(popSizes, times, true); intervals = new CoalescentIntervalGenerator(demo); RootedTree outTree = sim.simulate(intervals); exporter.exportTree(outTree); writer.println(); writer.flush(); if (count > 0 && count % stepSize == 0) { System.out.print("*"); System.out.flush(); } count++; } } catch (ImportException e) { e.printStackTrace(); } fileReader.close(); writer.close(); } private static void setSamplingTimes(final RootedTree tree) { setSamplingTimes(tree, tree.getRootNode(), 0.0); // the dates are distances from root so make them heights double maxLength = 0.0; for (Taxon taxon : tree.getTaxa()) { double length = (Double)taxon.getAttribute("length"); if (length > maxLength) { maxLength = length; } } for (Taxon taxon : tree.getTaxa()) { double length = (Double)taxon.getAttribute("length"); taxon.setAttribute("date", maxLength - length); } } private static void setSamplingTimes(final RootedTree tree, final Node node, double length) { if (tree.isExternal(node)) { tree.getTaxon(node).setAttribute("length", length); } else { for (Node child : tree.getChildren(node)) { double l = tree.getLength(child); setSamplingTimes(tree, child, length + l); } } } private static double[] getTimes(final RootedTree tree, final double[] groupSizes) { double[] heights = new double[tree.getInternalNodes().size()]; int i = 0; for (Node node : tree.getInternalNodes()) { heights[i] = tree.getHeight(node); i++; } Arrays.sort(heights); if (groupSizes != null) { double[] allHeights = heights; heights = new double[groupSizes.length]; int k = 0; for (int j = 0; j < groupSizes.length; j++) { k += groupSizes[j]; heights[j] = allHeights[k - 1]; } } return heights; } // Main entry point static public void main(String[] args) { if (args.length > 1) { if (args.length != 3) { System.err.println("Usage: coalgen <input_file> <tree_file> <output_file>"); return; } String inputFileName = args[0]; String treeFileName = args[1]; String outputFileName = args[2]; try { CoalGenApp.simulate(inputFileName, treeFileName, outputFileName); } catch (IOException e) { e.printStackTrace(); } catch (TraceException e) { e.printStackTrace(); } catch (Importer.ImportException e) { e.printStackTrace(); } } else { System.setProperty("com.apple.macos.useScreenMenuBar", "true"); System.setProperty("apple.laf.useScreenMenuBar", "true"); new CoalGenApp(); } } }