/* * StructuredCoalescentLikelihood.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.evomodel.coalescent.structure; import dr.evolution.coalescent.structure.ColouredTreeIntervals; import dr.evolution.coalescent.structure.StructuredCoalescent; import dr.evolution.coalescent.structure.StructuredIntervalList; import dr.evolution.colouring.ColourChangeMatrix; import dr.evomodel.tree.TreeModel; import dr.inference.model.*; import dr.xml.*; import java.util.logging.Logger; /** * A likelihood function for a structered coalescent model * * @author Andrew Rambaut * @author Alexei Drummond * @version $Id: StructuredCoalescentLikelihood.java,v 1.20 2006/09/11 09:33:01 gerton Exp $ */ public class StructuredCoalescentLikelihood extends AbstractModelLikelihood { // PUBLIC STUFF public static final String STRUCTURED_COALESCENT_LIKELIHOOD = "structuredCoalescentLikelihood"; public static final String META_POPULATION_MODEL = "metaPopulationModel"; public static final String MIGRATION_MODEL = "migrationModel"; public static final String POPULATION = "population"; public StructuredCoalescentLikelihood(TreeModel treeModel, MetaPopulationModel metaPopulationModel, ColourSamplerModel colourSamplerModel, MigrationModel migrationModel) { this(STRUCTURED_COALESCENT_LIKELIHOOD, treeModel, metaPopulationModel, colourSamplerModel, migrationModel); } public StructuredCoalescentLikelihood(String name, TreeModel treeModel, MetaPopulationModel metaPopulationModel, ColourSamplerModel colourSamplerModel, MigrationModel migrationModel) { super(name); this.treeModel = treeModel; addModel(treeModel); this.metaPopulationModel = metaPopulationModel; addModel(metaPopulationModel); this.colourSamplerModel = colourSamplerModel; addModel(colourSamplerModel); this.migrationModel = migrationModel; addModel(migrationModel); addStatistic(migrationWaitingTimesStatistic); addStatistic(coalescentWaitingTimeStatistic); } // ************************************************************** // ModelListener IMPLEMENTATION // ************************************************************** protected final void handleModelChangedEvent(Model model, Object object, int index) { if (model == treeModel) { // treeModel has changed so recalculate the intervals } else { // a demographicModel has changed so we don't need to recalculate the intervals } likelihoodKnown = false; } // ************************************************************** // VariableListener IMPLEMENTATION // ************************************************************** protected final void handleVariableChangedEvent(Variable variable, int index, Parameter.ChangeType type) { likelihoodKnown = false; } // ************************************************************** // Model IMPLEMENTATION // ************************************************************** /** * Stores the precalculated state: in this case the intervals */ protected final void storeState() { storedLogLikelihood = logLikelihood; } /** * Restores the precalculated state: that is the intervals of the tree. */ protected final void restoreState() { logLikelihood = storedLogLikelihood; } protected final void acceptState() { } // nothing to do // ************************************************************** // Likelihood IMPLEMENTATION // ************************************************************** public final Model getModel() { return this; } public final double getLogLikelihood() { likelihoodKnown = false; if (!likelihoodKnown) { logLikelihood = calculateLogLikelihood(); likelihoodKnown = true; } return logLikelihood; } public final void makeDirty() { likelihoodKnown = false; } /** * Calculates the log likelihood of this set of coalescent intervals, * given a demographic model. */ public double calculateLogLikelihood() { // make intervals StructuredIntervalList list = new ColouredTreeIntervals(treeModel, colourSamplerModel.getTreeColouring()); ColourChangeMatrix mm = migrationModel.getMigrationMatrix(); StructuredCoalescent sc = new StructuredCoalescent(); double logL = sc.calculateLogLikelihood(colourSamplerModel.getTreeColouring(), list, mm, metaPopulationModel); return logL; } // **************************************************************** // Private and protected stuff // **************************************************************** private final Statistic migrationWaitingTimesStatistic = new Statistic.Abstract() { public String getStatisticName() { return "migrationWaitingTimes"; } public int getDimension() { return metaPopulationModel.getPopulationCount(); } public double getStatisticValue(int dim) { double[] migrationRates = migrationModel.getMigrationRates(0); return 1.0 / migrationRates[dim]; } }; private final Statistic coalescentWaitingTimeStatistic = new Statistic.Abstract() { public String getStatisticName() { return "coalescentWaitingTime"; } public int getDimension() { return 1; } public double getStatisticValue(int dim) { double[] popSizes = metaPopulationModel.getPopulationSizes(0); int[] counts = colourSamplerModel.getLeafColourCounts(); double sum = 0.0; for (int i = 0; i < popSizes.length; i++) { sum += ((double) counts[i]) / popSizes[i]; } return 1.0 / sum; } }; public static XMLObjectParser PARSER = new AbstractXMLObjectParser() { public String getParserName() { return STRUCTURED_COALESCENT_LIKELIHOOD; } public Object parseXMLObject(XMLObject xo) throws XMLParseException { TreeModel treeModel = (TreeModel) xo.getChild(TreeModel.class); ColourSamplerModel colourSamplerModel = (ColourSamplerModel) xo.getChild(ColourSamplerModel.class); MigrationModel migrationModel = (MigrationModel) xo.getChild(MigrationModel.class); MetaPopulationModel metaPopulationModel = (MetaPopulationModel) xo.getChild(MetaPopulationModel.class); StructuredCoalescentLikelihood likelihood = new StructuredCoalescentLikelihood(treeModel, metaPopulationModel, colourSamplerModel, migrationModel); Logger.getLogger("dr.evomodel").info("Creating structured coalescent tree prior."); return likelihood; } //************************************************************************ // AbstractXMLObjectParser implementation //************************************************************************ public String getParserDescription() { return "This element represents a likelihood function for transmission."; } public Class getReturnType() { return StructuredCoalescentLikelihood.class; } public XMLSyntaxRule[] getSyntaxRules() { return rules; } private final XMLSyntaxRule[] rules = { new ElementRule(TreeModel.class, "The tree."), new ElementRule(ColourSamplerModel.class, "The colour sampler model."), new ElementRule(MigrationModel.class, "The migration model."), new ElementRule(MetaPopulationModel.class, "The meta-population model."), }; }; private TreeModel treeModel = null; private MetaPopulationModel metaPopulationModel = null; private ColourSamplerModel colourSamplerModel = null; private MigrationModel migrationModel = null; private boolean likelihoodKnown = false; private double logLikelihood; private double storedLogLikelihood; }