/* * F84DistanceMatrix.java * * Copyright (C) 2002-2006 Alexei Drummond and Andrew Rambaut * * 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 beast.evolution.alignment.distance; import beast.core.Description; import beast.evolution.alignment.Alignment; import beast.evolution.substitutionmodel.Frequencies; /** * compute HKY corrected distance matrix * * @author Andrew Rambaut * @version $Id: F84DistanceMatrix.java,v 1.3 2005/05/24 20:25:56 rambaut Exp $ */ @Description("compute HKY corrected distance") public class F84Distance extends Distance.Base { /** * set the pattern source */ @Override public void setPatterns(Alignment patterns) { super.setPatterns(patterns); Frequencies frequencies = new Frequencies(); try { frequencies.initByName("data", patterns, "estimate", true); } catch (Exception e) { e.printStackTrace(); } double[] freqs = frequencies.getFreqs(); stateCount = dataType.getStateCount(); if (stateCount != 4) { throw new IllegalArgumentException("F84DistanceMatrix must have nucleotide patterns"); } double freqA = freqs[0]; double freqC = freqs[1]; double freqG = freqs[2]; double freqT = freqs[3]; double freqR = freqA + freqG; double freqY = freqC + freqT; constA = ((freqA * freqG) / freqR) + ((freqC * freqT) / freqY); constB = (freqA * freqG) + (freqC * freqT); constC = (freqR * freqY); } /** * Calculate a pairwise distance */ @Override public double pairwiseDistance(int taxon1, int taxon2) { int state1, state2; int n = patterns.getPatternCount(); double weight, distance; double sumTs = 0.0; double sumTv = 0.0; double sumWeight = 0.0; int[] pattern; for (int i = 0; i < n; i++) { pattern = patterns.getPattern(i); state1 = pattern[taxon1]; state2 = pattern[taxon2]; weight = patterns.getPatternWeight(i); if (!dataType.isAmbiguousState(state1) && !dataType.isAmbiguousState(state2) && state1 != state2) { if ((state1 == 0 && state2 == 2) || (state1 == 2 && state2 == 0)) { // it's a transition sumTs += weight; } else { // it's a transversion sumTv += weight; } } sumWeight += weight; } double P = sumTs / sumWeight; double Q = sumTv / sumWeight; double tmp1 = Math.log(1.0 - (P / (2.0 * constA)) - (((constA - constB) * Q) / (2.0 * constA * constC))); double tmp2 = Math.log(1.0 - (Q / (2.0 * constC))); distance = -(2.0 * constA * tmp1) + (2.0 * (constA - constB - constC) * tmp2); if (distance < MAX_DISTANCE) { return distance; } else { return MAX_DISTANCE; } } // // Private stuff // private int stateCount; //used in correction formula private double constA, constB, constC; }