/* * XMLGenerator.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.bss; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import dr.evolution.tree.TreeUtils; import dr.evomodelxml.substmodel.MG94CodonModelParser; import dr.evomodel.substmodel.aminoacid.AminoAcidModelType; import dr.evomodel.substmodel.nucleotide.NucModelType; import dr.app.beagle.tools.parsers.BeagleSequenceSimulatorParser; import dr.app.beagle.tools.parsers.PartitionParser; import dr.app.beauti.util.XMLWriter; import dr.evolution.datatype.AminoAcids; import dr.evolution.datatype.DataType; import dr.evolution.util.Taxa; import dr.evolution.util.Taxon; import dr.oldevomodel.sitemodel.SiteModel; import dr.evomodel.tree.TreeModel; import dr.evomodelxml.branchratemodel.DiscretizedBranchRatesParser; import dr.evomodelxml.branchratemodel.StrictClockBranchRatesParser; import dr.evomodelxml.coalescent.CoalescentSimulatorParser; import dr.evomodelxml.coalescent.ConstantPopulationModelParser; import dr.evomodelxml.coalescent.ExponentialGrowthModelParser; import dr.oldevomodelxml.sitemodel.GammaSiteModelParser; import dr.oldevomodelxml.substmodel.EmpiricalAminoAcidModelParser; import dr.oldevomodelxml.substmodel.FrequencyModelParser; import dr.oldevomodelxml.substmodel.GTRParser; import dr.oldevomodelxml.substmodel.HKYParser; import dr.oldevomodelxml.substmodel.TN93Parser; import dr.oldevomodelxml.substmodel.YangCodonModelParser; import dr.evomodelxml.tree.TreeModelParser; import dr.evoxml.NewickParser; import dr.evoxml.SequenceParser; import dr.evoxml.TaxaParser; import dr.evoxml.TaxonParser; import dr.evoxml.util.XMLUnits; import dr.inference.distribution.ExponentialDistributionModel; import dr.inference.model.ParameterParser; import dr.inferencexml.distribution.DistributionModelParser; import dr.inferencexml.distribution.InverseGaussianDistributionModelParser; import dr.inferencexml.distribution.LogNormalDistributionModelParser; import dr.util.Attribute; import dr.xml.Report; import dr.xml.XMLParser; /** * @author Filip Bielejec * @version $Id$ */ public class XMLGenerator { private PartitionDataList dataList; public XMLGenerator(PartitionDataList dataList) { this.dataList = dataList; }// END: Constructor public void generateXML(File file) throws IOException { XMLWriter writer = new XMLWriter(new BufferedWriter( new FileWriter(file))); // ////////////// // ---header---// // ////////////// writer.writeText("<?xml version=\"1.0\" standalone=\"yes\"?>"); writer.writeComment("Generated by " + BeagleSequenceSimulatorApp.LONG_NAME + " " + BeagleSequenceSimulatorApp.VERSION); writer.writeOpenTag("beast"); writer.writeBlankLine(); // //////////////////// // ---taxa element---// // //////////////////// try { int suffix = 1; ArrayList<Taxa> taxaList = new ArrayList<Taxa>(); for (PartitionData data : dataList) { if (data.record == null) { throw new RuntimeException("Set Tree Model in Partitions tab for " + suffix + " partition."); } else { Taxa taxa = null; if (data.demographicModelIndex == 0 && data.record.isTreeSet()) { taxa = new Taxa(data.record.getTree().asList()); } else if (data.demographicModelIndex == 0 && data.record.isTaxaSet()) { throw new RuntimeException("Data and demographic model incompatible for partition " + suffix); } else if( (data.demographicModelIndex > 0 && data.demographicModelIndex <= PartitionData.lastImplementedIndex) && data.record.isTreeSet()) { taxa = new Taxa(data.record.getTree().asList()); } else if((data.demographicModelIndex > 0 && data.demographicModelIndex <= PartitionData.lastImplementedIndex) && data.record.isTaxaSet()) { taxa = data.record.getTaxa(); } else { // }// END: demo model check if (taxaList.size() == 0 | !Utils.isTaxaInList(taxa, taxaList) ) { data.taxaIdref += suffix; writeTaxa(taxa, writer, String.valueOf(suffix)); writer.writeBlankLine(); taxaList.add(taxa); // System.out.println("NOT IN LIST"); } else { int index = Utils.taxaIsIdenticalWith(taxa, taxaList) + 1; data.taxaIdref += index; // System.out.println("IDENTICAL WITH " + index); } }// END: treeModel set check suffix++; }// END: partition loop } catch (Exception e) { throw new RuntimeException("Taxa generation has failed:\n" + e.getMessage()); }// END: try-catch block // //////////////////////// // ---topology element---// // //////////////////////// try { int suffix = 1; ArrayList<TreeModel> treeModelList = new ArrayList<TreeModel>(); for (PartitionData data : dataList) { if (data.demographicModelIndex == 0) { TreeModel treeModel = data.createTreeModel(); if (treeModelList.size() == 0 | !Utils.isTreeModelInList(treeModel, treeModelList)) { data.treeModelIdref += suffix; writeNewick(treeModel, writer, String.valueOf(suffix)); writer.writeBlankLine(); treeModelList.add(treeModel); } else { int index = Utils.treeModelIsIdenticalWith(treeModel, treeModelList) + 1; data.treeModelIdref += index; }// END: list check } else if(data.demographicModelIndex > 0 && data.demographicModelIndex <= PartitionData.lastImplementedIndex){ data.demographicModelIdref += suffix; data.treeModelIdref += suffix; writeDemographicModel(data, writer, String.valueOf(suffix)); writer.writeBlankLine(); } else { // throw exception }// END: demo model check suffix++; }// END: partition loop } catch (Exception e) { throw new RuntimeException("Topology generation has failed:\n" + e.getMessage()); }// END: try-catch block // ////////////////////////// // ---tree model element---// // ////////////////////////// try { int suffix = 1; ArrayList<TreesTableRecord> recordsList = new ArrayList<TreesTableRecord>(); for (PartitionData data : dataList) { TreesTableRecord record = data.record; if (recordsList.size() == 0 | !Utils.isRecordInList(record, recordsList)) { writeTreeModel(writer, String.valueOf(suffix)); writer.writeBlankLine(); recordsList.add(record); } suffix++; }// END: partition loop } catch (Exception e) { throw new RuntimeException("Tree model generation has failed:\n" + e.getMessage()); }// END: try-catch block // ////////////////////////////////// // ---branch rates model element---// // ////////////////////////////////// try { int suffix = 1; ArrayList<PartitionData> partitionList = new ArrayList<PartitionData>(); for (PartitionData data : dataList) { if (partitionList.size() == 0 | !Utils.isElementInList(data, partitionList, Utils.BRANCH_RATE_MODEL_ELEMENT)) { data.clockModelIdref += suffix; writeBranchRatesModel(data, writer, String.valueOf(suffix)); writer.writeBlankLine(); partitionList.add(data); // System.out.println("NOT IN LIST"); } else { int index = Utils.isIdenticalWith(data, partitionList, Utils.BRANCH_RATE_MODEL_ELEMENT) + 1; data.clockModelIdref += index; // System.out.println("IDENTICAL WITH " + index); } suffix++; }// END: partition loop } catch (Exception e) { throw new RuntimeException("Clock model generation has failed:\n" + e.getMessage()); }// END: try-catch block // /////////////////////////////// // ---frequency model element---// // /////////////////////////////// try { int suffix = 1; ArrayList<PartitionData> partitionList = new ArrayList<PartitionData>(); for (PartitionData data : dataList) { if (partitionList.size() == 0 | !Utils.isElementInList(data, partitionList, Utils.FREQUENCY_MODEL_ELEMENT)) { data.frequencyModelIdref += suffix; writeFrequencyModel(data, writer); writer.writeBlankLine(); partitionList.add(data); // System.out.println("NOT IN LIST"); } else { int index = Utils.isIdenticalWith(data, partitionList, Utils.FREQUENCY_MODEL_ELEMENT) + 1; data.frequencyModelIdref += index; // System.out.println("IDENTICAL WITH " + index); } suffix++; }// END: partition loop } catch (Exception e) { throw new RuntimeException( "Frequency model generation has failed:\n" + e.getMessage()); }// END: try-catch block // //////////////////////////// // ---branch model element---// // //////////////////////////// try { int suffix = 1; ArrayList<PartitionData> partitionList = new ArrayList<PartitionData>(); for (PartitionData data : dataList) { if (partitionList.size() == 0 | !Utils.isElementInList(data, partitionList, Utils.BRANCH_MODEL_ELEMENT)) { data.substitutionModelIdref += suffix; writeBranchModel(data, writer, String.valueOf(suffix)); writer.writeBlankLine(); partitionList.add(data); } else { int index = Utils.isIdenticalWith(data, partitionList, Utils.BRANCH_MODEL_ELEMENT) + 1; data.substitutionModelIdref += index; } suffix++; }// END: partition loop } catch (Exception e) { throw new RuntimeException("Branch model generation has failed:\n" + e.getMessage()); }// END: try-catch block // /////////////////////////////// // ---site rate model element---// // /////////////////////////////// try { int suffix = 1; ArrayList<PartitionData> partitionList = new ArrayList<PartitionData>(); for (PartitionData data : dataList) { if (partitionList.size() == 0 | !Utils.isElementInList(data, partitionList, Utils.SITE_RATE_MODEL_ELEMENT)) { data.siteRateModelIdref += suffix; writeSiteRateModel(data, writer, suffix); writer.writeBlankLine(); partitionList.add(data); } else { int index = Utils.isIdenticalWith(data, partitionList, Utils.SITE_RATE_MODEL_ELEMENT) + 1; data.siteRateModelIdref += index; } suffix++; }// END: partition loop } catch (Exception e) { System.err.println(e); throw new RuntimeException( "Site rate model generation has failed:\n" + e.getMessage()); }// END: try-catch block // ///////////////////////////////////////// // ---beagle sequence simulator element---// // ///////////////////////////////////////// try { writeBeagleSequenceSimulator(writer); writer.writeBlankLine(); } catch (Exception e) { throw new RuntimeException( "Beagle Sequence Simulator element generation has failed:\n" + e.getMessage()); }// END: try-catch block // ////////////////////// // ---report element---// // ////////////////////// try { writeReport(writer); writer.writeBlankLine(); } catch (Exception e) { System.err.println(e); throw new RuntimeException( "Report element generation has failed:\n" + e.getMessage()); }// END: try-catch block writer.writeCloseTag("beast"); writer.flush(); writer.close(); // reset all idrefs for (PartitionData data : dataList) { data.resetIdrefs(); } }// END: generateXML private void writeBeagleSequenceSimulator(XMLWriter writer) { writer.writeOpenTag( BeagleSequenceSimulatorParser.BEAGLE_SEQUENCE_SIMULATOR, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, "simulator"), // new Attribute.Default<String>( BeagleSequenceSimulatorParser.PARALLEL, String .valueOf(dataList.useParallel)), // new Attribute.Default<String>( BeagleSequenceSimulatorParser.OUTPUT, String .valueOf(dataList.outputFormat)) }); int suffix = 1; for (PartitionData data : dataList) { writer.writeOpenTag( PartitionParser.PARTITION, new Attribute[] { new Attribute.Default<String>(PartitionParser.FROM, String.valueOf(data.from)), new Attribute.Default<String>(PartitionParser.TO, String.valueOf(data.to)), new Attribute.Default<String>( PartitionParser.EVERY, String .valueOf(data.every)) }); writer.writeIDref(TreeModel.TREE_MODEL, data.treeModelIdref); int substitutionModelIndex = data.substitutionModelIndex; switch (substitutionModelIndex) { case 0: // HKY writer.writeIDref(NucModelType.HKY.getXMLName(), data.substitutionModelIdref); break; case 1: // GTR writer.writeIDref(GTRParser.GTR_MODEL, data.substitutionModelIdref); break; case 2: // TN93 writer.writeIDref(NucModelType.TN93.getXMLName(), data.substitutionModelIdref); break; case 3: // Yang Codon Model writer.writeIDref(YangCodonModelParser.YANG_CODON_MODEL, data.substitutionModelIdref); break; case 4: // Blosum62 writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 5: // CPREV writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 6: // Dayhoff writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 7: // FLU writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 8: // JTT writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 9: // LG writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 10: // MTREV writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 11: // WAG writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; }// END: switch writer.writeIDref(SiteModel.SITE_MODEL, data.siteRateModelIdref); int clockModel = data.clockModelIndex; switch (clockModel) { case 0: // StrictClock writer.writeIDref( StrictClockBranchRatesParser.STRICT_CLOCK_BRANCH_RATES, data.clockModelIdref); break; case 1: // LognormalRelaxedClock writer.writeIDref( DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES, data.clockModelIdref); break; case 2: // ExponentialRelaxedClock writer.writeIDref( DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES, data.clockModelIdref); break; }// END: switch writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); if (data.ancestralSequenceString != null) { writeAncestralSequence(data, writer, suffix); } writer.writeCloseTag(PartitionParser.PARTITION); suffix++; }// END: partitions loop writer.writeCloseTag(BeagleSequenceSimulatorParser.BEAGLE_SEQUENCE_SIMULATOR); }// END: writeBeagleSequenceSimulator private void writeAncestralSequence(PartitionData data, XMLWriter writer, int suffix) { writer.writeOpenTag(SequenceParser.SEQUENCE); writer.writeTag( TaxonParser.TAXON, // tagname new Attribute[] { // attributes[] new Attribute.Default<String>(XMLParser.ID, Utils.ANCESTRAL_SEQUENCE + suffix) }, true // close ); writer.write (data.ancestralSequenceString + "\n"); writer.writeCloseTag(SequenceParser.SEQUENCE); }//END: writeAncestralSequence private void writeNewick(TreeModel tree, XMLWriter writer, String suffix) { writer.writeOpenTag(NewickParser.NEWICK, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, Utils.TOPOLOGY + suffix), // new Attribute.Default<String>(NewickParser.USING_DATES, "false"), // new Attribute.Default<String>(NewickParser.USING_HEIGHTS, "true") // }); writer.writeText(TreeUtils.newick(tree)); writer.writeCloseTag(NewickParser.NEWICK); }// END: writeNewick private void writeDemographicModel(PartitionData data, XMLWriter writer, String suffix) { int demographicModel = data.demographicModelIndex; switch (demographicModel) { case 0: // NoModel // do nothing break; case 1: // Constant Population writer.writeOpenTag( ConstantPopulationModelParser.CONSTANT_POPULATION_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, Utils.DEMOGRAPHIC_MODEL + suffix // data.demographicModelIdref ), new Attribute.Default<String>(XMLUnits.UNITS, XMLUnits.YEARS) }); writeParameter(ConstantPopulationModelParser.POPULATION_SIZE, "constant.popSize" + suffix, 1, String.valueOf(data.demographicParameterValues[0]), writer); writer.writeCloseTag(ConstantPopulationModelParser.CONSTANT_POPULATION_MODEL); writer.writeBlankLine(); writer.writeOpenTag( CoalescentSimulatorParser.COALESCENT_SIMULATOR, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, Utils.TOPOLOGY + suffix) }); writer.writeIDref(TaxaParser.TAXA, data.taxaIdref); writer.writeIDref(ConstantPopulationModelParser.CONSTANT_POPULATION_MODEL, data.demographicModelIdref); writer.writeCloseTag(CoalescentSimulatorParser.COALESCENT_SIMULATOR); break; case 2: // Exponential Growth (Growth Rate) writer.writeOpenTag( ExponentialGrowthModelParser.EXPONENTIAL_GROWTH_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.demographicModelIdref), new Attribute.Default<String>(XMLUnits.UNITS, XMLUnits.YEARS) }); writeParameter(ExponentialGrowthModelParser.POPULATION_SIZE, "exponential.popSize" + suffix, 1, String.valueOf(data.demographicParameterValues[1]), writer); writeParameter(ExponentialGrowthModelParser.GROWTH_RATE, "exponential.growthRate" + suffix, 1, String.valueOf(data.demographicParameterValues[2]), writer); writer.writeCloseTag(ExponentialGrowthModelParser.EXPONENTIAL_GROWTH_MODEL); writer.writeBlankLine(); writer.writeOpenTag( CoalescentSimulatorParser.COALESCENT_SIMULATOR, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, Utils.TOPOLOGY + suffix) }); writer.writeIDref(TaxaParser.TAXA, TaxaParser.TAXA); writer.writeIDref(ExponentialGrowthModelParser.EXPONENTIAL_GROWTH_MODEL, data.demographicModelIdref); writer.writeCloseTag(CoalescentSimulatorParser.COALESCENT_SIMULATOR); break; case 3: // Exponential Growth (Doubling Time) writer.writeOpenTag( ExponentialGrowthModelParser.EXPONENTIAL_GROWTH_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.demographicModelIdref), new Attribute.Default<String>(XMLUnits.UNITS, XMLUnits.YEARS) }); writeParameter(ExponentialGrowthModelParser.POPULATION_SIZE, "exponential.popSize" + suffix, 1, String.valueOf(data.demographicParameterValues[3]), writer); writeParameter(ExponentialGrowthModelParser.DOUBLING_TIME, "exponential.doublingTime" + suffix, 1, String.valueOf(data.demographicParameterValues[4]), writer); writer.writeCloseTag(ExponentialGrowthModelParser.EXPONENTIAL_GROWTH_MODEL); writer.writeBlankLine(); writer.writeOpenTag( CoalescentSimulatorParser.COALESCENT_SIMULATOR, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, Utils.TOPOLOGY + suffix) }); writer.writeIDref(TaxaParser.TAXA, TaxaParser.TAXA); writer.writeIDref(ExponentialGrowthModelParser.EXPONENTIAL_GROWTH_MODEL, data.demographicModelIdref); writer.writeCloseTag(CoalescentSimulatorParser.COALESCENT_SIMULATOR); break; // case 4: // Logistic Growth (Growth Rate) }// END: switch }// END: writeDemographicModel private void writeBranchRatesModel(PartitionData data, XMLWriter writer, String suffix) { double numberOfBranches = 0; int clockModel = data.clockModelIndex; switch (clockModel) { case 0: // StrictClock writer.writeOpenTag( StrictClockBranchRatesParser.STRICT_CLOCK_BRANCH_RATES, new Attribute[] { new Attribute.Default<String>( XMLParser.ID, data.clockModelIdref) }); writeParameter(StrictClockBranchRatesParser.RATE, PartitionData.clockParameterNames[0] + suffix, 1, String.valueOf(data.clockParameterValues[0]), writer); writer.writeCloseTag(StrictClockBranchRatesParser.STRICT_CLOCK_BRANCH_RATES); break; case 1: // Lognormal relaxed clock writer.writeOpenTag( DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.clockModelIdref), new Attribute.Default<String>( DiscretizedBranchRatesParser.RANDOMIZE_RATES, "true") } ); writer.writeIDref(TreeModel.TREE_MODEL, data.treeModelIdref); writer.writeOpenTag(DiscretizedBranchRatesParser.DISTRIBUTION); writer.writeOpenTag( LogNormalDistributionModelParser.LOGNORMAL_DISTRIBUTION_MODEL, new Attribute[] { new Attribute.Default<String>( LogNormalDistributionModelParser.OFFSET, String.valueOf(data.clockParameterValues[3]) ), new Attribute.Default<String>( LogNormalDistributionModelParser.MEAN_IN_REAL_SPACE, "false"), new Attribute.Default<String>( LogNormalDistributionModelParser.STDEV_IN_REAL_SPACE, "false") }); writeParameter(LogNormalDistributionModelParser.MEAN, PartitionData.clockParameterNames[1] + suffix, 1, String.valueOf(data.clockParameterValues[1]), writer); writeParameter(LogNormalDistributionModelParser.STDEV, PartitionData.clockParameterNames[2] + suffix, 1, String.valueOf(data.clockParameterValues[2]), writer); writer.writeCloseTag(LogNormalDistributionModelParser.LOGNORMAL_DISTRIBUTION_MODEL); writer.writeCloseTag(DiscretizedBranchRatesParser.DISTRIBUTION); numberOfBranches = 2 * (data.createTreeModel().getTaxonCount() - 1); writeParameter(DiscretizedBranchRatesParser.RATE_CATEGORIES, "branchRates.categories" + suffix, (int) numberOfBranches, null, writer); writer.writeCloseTag(DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES); break; case 2: // Exponential relaxed clock writer.writeOpenTag( DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.clockModelIdref), new Attribute.Default<String>( DiscretizedBranchRatesParser.RANDOMIZE_RATES, "true") } ); writer.writeIDref(TreeModel.TREE_MODEL, data.treeModelIdref); writer.writeOpenTag(DiscretizedBranchRatesParser.DISTRIBUTION); writer.writeOpenTag( ExponentialDistributionModel.EXPONENTIAL_DISTRIBUTION_MODEL, new Attribute[] { new Attribute.Default<String>( LogNormalDistributionModelParser.OFFSET, String.valueOf(data.clockParameterValues[5]) ), new Attribute.Default<String>( LogNormalDistributionModelParser.MEAN_IN_REAL_SPACE, "true") }); writeParameter(DistributionModelParser.MEAN, PartitionData.clockParameterNames[4] + suffix, 1, String.valueOf(data.clockParameterValues[4]), writer); writer.writeCloseTag(ExponentialDistributionModel.EXPONENTIAL_DISTRIBUTION_MODEL); writer.writeCloseTag(DiscretizedBranchRatesParser.DISTRIBUTION); numberOfBranches = 2 * (data.createTreeModel().getTaxonCount() - 1); writeParameter(DiscretizedBranchRatesParser.RATE_CATEGORIES, "branchRates.categories" + suffix, (int) numberOfBranches, null, writer); writer.writeCloseTag(DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES); break; case 3: // Inverse Gaussian writer.writeOpenTag( DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.clockModelIdref), new Attribute.Default<String>( DiscretizedBranchRatesParser.RANDOMIZE_RATES, "true") } ); writer.writeIDref(TreeModel.TREE_MODEL, data.treeModelIdref); writer.writeOpenTag(DiscretizedBranchRatesParser.DISTRIBUTION); writer.writeOpenTag( InverseGaussianDistributionModelParser.INVERSEGAUSSIAN_DISTRIBUTION_MODEL, new Attribute[] { new Attribute.Default<String>( InverseGaussianDistributionModelParser.OFFSET, String.valueOf(data.clockParameterValues[8])) }); writeParameter(InverseGaussianDistributionModelParser.MEAN, PartitionData.clockParameterNames[7] + suffix, 1, String.valueOf(data.clockParameterValues[7]), writer); writeParameter(InverseGaussianDistributionModelParser.STDEV, PartitionData.clockParameterNames[6] + suffix, 1, String.valueOf(data.clockParameterValues[6]), writer); writer.writeCloseTag(InverseGaussianDistributionModelParser.INVERSEGAUSSIAN_DISTRIBUTION_MODEL); writer.writeCloseTag(DiscretizedBranchRatesParser.DISTRIBUTION); numberOfBranches = 2 * (data.createTreeModel().getTaxonCount() - 1); writeParameter(DiscretizedBranchRatesParser.RATE_CATEGORIES, "branchRates.categories" + suffix, (int) numberOfBranches, null, writer); writer.writeCloseTag(DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES); }// END: switch }// END: writeBranchRatesModel private void writeTaxa(Taxa taxa, XMLWriter writer, String suffix) { writer.writeOpenTag(TaxaParser.TAXA, // tagname new Attribute[] { // attributes[] new Attribute.Default<String>(XMLParser.ID, TaxaParser.TAXA + suffix) }); for (int i = 0; i < taxa.getTaxonCount(); i++) { Taxon taxon = taxa.getTaxon(i); writer.writeTag( TaxonParser.TAXON, // tagname new Attribute[] { // attributes[] new Attribute.Default<String>(XMLParser.ID, taxon.getId()) }, true // close ); }// END: i loop writer.writeCloseTag(TaxaParser.TAXA); }// END: writeTaxa private void writeTreeModel( // TreeModel tree, XMLWriter writer, String suffix) { final String treeModelName = TreeModel.TREE_MODEL + suffix; writer.writeTag(TreeModel.TREE_MODEL, new Attribute.Default<String>( XMLParser.ID, treeModelName), false); writer.writeIDref("tree", Utils.TOPOLOGY + suffix); writeParameter(TreeModelParser.ROOT_HEIGHT, treeModelName + "." + TreeModelParser.ROOT_HEIGHT, 1, null, writer); writer.writeOpenTag(TreeModelParser.NODE_HEIGHTS, new Attribute.Default<String>(TreeModelParser.INTERNAL_NODES, "true")); writeParameter(null, treeModelName + "." + "internalNodeHeights", 1, null, writer); 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") }); writeParameter(null, treeModelName + "." + "allInternalNodeHeights", 1, null, writer); writer.writeCloseTag(TreeModelParser.NODE_HEIGHTS); writer.writeCloseTag(TreeModel.TREE_MODEL); }// END: writeTreeModel private void writeReport(XMLWriter writer) { writer.writeOpenTag( Report.REPORT, new Attribute[] { new Attribute.Default<String>( Report.FILENAME, "sequences." + String.valueOf(dataList.outputFormat) .toLowerCase()) }); writer.writeIDref( BeagleSequenceSimulatorParser.BEAGLE_SEQUENCE_SIMULATOR, "simulator"); writer.writeCloseTag(Report.REPORT); }// END: writeReport private void writeSiteRateModel(PartitionData data, XMLWriter writer, int suffix) { writer.writeOpenTag(SiteModel.SITE_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.siteRateModelIdref) }); writer.writeOpenTag(GammaSiteModelParser.SUBSTITUTION_MODEL); int substitutionModelIndex = data.substitutionModelIndex; switch (substitutionModelIndex) { case 0: // HKY writer.writeIDref(NucModelType.HKY.getXMLName(), data.substitutionModelIdref); break; case 1: // GTR writer.writeIDref(GTRParser.GTR_MODEL, data.substitutionModelIdref); break; case 2: // TN93 writer.writeIDref(NucModelType.TN93.getXMLName(), data.substitutionModelIdref); break; case 3: // GY94CodonModel writer.writeIDref(YangCodonModelParser.YANG_CODON_MODEL, data.substitutionModelIdref); break; case 4: // MG94CodonModel writer.writeIDref(MG94CodonModelParser.MUSE_CODON_MODEL, data.substitutionModelIdref); break; case 5: // Blosum62 writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 6: // CPREV writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 7: // Dayhoff writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 8: // FLU writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 9: // JTT writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 10: // LG writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 11: // MTREV writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; case 12: // WAG writer.writeIDref(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, data.substitutionModelIdref); break; }// END: switch writer.writeCloseTag(GammaSiteModelParser.SUBSTITUTION_MODEL); int siteRateModelIndex = data.siteRateModelIndex; switch (siteRateModelIndex) { case 0: // no model // do nothing break; case 1: // GammaSiteRateModel writer.writeOpenTag( GammaSiteModelParser.GAMMA_SHAPE, new Attribute.Default<String>( GammaSiteModelParser.GAMMA_CATEGORIES, String.valueOf((int) data.siteRateModelParameterValues[0]))); //TODO writeParameter(null, "alpha" + suffix, 1, String.valueOf(data.siteRateModelParameterValues[1]), writer); writer.writeCloseTag(GammaSiteModelParser.GAMMA_SHAPE); if (data.siteRateModelParameterValues[2] > 0.0) { writeParameter(GammaSiteModelParser.PROPORTION_INVARIANT, "pInv", 1, String.valueOf(data.siteRateModelParameterValues[2]), writer); } break; }// END: switch writer.writeCloseTag(SiteModel.SITE_MODEL); }// END: writeSiteModel private void writeBranchModel(PartitionData data, XMLWriter writer, String suffix) { int substitutionModelIndex = data.substitutionModelIndex; switch (substitutionModelIndex) { case 0: // HKY writer.writeOpenTag(NucModelType.HKY.getXMLName(), new Attribute[] { new Attribute.Default<String>( XMLParser.ID, data.substitutionModelIdref) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writeParameter(HKYParser.KAPPA, HKYParser.KAPPA + suffix, 1, String.valueOf(data.substitutionParameterValues[0]), writer); writer.writeCloseTag(NucModelType.HKY.getXMLName()); break; case 1: // GTR writer.writeOpenTag(GTRParser.GTR_MODEL, new Attribute[] { new Attribute.Default<String>( XMLParser.ID, data.substitutionModelIdref) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writeParameter(GTRParser.A_TO_C, "ac" + suffix, 1, String.valueOf(data.substitutionParameterValues[1]), writer); writeParameter(GTRParser.A_TO_G, "ag" + suffix, 1, String.valueOf(data.substitutionParameterValues[2]), writer); writeParameter(GTRParser.A_TO_T, "at" + suffix, 1, String.valueOf(data.substitutionParameterValues[3]), writer); writeParameter(GTRParser.C_TO_G, "cg" + suffix, 1, String.valueOf(data.substitutionParameterValues[4]), writer); writeParameter(GTRParser.C_TO_T, "ct" + suffix, 1, String.valueOf(data.substitutionParameterValues[5]), writer); // writeParameter(GTRParser.G_TO_T, "gt" + suffix, 1, // String.valueOf(data.substitutionParameterValues[6]), writer); writer.writeCloseTag(GTRParser.GTR_MODEL); break; case 2: // TN93 writer.writeOpenTag(NucModelType.TN93.getXMLName(), new Attribute[] { new Attribute.Default<String>( XMLParser.ID, data.substitutionModelIdref) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writeParameter(TN93Parser.KAPPA1, TN93Parser.KAPPA1 + suffix, 1, String.valueOf(data.substitutionParameterValues[7]), writer); writeParameter(TN93Parser.KAPPA2, TN93Parser.KAPPA2 + suffix, 1, String.valueOf(data.substitutionParameterValues[8]), writer); writer.writeCloseTag(NucModelType.TN93.getXMLName()); break; case 3: // Yang Codon Model writer.writeOpenTag(YangCodonModelParser.YANG_CODON_MODEL, new Attribute[] { new Attribute.Default<String>( XMLParser.ID, data.substitutionModelIdref) }); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writeParameter(YangCodonModelParser.OMEGA, YangCodonModelParser.OMEGA + suffix, 1, String.valueOf(data.substitutionParameterValues[9]), writer); writeParameter(YangCodonModelParser.KAPPA, YangCodonModelParser.KAPPA + suffix, 1, String.valueOf(data.substitutionParameterValues[10]), writer); writer.writeCloseTag(YangCodonModelParser.YANG_CODON_MODEL); break; case 4: // writer.writeOpenTag(MG94CodonModelParser.MUSE_CODON_MODEL, new Attribute[] { new Attribute.Default<String>( XMLParser.ID, data.substitutionModelIdref) }); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writeParameter(MG94CodonModelParser.ALPHA, MG94CodonModelParser.ALPHA + suffix, 1, String.valueOf(data.substitutionParameterValues[11]), writer); writeParameter(MG94CodonModelParser.BETA, MG94CodonModelParser.BETA + suffix, 1, String.valueOf(data.substitutionParameterValues[12]), writer); writeParameter(MG94CodonModelParser.KAPPA, MG94CodonModelParser.KAPPA + suffix, 1, String.valueOf(data.substitutionParameterValues[13]), writer); writer.writeCloseTag(MG94CodonModelParser.MUSE_CODON_MODEL); break; case 5: // Blosum62 writer.writeOpenTag( EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.substitutionModelIdref), // new Attribute.Default<String>( EmpiricalAminoAcidModelParser.TYPE, AminoAcidModelType.BLOSUM_62.getXMLName()) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writer.writeCloseTag(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL); break; case 6: // CPREV writer.writeOpenTag( EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.substitutionModelIdref), // new Attribute.Default<String>( EmpiricalAminoAcidModelParser.TYPE, AminoAcidModelType.CP_REV_45.getXMLName()) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writer.writeCloseTag(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL); break; case 7: // Dayhoff writer.writeOpenTag( EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.substitutionModelIdref), // new Attribute.Default<String>( EmpiricalAminoAcidModelParser.TYPE, AminoAcidModelType.DAYHOFF.getXMLName()) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writer.writeCloseTag(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL); break; case 8: // FLU writer.writeOpenTag( EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.substitutionModelIdref), // new Attribute.Default<String>( EmpiricalAminoAcidModelParser.TYPE, AminoAcidModelType.FLU.getXMLName()) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writer.writeCloseTag(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL); break; case 9: // JTT writer.writeOpenTag( EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.substitutionModelIdref), // new Attribute.Default<String>( EmpiricalAminoAcidModelParser.TYPE, AminoAcidModelType.JTT.getXMLName()) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writer.writeCloseTag(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL); break; case 10: // LG writer.writeOpenTag( EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.substitutionModelIdref), // new Attribute.Default<String>( EmpiricalAminoAcidModelParser.TYPE, AminoAcidModelType.LG.getXMLName()) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writer.writeCloseTag(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL); break; case 11: // MTREV writer.writeOpenTag( EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.substitutionModelIdref), // new Attribute.Default<String>( EmpiricalAminoAcidModelParser.TYPE, AminoAcidModelType.MT_REV_24.getXMLName()) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writer.writeCloseTag(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL); break; case 12: // WAG writer.writeOpenTag( EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL, new Attribute[] { new Attribute.Default<String>(XMLParser.ID, data.substitutionModelIdref), // new Attribute.Default<String>( EmpiricalAminoAcidModelParser.TYPE, AminoAcidModelType.WAG.getXMLName()) }); writer.writeOpenTag(FrequencyModelParser.FREQUENCIES); writer.writeIDref(FrequencyModelParser.FREQUENCY_MODEL, data.frequencyModelIdref); writer.writeCloseTag(FrequencyModelParser.FREQUENCIES); writer.writeCloseTag(EmpiricalAminoAcidModelParser.EMPIRICAL_AMINO_ACID_MODEL); break; }// END: switch }// END: writeBranchModel private void writeFrequencyModel(PartitionData data, XMLWriter writer) { DataType dataType = null; String frequencies = null; // int dataTypeIndex = data.dataTypeIndex; int frequencyModelIndex = data.frequencyModelIndex; switch (frequencyModelIndex) { case 0: // Nucleotide dataType = data.createDataType(); // dataType = Nucleotides.INSTANCE; frequencies = data.frequencyParameterValues[0] + ""; for (int i = 1; i < 4; i++) { frequencies += " " + data.frequencyParameterValues[i]; } writer.writeOpenTag(FrequencyModelParser.FREQUENCY_MODEL, // tagname new Attribute[] { // attributes[] new Attribute.Default<String>(XMLParser.ID, data.frequencyModelIdref), // id new Attribute.Default<String>(DataType.DATA_TYPE, dataType.getDescription()) // dataType }); writeParameter(FrequencyModelParser.FREQUENCIES, null, dataType.getStateCount(), frequencies, writer); writer.writeCloseTag(FrequencyModelParser.FREQUENCY_MODEL); break; case 1: // Codon dataType = data.createDataType(); // dataType = Codons.UNIVERSAL; frequencies = data.frequencyParameterValues[4] + ""; for (int i = 5; i < 65; i++) { frequencies += " " + data.frequencyParameterValues[i]; } writer.writeOpenTag(FrequencyModelParser.FREQUENCY_MODEL, // tagname new Attribute[] { // attributes[] new Attribute.Default<String>(XMLParser.ID, data.frequencyModelIdref), // id new Attribute.Default<String>(DataType.DATA_TYPE, // dataType.getDescription() Utils.CODON_UNIVERSAL ) // dataType }); writeParameter(FrequencyModelParser.FREQUENCIES, null, dataType.getStateCount(), frequencies, writer); writer.writeCloseTag(FrequencyModelParser.FREQUENCY_MODEL); break; case 2: // Amino acid dataType = data.createDataType(); // dataType = AminoAcids.INSTANCE; frequencies = data.frequencyParameterValues[65] + ""; for (int i = 66; i < 85; i++) { frequencies += " " + data.frequencyParameterValues[i]; } writer.writeOpenTag(FrequencyModelParser.FREQUENCY_MODEL, // tagname new Attribute[] { // attributes[] new Attribute.Default<String>(XMLParser.ID, data.frequencyModelIdref), // id new Attribute.Default<String>(DataType.DATA_TYPE, // dataType.getDescription() AminoAcids.DESCRIPTION ) // dataType }); writeParameter(FrequencyModelParser.FREQUENCIES, null, dataType.getStateCount(), frequencies, writer); writer.writeCloseTag(FrequencyModelParser.FREQUENCY_MODEL); break; }// END: switch }// END: writeFrequencyModel @SuppressWarnings("rawtypes") private void writeParameter(String wrapper, String id, int dimension, String value, XMLWriter writer) { if (wrapper != null) { writer.writeOpenTag(wrapper); } ArrayList<Attribute.Default> attributes = new ArrayList<Attribute.Default>(); if (id != null) { attributes.add(new Attribute.Default<String>(XMLParser.ID, id)); } if (dimension > 1) { attributes.add(new Attribute.Default<String>( ParameterParser.DIMENSION, String.valueOf(dimension))); } if (value != null) { attributes.add(new Attribute.Default<String>(ParameterParser.VALUE, value)); } Attribute[] attrArray = new Attribute[attributes.size()]; for (int i = 0; i < attrArray.length; i++) { attrArray[i] = attributes.get(i); } writer.writeTag(ParameterParser.PARAMETER, attrArray, true); if (wrapper != null) { writer.writeCloseTag(wrapper); } }// END: writeParameter }// END: class