/* * File SubstitutionModel.java * * Copyright (C) 2010 Remco Bouckaert remco@cs.auckland.ac.nz * * This file is part of BEAST2. * 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 beast.evolution.substitutionmodel; import beast.core.CalculationNode; import beast.core.Description; import beast.core.Input; import beast.core.Input.Validate; import beast.evolution.datatype.DataType; import beast.evolution.tree.Node; @Description("Specifies substitution model from which a transition probability matrix for a given " + "distance can be obtained.") public interface SubstitutionModel { /** * get the complete transition probability matrix for the given distance * determined as (startTime-endTime)*rate * * @param node tree node for which to calculate the probabilities * @param startTime * @param endTime we assume start time is larger than end time * @param rate rate, includes gamma rates and branch rates * @param matrix an array to store the matrix which represents the transition probability * matrix in the form of an array. So, matrix must be of size n*n where n is number of states. */ void getTransitionProbabilities(Node node, double startTime, double endTime, double rate, double[] matrix); /** * @param node In most cases, the rate matrix is independent of the tree, but if it changes * throughout a tree, the node can provide this information. * @return instantaneous rate matrix Q, where Q is flattened into an array * This is a square matrix, where rows add to zero, or null when no rate * matrix is available. */ double[] getRateMatrix(Node node); /** * return frequencies for root distribution * */ double[] getFrequencies(); public int getStateCount(); /** * This function returns the Eigen decomposition of the instantaneous rate matrix if available. * Such Eigen decomposition may not be available because the substitution model changes over time, * for example, when one HKY model applies for some time t less than threshold time T while a GTR * model applies when t >= T. * * @param node In most cases, the rate matrix, and thus the Eigen decomposition, is independent of the tree, * but if it changes throughout a tree, the node can provide this information. * @return the EigenDecomposition, null if not available */ EigenDecomposition getEigenDecomposition(Node node); /** * @return whether substitution model can return complex diagonalizations * If so, for example, a treelikelihood needs to be able to deal with this. */ boolean canReturnComplexDiagonalization(); /** * return true if this substitution model is suitable for the data type */ boolean canHandleDataType(DataType dataType); /** * basic implementation of a SubstitutionModel bringing together relevant super class* */ @Description(value = "Base implementation of a substitution model.", isInheritable = false) public abstract class Base extends CalculationNode implements SubstitutionModel { final public Input<Frequencies> frequenciesInput = new Input<>("frequencies", "substitution model equilibrium state frequencies", Validate.REQUIRED); /** * shadows frequencies, or can be set by subst model * */ protected Frequencies frequencies; /** * number of states * */ protected int nrOfStates; @Override public void initAndValidate() { frequencies = frequenciesInput.get(); } @Override public double[] getFrequencies() { return frequencies.getFreqs(); } @Override public int getStateCount() { return nrOfStates; } @Override public boolean canReturnComplexDiagonalization() { return false; } @Override public double[] getRateMatrix(Node node) { return null; } } // class Base /** * basic implementation of a SubstitutionModel bringing together relevant super class* */ @Description(value = "Base implementation of a nucleotide substitution model.", isInheritable = false) public abstract class NucleotideBase extends Base { public double freqA, freqC, freqG, freqT, // A+G freqR, // C+T freqY; @Override public int getStateCount() { assert nrOfStates == 4; return nrOfStates; } protected void calculateFreqRY() { double[] freqs = frequencies.getFreqs(); freqA = freqs[0]; freqC = freqs[1]; freqG = freqs[2]; freqT = freqs[3]; freqR = freqA + freqG; freqY = freqC + freqT; } } // class NucleotideBase } // class SubstitutionModel