/*
* DolloComponentGenerator.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.components.dollo;
import dr.app.beauti.generator.BaseComponentGenerator;
import dr.app.beauti.options.*;
import dr.app.beauti.util.XMLWriter;
import dr.evolution.datatype.DataType;
import dr.evomodel.branchratemodel.BranchRateModel;
import dr.oldevomodel.sitemodel.GammaSiteModel;
import dr.oldevomodel.sitemodel.SiteModel;
import dr.evomodel.tree.TreeModel;
import dr.oldevomodelxml.MSSD.ALSSiteModelParser;
import dr.oldevomodelxml.MSSD.ALSTreeLikelihoodParser;
import dr.evomodelxml.branchratemodel.DiscretizedBranchRatesParser;
import dr.evomodelxml.branchratemodel.RandomLocalClockModelParser;
import dr.evomodelxml.branchratemodel.StrictClockBranchRatesParser;
import dr.oldevomodelxml.sitemodel.GammaSiteModelParser;
import dr.oldevomodelxml.substmodel.MutationDeathModelParser;
import dr.oldevomodelxml.treelikelihood.TreeLikelihoodParser;
import dr.evoxml.AlignmentParser;
import dr.evoxml.MutationDeathTypeParser;
import dr.evoxml.SitePatternsParser;
import dr.inference.model.ParameterParser;
import dr.util.Attribute;
import dr.xml.XMLParser;
/**
* @author Marc Suchard
* @version $Id$
*/
public class DolloComponentGenerator extends BaseComponentGenerator {
protected DolloComponentGenerator(BeautiOptions options) {
super(options);
}
public boolean usesInsertionPoint(InsertionPoint point) {
DolloComponentOptions component = (DolloComponentOptions) options
.getComponentOptions(DolloComponentOptions.class);
if (!component.isActive()) {
return false;
}
switch (point) {
case AFTER_TAXA:
case AFTER_SUBSTITUTION_MODEL:
case IN_FILE_LOG_PARAMETERS:
// case IN_MCMC_LIKELIHOOD:
// case AFTER_TREE_LIKELIHOOD:
// case IN_OPERATORS:
// case IN_TREES_LOG:
// case AFTER_TREES_LOG:
// case AFTER_MCMC:
return true;
default:
return false;
}
}// END: usesInsertionPoint
protected void generate(final InsertionPoint point, final Object item, final String prefix, final XMLWriter writer) {
DolloComponentOptions component = (DolloComponentOptions) options
.getComponentOptions(DolloComponentOptions.class);
if (!includeStochasticDollo()) {
return;
}
switch (point) {
case AFTER_TAXA:
writeDataType(writer);
break;
case AFTER_SUBSTITUTION_MODEL:
writeDolloSubstitutionModels(writer, component);
break;
// case AFTER_TREE_LIKELIHOOD:
// writeDolloTreeLikelihoods(writer, component);
// break;
case IN_OPERATORS:
break;
// case IN_MCMC_LIKELIHOOD:
// writeDolloTreeLikelihoodReferences(writer);
// break;
case IN_SCREEN_LOG:
writeScreenLogEntries(writer, component);
break;
case IN_FILE_LOG_PARAMETERS:
writeLog(writer, component);
break;
case IN_TREES_LOG:
break;
case AFTER_TREES_LOG:
break;
case AFTER_MCMC:
break;
default:
throw new IllegalArgumentException(
"This insertion point is not implemented for "
+ this.getClass().getName());
}
}// END: generate
private void writeScreenLogEntries(XMLWriter writer, DolloComponentOptions component) {
}
// private void writeDolloTreeLikelihoodReferences(XMLWriter writer) {
//
// for (AbstractPartitionData partition : options.dataPartitions) {
// PartitionSubstitutionModel model = partition.getPartitionSubstitutionModel();
// String prefix = partition.getName();
// if (model.isDolloModel()) {
// writer.writeIDref(ALSTreeLikelihoodParser.LIKE_NAME,
// prefix + ALSTreeLikelihoodParser.LIKE_NAME);
// }
// }
// }
private void writeLog(XMLWriter writer, DolloComponentOptions component) {
for (AbstractPartitionData partition : options.dataPartitions) {
PartitionSubstitutionModel model = partition.getPartitionSubstitutionModel();
if (model.isDolloModel()) {
String prefix = partition.getName() + ".";
writer.writeIDref(ParameterParser.PARAMETER,
component.getOptions().getParameter(prefix + DolloComponentOptions.DEATH_RATE).getName());
}
}
}
private void writeDataType(XMLWriter writer) {
writer.writeOpenTag(MutationDeathTypeParser.MODEL_NAME,
new Attribute.Default<String>(XMLParser.ID, DolloComponentOptions.DATA_NAME));
writer.writeTag(MutationDeathTypeParser.EXTANT,
new Attribute.Default<String>(MutationDeathTypeParser.CODE, "1"), true);
writer.writeTag(MutationDeathTypeParser.STATE,
new Attribute.Default<String>(MutationDeathTypeParser.CODE, "0"), true);
writer.writeTag(MutationDeathTypeParser.AMBIGUITY,
new Attribute.Default<String>(MutationDeathTypeParser.CODE, "-"), true); // Some users use this specification
writer.writeTag(MutationDeathTypeParser.AMBIGUITY,
new Attribute.Default<String>(MutationDeathTypeParser.CODE, "?"), true);
writer.writeCloseTag(MutationDeathTypeParser.MODEL_NAME);
}
private boolean includeStochasticDollo() {
for (AbstractPartitionData partition : options.dataPartitions) {
PartitionSubstitutionModel model = partition.getPartitionSubstitutionModel();
if (model.isDolloModel()) {
return true;
}
}
return false;
}
@Override
protected String getCommentLabel() {
return "Stochastic Dollo";
}
private void writeDolloSubstitutionModels(XMLWriter writer, DolloComponentOptions component) {
// generate tree likelihoods for stochastic Dollo partitions
for (AbstractPartitionData partition : options.dataPartitions) {
PartitionSubstitutionModel model = partition.getPartitionSubstitutionModel();
if (model.isDolloModel()) {
writeDolloSubstitutionModel(partition, writer, component);
writeDolloSiteModel(partition, writer, component);
writeDolloTreeLikelihood(TreeLikelihoodParser.TREE_LIKELIHOOD, -1, partition, writer);
}
}
}
private void writeDolloSubstitutionModel(AbstractPartitionData partition, XMLWriter writer, DolloComponentOptions component) {
String prefix = partition.getName() + ".";
// String prefix = partition.getPrefix(); // TODO Fix
writer.writeOpenTag(MutationDeathModelParser.MD_MODEL,
new Attribute.Default<String>(XMLParser.ID, prefix + DolloComponentOptions.MODEL_NAME ));
writeParameter(prefix + DolloComponentOptions.DEATH_RATE,
component.getOptions().getParameter(prefix + DolloComponentOptions.DEATH_RATE), writer);
writer.writeTag(DataType.DATA_TYPE, new Attribute.Default<String>(XMLParser.IDREF, DolloComponentOptions.DATA_NAME), true);
writer.writeCloseTag(MutationDeathModelParser.MD_MODEL);
writer.write("\n");
}
private void writeDolloSiteModel(AbstractPartitionData partition, XMLWriter writer, DolloComponentOptions components) {
String prefix = partition.getName() + ".";
writer.writeOpenTag(ALSSiteModelParser.ALS_SITE_MODEL,
new Attribute[]{new Attribute.Default<String>(XMLParser.ID, prefix + SiteModel.SITE_MODEL)});
writer.writeOpenTag(GammaSiteModelParser.SUBSTITUTION_MODEL);
writer.writeIDref(MutationDeathModelParser.MD_MODEL, prefix + DolloComponentOptions.MODEL_NAME);
writer.writeCloseTag(GammaSiteModelParser.SUBSTITUTION_MODEL);
PartitionSubstitutionModel model = partition.getPartitionSubstitutionModel();
if (model.hasCodonPartitions()) {
writeParameter(GammaSiteModelParser.RELATIVE_RATE, "mu", model, writer);
}
if (model.isGammaHetero()) {
writer.writeOpenTag(GammaSiteModelParser.GAMMA_SHAPE,
new Attribute.Default<String>(GammaSiteModelParser.GAMMA_CATEGORIES, "" + model.getGammaCategories()));
writeParameter(prefix + "alpha", model, writer);
writer.writeCloseTag(GammaSiteModelParser.GAMMA_SHAPE);
}
if (model.isInvarHetero()) {
writeParameter(GammaSiteModelParser.PROPORTION_INVARIANT, "pInv", model, writer);
}
writer.writeCloseTag(ALSSiteModelParser.ALS_SITE_MODEL);
}
// private void writeDolloTreeLikelihoods(XMLWriter writer, DolloComponentOptions component) {
//
// // generate tree likelihoods for stochastic Dollo partitions
// for (AbstractPartitionData partition : options.dataPartitions) {
// PartitionSubstitutionModel model = partition.getPartitionSubstitutionModel();
// if (model.isDolloModel()) {
// writeDolloTreeLikelihood(ALSTreeLikelihoodParser.LIKE_NAME, -1, partition, writer);
// }
// }
// }
private void writeDolloTreeLikelihood(String id, int num, AbstractPartitionData partition, XMLWriter writer) {
PartitionSubstitutionModel substModel = partition.getPartitionSubstitutionModel();
PartitionTreeModel treeModel = partition.getPartitionTreeModel();
PartitionClockModel clockModel = partition.getPartitionClockModel();
String prefix = partition.getName() + ".";
String oldPrefix = partition.getPrefix(); // TODO Get working
writer.writeComment("Likelihood for tree given a stochastic Dollo model");
writer.writeOpenTag(
ALSTreeLikelihoodParser.LIKE_NAME,
new Attribute[]{
new Attribute.Default<String>(XMLParser.ID, oldPrefix + id),
new Attribute.Default<Boolean>(TreeLikelihoodParser.USE_AMBIGUITIES, true),
new Attribute.Default<Boolean>(ALSTreeLikelihoodParser.INTEGRATE_GAIN_RATE, true)}
);
if (!options.samplePriorOnly) {
writer.writeIDref(SitePatternsParser.PATTERNS, partition.getPrefix() + SitePatternsParser.PATTERNS);
} else {
// We just need to use the dummy alignment
if (partition instanceof PartitionData) {
writer.writeIDref(AlignmentParser.ALIGNMENT, ((PartitionData) partition).getAlignment().getId());
}
}
writer.writeIDref(TreeModel.TREE_MODEL, treeModel.getPrefix() + TreeModel.TREE_MODEL);
writer.writeIDref(GammaSiteModel.SITE_MODEL, prefix + SiteModel.SITE_MODEL);
writer.writeTag(ALSTreeLikelihoodParser.OBSERVATION_PROCESS,
new Attribute.Default<String>(ALSTreeLikelihoodParser.OBSERVATION_TYPE,ALSTreeLikelihoodParser.ANY_TIP),
true);
switch (clockModel.getClockType()) {
case STRICT_CLOCK:
writer.writeIDref(StrictClockBranchRatesParser.STRICT_CLOCK_BRANCH_RATES, clockModel.getPrefix()
+ BranchRateModel.BRANCH_RATES);
break;
case UNCORRELATED:
writer.writeIDref(DiscretizedBranchRatesParser.DISCRETIZED_BRANCH_RATES, options.noDuplicatedPrefix(clockModel.getPrefix(), treeModel.getPrefix())
+ BranchRateModel.BRANCH_RATES);
break;
case RANDOM_LOCAL_CLOCK:
writer.writeIDref(RandomLocalClockModelParser.LOCAL_BRANCH_RATES, clockModel.getPrefix()
+ BranchRateModel.BRANCH_RATES);
break;
case AUTOCORRELATED:
throw new UnsupportedOperationException("Autocorrelated relaxed clock model not implemented yet");
default:
throw new IllegalArgumentException("Unknown clock model");
}
writer.writeCloseTag(ALSTreeLikelihoodParser.LIKE_NAME);
}
}// END: class