/* * EpochBranchModel.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.branchmodel; import dr.evomodel.substmodel.FrequencyModel; import dr.evomodel.substmodel.SubstitutionModel; import dr.evolution.tree.NodeRef; import dr.evomodel.tree.TreeModel; import dr.inference.model.AbstractModel; import dr.inference.model.Model; import dr.inference.model.Parameter; import dr.inference.model.Variable; import dr.util.Author; import dr.util.Citable; import dr.util.Citation; import java.util.*; /** * @author Filip Bielejec * @author Andrew Rambaut * @author Marc A. Suchard * @version $Id$ */ @SuppressWarnings("serial") public class EpochBranchModel extends AbstractModel implements BranchModel, Citable { public static final String EPOCH_BRANCH_MODEL = "EpochBranchModel"; public EpochBranchModel(TreeModel tree, List<SubstitutionModel> substitutionModels, Parameter epochTimes) { super(EPOCH_BRANCH_MODEL); this.substitutionModels = substitutionModels; if (substitutionModels == null || substitutionModels.size() == 0) { throw new IllegalArgumentException("EpochBranchModel must be provided with at least one substitution model"); } this.epochTimes = epochTimes; this.tree = tree; for (SubstitutionModel model : substitutionModels) { addModel(model); } addModel(tree); addVariable(epochTimes); }// END: Constructor @Override public Mapping getBranchModelMapping(NodeRef node) { int nModels = substitutionModels.size(); int epochCount = nModels - 1; double[] transitionTimes = epochTimes.getParameterValues(); double parentHeight = tree.getNodeHeight(tree.getParent(node)); double nodeHeight = tree.getNodeHeight(node); List<Double> weightList = new ArrayList<Double>(); List<Integer> orderList = new ArrayList<Integer>(); // find the epoch that the node height is in... int epoch = 0; while (epoch < epochCount && nodeHeight >= transitionTimes[epoch]) { epoch ++; } double currentHeight = nodeHeight; // find the epoch that the parent height is in... while (epoch < epochCount && parentHeight >= transitionTimes[epoch]) { weightList.add( transitionTimes[epoch] - currentHeight ); orderList.add(epoch); currentHeight = transitionTimes[epoch]; epoch ++; } weightList.add( parentHeight - currentHeight ); orderList.add(epoch); if (orderList.size() == 0) { throw new RuntimeException("EpochBranchModel failed to give a valid mapping"); } final int[] order = new int[orderList.size()]; final double[] weights = new double[weightList.size()]; for (int i = 0; i < orderList.size(); i++) { order[i] = orderList.get(i); weights[i] = weightList.get(i); } return new Mapping() { @Override public int[] getOrder() { return order; } @Override public double[] getWeights() { return weights; } }; }// END: getBranchModelMapping @Override public boolean requiresMatrixConvolution() { return true; } @Override public List<SubstitutionModel> getSubstitutionModels() { return substitutionModels; } @Override public SubstitutionModel getRootSubstitutionModel() { return substitutionModels.get(substitutionModels.size() - 1); } public FrequencyModel getRootFrequencyModel() { return getRootSubstitutionModel().getFrequencyModel(); } protected void handleModelChangedEvent(Model model, Object object, int index) { fireModelChanged(); }// END: handleModelChangedEvent @SuppressWarnings("rawtypes") protected void handleVariableChangedEvent(Variable variable, int index, Parameter.ChangeType type) { }// END: handleVariableChangedEvent protected void storeState() { }// END: storeState protected void restoreState() { }// END: restoreState protected void acceptState() { }// END: acceptState @Override public Citation.Category getCategory() { return Citation.Category.SUBSTITUTION_MODELS; } @Override public String getDescription() { return "Epoch Branch model"; } public List<Citation> getCitations() { return Arrays.asList( new Citation(new Author[]{new Author("F", "Bielejec"), new Author("P", "Lemey"), new Author("G", "Baele"), new Author("A", "Rambaut"), new Author("MA", "Suchard")}, Citation.Status.IN_PREPARATION)); }// END: getCitations private final TreeModel tree; private final List<SubstitutionModel> substitutionModels; private final Parameter epochTimes; }// END: class