/* * TreeModelGenerator.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.beauti.generator; import dr.app.beauti.components.ComponentFactory; import dr.app.beauti.options.AbstractPartitionData; import dr.app.beauti.options.BeautiOptions; import dr.app.beauti.options.PartitionTreeModel; import dr.app.beauti.util.XMLWriter; import dr.evolution.datatype.DataType; import dr.evomodel.tree.TMRCAStatistic; import dr.evomodel.tree.TreeModel; import dr.evomodelxml.coalescent.OldCoalescentSimulatorParser; import dr.evomodelxml.tree.MicrosatelliteSamplerTreeModelParser; import dr.evomodelxml.tree.TMRCAStatisticParser; import dr.evomodelxml.tree.TreeModelParser; import dr.evoxml.MicrosatellitePatternParser; import dr.evoxml.UPGMATreeParser; import dr.inference.model.ParameterParser; import dr.util.Attribute; import dr.xml.XMLParser; /** * @author Alexei Drummond * @author Andrew Rambaut * @author Walter Xie */ public class TreeModelGenerator extends Generator { public TreeModelGenerator(BeautiOptions options, ComponentFactory[] components) { super(options, components); } /** * Write tree model XML block. * * @param model * @param writer the writer */ void writeTreeModel(PartitionTreeModel model, XMLWriter writer) { setModelPrefix(model.getPrefix()); final String treeModelName = modelPrefix + TreeModel.TREE_MODEL; // treemodel.treeModel or treeModel writer.writeComment("Generate a tree model"); writer.writeTag(TreeModel.TREE_MODEL, new Attribute.Default<String>(XMLParser.ID, treeModelName), false); final String STARTING_TREE = InitialTreeGenerator.STARTING_TREE; switch (model.getStartingTreeType()) { case USER: writer.writeIDref("tree", modelPrefix + STARTING_TREE); break; case UPGMA: writer.writeIDref(UPGMATreeParser.UPGMA_TREE, modelPrefix + STARTING_TREE); break; case RANDOM: writer.writeIDref(OldCoalescentSimulatorParser.COALESCENT_TREE, modelPrefix + STARTING_TREE); break; default: throw new IllegalArgumentException("Unknown StartingTreeType"); } writer.writeOpenTag(TreeModelParser.ROOT_HEIGHT); writer.writeTag(ParameterParser.PARAMETER, new Attribute.Default<String>(XMLParser.ID, treeModelName + "." + OldCoalescentSimulatorParser.ROOT_HEIGHT), true); writer.writeCloseTag(TreeModelParser.ROOT_HEIGHT); writer.writeOpenTag(TreeModelParser.NODE_HEIGHTS, new Attribute.Default<String>(TreeModelParser.INTERNAL_NODES, "true")); writer.writeTag(ParameterParser.PARAMETER, new Attribute.Default<String>(XMLParser.ID, treeModelName + "." + "internalNodeHeights"), true); writer.writeCloseTag(TreeModelParser.NODE_HEIGHTS); writer.writeOpenTag(TreeModelParser.NODE_HEIGHTS, new Attribute[]{ new Attribute.Default<String>(TreeModelParser.INTERNAL_NODES, "true"), new Attribute.Default<String>(TreeModelParser.ROOT_NODE, "true") }); writer.writeTag(ParameterParser.PARAMETER, new Attribute.Default<String>(XMLParser.ID, treeModelName + "." + "allInternalNodeHeights"), true); writer.writeCloseTag(TreeModelParser.NODE_HEIGHTS); // int randomLocalClockCount = 0; // int autocorrelatedClockCount = 0; // for (PartitionData pd : model.getDataPartitions()) { // only the PDs linked to this tree model // PartitionClockModel clockModel = pd.getPartitionClockModel(); // switch (clockModel.getClockType()) { // case AUTOCORRELATED_LOGNORMAL: autocorrelatedClockCount += 1; break; // case RANDOM_LOCAL_CLOCK: randomLocalClockCount += 1; break; // } // } // // if (autocorrelatedClockCount > 1 || randomLocalClockCount > 1 || autocorrelatedClockCount + randomLocalClockCount > 1) { // //FAIL // throw new IllegalArgumentException("clock model/tree model combination not implemented by BEAST yet!"); // } // move to validateClockTreeModelCombination(PartitionTreeModel model) // if (autocorrelatedClockCount == 1) { // if (count[0] == 1) { // writer.writeOpenTag(TreeModelParser.NODE_RATES, // new Attribute[]{ // new Attribute.Default<String>(TreeModelParser.ROOT_NODE, "false"), // new Attribute.Default<String>(TreeModelParser.INTERNAL_NODES, "true"), // new Attribute.Default<String>(TreeModelParser.LEAF_NODES, "true") // }); // writer.writeTag(ParameterParser.PARAMETER, // new Attribute.Default<String>(XMLParser.ID, treeModelName + "." + TreeModelParser.NODE_RATES), true); // writer.writeCloseTag(TreeModelParser.NODE_RATES); // // writer.writeOpenTag(TreeModelParser.NODE_RATES, // new Attribute[]{ // new Attribute.Default<String>(TreeModelParser.ROOT_NODE, "true"), // new Attribute.Default<String>(TreeModelParser.INTERNAL_NODES, "false"), // new Attribute.Default<String>(TreeModelParser.LEAF_NODES, "false") // }); // writer.writeTag(ParameterParser.PARAMETER, // new Attribute.Default<String>(XMLParser.ID, // treeModelName + "." + RateEvolutionLikelihood.ROOTRATE), true); // writer.writeCloseTag(TreeModelParser.NODE_RATES); //// } else if (randomLocalClockCount == 1 ) { // } else //+++++++++++++ removed because random local clock XML is changed ++++++++++++++++ // int[] count = validateClockTreeModelCombination(model); // if (count[1] == 1) { // writer.writeOpenTag(TreeModelParser.NODE_RATES, // new Attribute[]{ // new Attribute.Default<String>(TreeModelParser.ROOT_NODE, "false"), // new Attribute.Default<String>(TreeModelParser.INTERNAL_NODES, "true"), // new Attribute.Default<String>(TreeModelParser.LEAF_NODES, "true") // }); // writer.writeTag(ParameterParser.PARAMETER, // new Attribute.Default<String>(XMLParser.ID, modelPrefix + ClockType.LOCAL_CLOCK + ".relativeRates"), true); // writer.writeCloseTag(TreeModelParser.NODE_RATES); // // writer.writeOpenTag(TreeModelParser.NODE_TRAITS, // new Attribute[]{ // new Attribute.Default<String>(TreeModelParser.ROOT_NODE, "false"), // new Attribute.Default<String>(TreeModelParser.INTERNAL_NODES, "true"), // new Attribute.Default<String>(TreeModelParser.LEAF_NODES, "true") // }); // writer.writeTag(ParameterParser.PARAMETER, // new Attribute.Default<String>(XMLParser.ID, modelPrefix + ClockType.LOCAL_CLOCK + ".changes"), true); // writer.writeCloseTag(TreeModelParser.NODE_TRAITS); // } generateInsertionPoint(ComponentGenerator.InsertionPoint.IN_TREE_MODEL, model, writer); writer.writeCloseTag(TreeModel.TREE_MODEL); // if (autocorrelatedClockCount == 1) { // if (count[0] == 1) { // writer.writeText(""); // writer.writeOpenTag(CompoundParameter.COMPOUND_PARAMETER, // new Attribute[]{new Attribute.Default<String>(XMLParser.ID, treeModelName + "." + "allRates")}); // writer.writeIDref(ParameterParser.PARAMETER, treeModelName + "." + TreeModelParser.NODE_RATES); // writer.writeIDref(ParameterParser.PARAMETER, treeModelName + "." + RateEvolutionLikelihood.ROOTRATE); // writer.writeCloseTag(CompoundParameter.COMPOUND_PARAMETER); // } writer.writeComment("Statistic for time of most recent common ancestor of tree"); writer.writeTag(TMRCAStatisticParser.TMRCA_STATISTIC, new Attribute[]{ new Attribute.Default<String>(XMLParser.ID, treeModelName + ".rootAge"), new Attribute.Default<String>(TMRCAStatisticParser.ABSOLUTE, "true") }, false); writer.writeIDref(TreeModel.TREE_MODEL, treeModelName); writer.writeCloseTag(TMRCAStatisticParser.TMRCA_STATISTIC); if (model.getDataType().getType() == DataType.MICRO_SAT) { for (AbstractPartitionData partitionData : options.getDataPartitions(model)) { writer.writeComment("Generate a microsatellite tree model"); writer.writeTag(MicrosatelliteSamplerTreeModelParser.TREE_MICROSATELLITE_SAMPLER_MODEL, new Attribute.Default<String>(XMLParser.ID, partitionData.getName() + "." + MicrosatelliteSamplerTreeModelParser.TREE_MICROSATELLITE_SAMPLER_MODEL), false); writer.writeOpenTag(MicrosatelliteSamplerTreeModelParser.TREE); writer.writeIDref(TreeModel.TREE_MODEL, treeModelName); writer.writeCloseTag(MicrosatelliteSamplerTreeModelParser.TREE); writer.writeOpenTag(MicrosatelliteSamplerTreeModelParser.INTERNAL_VALUES); writer.writeTag(ParameterParser.PARAMETER, new Attribute[]{ new Attribute.Default<String>(XMLParser.ID, partitionData.getName() + "." + MicrosatelliteSamplerTreeModelParser.TREE_MICROSATELLITE_SAMPLER_MODEL + ".internalNodesParameter"), new Attribute.Default<Integer>(ParameterParser.DIMENSION, model.getDimension())}, true); writer.writeCloseTag(MicrosatelliteSamplerTreeModelParser.INTERNAL_VALUES); writer.writeOpenTag(MicrosatelliteSamplerTreeModelParser.EXTERNAL_VALUES); writer.writeIDref(MicrosatellitePatternParser.MICROSATPATTERN, partitionData.getName()); writer.writeCloseTag(MicrosatelliteSamplerTreeModelParser.EXTERNAL_VALUES); writer.writeCloseTag(MicrosatelliteSamplerTreeModelParser.TREE_MICROSATELLITE_SAMPLER_MODEL); } } } }